2 min read
Blue-Green + DB 마이그레이션 안전 패턴
애플리케이션 전환과 스키마 변경을 분리해 다운타임 위험을 줄이는 단계별 전략

도입
애플리케이션은 Blue-Green으로 손쉽게 전환할 수 있지만 데이터베이스는 단순 스위치가 불가능하다. 스키마 변경과 데이터 변경이 함께 일어나면 롤백 전략이 없다면 배포 성공 후에도 서비스가 중단될 수 있다. 이 글은 DB 마이그레이션 안전성을 확보하기 위한 expand/contract 패턴과 전환 체크포인트를 다룬다.

문제 정의
DB 동반 배포에서 장애가 반복되는 이유는 코드 전환과 데이터 전환을 분리하지 않기 때문이다.
- 파괴적 스키마 변경을 먼저 적용해 이전 버전 앱이 즉시 깨진다.
- 백필 작업 진행률을 모른 채 트래픽을 전환해 데이터 누락이 발생한다.
- 롤백 시점에 양방향 호환이 없어 복구 시간이 길어진다.
해결 전략은 expand -> dual-write -> cutover -> contract 순서를 강제하는 것이다. 순서를 어기면 안전성을 보장하기 어렵다.
핵심 개념
| 관점 | 설계 기준 | 검증 포인트 |
|---|---|---|
| 스키마 단계 | 호환 가능한 컬럼 추가 | 구버전 앱 동작 여부 |
| 데이터 단계 | 백필 + 검증 리포트 | NULL/불일치 건수 |
| 전환 단계 | 읽기/쓰기 경로 분리 전환 | 전환 직후 오류율 |
| 정리 단계 | 구 컬럼 제거 시점 통제 | rollback 가능 시간 |
Blue-Green과 DB 마이그레이션을 하나의 배포 파이프라인으로 엮되, 데이터 단계는 독립적으로 모니터링해야 한다.
코드 예시 1: Expand 마이그레이션
ALTER TABLE orders
ADD COLUMN payment_status_v2 TEXT;
CREATE INDEX CONCURRENTLY idx_orders_payment_status_v2
ON orders (payment_status_v2);
-- 구버전 호환을 위해 기존 컬럼 유지
COMMENT ON COLUMN orders.payment_status_v2 IS 'new status field for v2 rollout';
코드 예시 2: Dual-write 애플리케이션 코드
export async function updatePaymentStatus(orderId: string, status: string) {
await db.tx(async (trx) => {
await trx.query(
"UPDATE orders SET payment_status = $2, payment_status_v2 = $2 WHERE id = $1",
[orderId, status],
);
});
}
아키텍처 흐름
Mermaid diagram rendering...
트레이드오프
- dual-write는 안전하지만 쓰기 경로 복잡도와 부하가 증가한다.
- expand/contract 기간을 길게 잡으면 리스크는 낮지만 개발 속도가 느려질 수 있다.
- 전환 체크를 자동화하면 품질이 올라가지만 초기 파이프라인 구축 비용이 필요하다.
정리
Blue-Green 환경에서 DB 안전성은 순서 관리가 핵심이다. 스키마 호환, 백필 검증, 단계적 컷오버를 분리하면 장애 반경을 크게 줄일 수 있다.
이미지 출처
- Cover: source link
- License: CC BY-SA 3.0 / Author: Robert.Harker
- Note: Wikimedia Commons 무료 라이선스 이미지를 다운로드 후 1600px 기준 JPG로 최적화했습니다.