배경 및 목표

수시 채용 데이터 구조를 공채와 호환되도록 변경해야 했습니다. 3,000+ 기업이 실시간으로 사용하는 서비스여서, 마이그레이션 중에도 서비스가 정상적으로 동작해야 했습니다. 단순 배치 마이그레이션으로는 N시간의 데이터 공백이 불가피했습니다.

sequenceDiagram
    participant M as 마이그레이션
    participant S as 서비스
    participant DB as DB
    Note over M,DB: ❌ 단순 배치 마이그레이션
    M->>DB: 기존 데이터 → 신규 구조 (N시간)
    Note over S,DB: 그 사이 신규 요청
    S->>DB: 구버전 데이터로 적재 ❌
    Note over S,DB: 정규 배포 후
    S->>DB: 구버전 데이터 사용 → 장애!

목표

  • 3,000+ 기업이 실시간 사용하는 서비스를 중단 없이 데이터 구조로 전환한다.
  • 마이그레이션 중 신규 요청도 손실 없이 신규 구조에 반영한다.

해결 방법과 해결 후보군

1. 듀얼라이트 전략 선택

“서비스를 잠시 내리고 마이그레이션하면 간단하다”는 유혹이 있었지만, 3,000+ 기업 서비스에서 중단은 옵션이 아니었습니다. 마이그레이션 동안 들어오는 신규 요청도 양쪽 구조에 동시 적재하는 듀얼라이트 방식이 유일한 무중단 방법이라고 판단했습니다.

2. 3단계 전환 프로세스

graph LR
    subgraph step1["1단계: 듀얼라이트 배포"]
        API --> OLD["기존 구조 저장"]
        API --> NEW["신규 구조 저장"]
    end
    subgraph step2["2단계: 배치 마이그레이션"]
        M["기존 데이터 → 신규 구조"]
    end
    subgraph step3["3단계: 정규 배포"]
        N["신규 구조 기반 전환"]
    end
    step1 --> step2 --> step3

1단계: 듀얼라이트 배포: 모든 API에서 기존+신규 데이터 구조에 동시 적재하는 코드를 배포했습니다. 이 시점부터 신규 요청은 양쪽 모두에 기록됩니다. API가 40개 이상이어서, 누락 방지를 위해 각 API별 체크리스트를 만들어 하나씩 검증했습니다.

듀얼라이트를 구현할 때 핵심은 기존 트랜잭션에 신규 저장 로직을 함께 묶는 것입니다. 하나의 트랜잭션 안에서 양쪽에 저장하므로, 한쪽만 실패하는 상황은 발생하지 않습니다.

@Transactional
fun process(request: Request) {
    // 기존 구조에 저장 (기존 로직 유지)
    legacyRepository.save(request.toLegacyEntity())
    
    // 신규 구조에도 동시 저장 (듀얼라이트)
    newStructureRepository.save(request.toNewEntity())
}

2단계: 배치 마이그레이션: 듀얼라이트가 동작하는 상태에서 기존 데이터를 Spring Batch로 신규 구조로 변환했습니다. 이 과정에서 1단계가 이미 신규 요청을 신규 구조에 적재하고 있으므로, 데이터 공백이 발생하지 않습니다.

3단계: 정규 배포: 마이그레이션 완료 후 신규 구조 기반으로 전환하고, 기존 적재 로직을 제거했습니다. API 버저닝을 활용하여 클라이언트 호출을 v2로 전환하면 완료됩니다.

3. 듀얼라이트가 필요한 이유

graph TB
    subgraph without["❌ 듀얼라이트 없이"]
        W1["마이그레이션 중 신규 요청"] --> W2["구버전만 적재"]
        W2 --> W3["정규 배포 후 장애"]
    end
    subgraph with["✅ 듀얼라이트 적용"]
        D1["마이그레이션 중 신규 요청"] --> D2["구버전+신버전 동시 적재"]
        D2 --> D3["정규 배포 후 정상"]
    end
시나리오듀얼라이트 없음듀얼라이트 적용
마이그레이션 중 신규 요청구버전만 적재양쪽 모두 적재
정규 배포 후장애 발생정상 동작
서비스 중단필요할 수 있음불필요

결과

지표결과
서비스 중단0분
데이터 손실0건
마이그레이션 중 신규 요청모두 정상 처리

모니터링

  • 듀얼라이트 구간에서 신규/구 구조 적재 정합성(양쪽 건수 일치)을 관측한다.
  • 배치 마이그레이션 진행률·실패 건수를 관측한다.