배경 및 목표
수시 채용 데이터 구조를 공채와 호환되도록 변경해야 했습니다. 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건 |
| 마이그레이션 중 신규 요청 | 모두 정상 처리 |
모니터링
- 듀얼라이트 구간에서 신규/구 구조 적재 정합성(양쪽 건수 일치)을 관측한다.
- 배치 마이그레이션 진행률·실패 건수를 관측한다.