Zero-Downtime Deployment: 무중단 배포 전략 완벽 가이드
서비스 규모가 커지면서 "배포 = 점검"이라는 공식은 더 이상 통하지 않습니다. 사용자들은 24시간 서비스를 기대하고, 잠깐의 다운타임도 매출 손실과 사용자 이탈로 이어집니다. 저희 팀은 최근 Zero-Downtime Deployment를 목표로 Blue-Green, Rolling, Canary 배포 전략을 모두 검토하고 실제 운영 환경에 적용했습니다.
왜 무중단 배포가 필요한가?
우리 서비스의 경우, 1분 다운타임의 비용을 계산해 보았습니다:
- 일평균 트래픽: 50만 요청
- 분당 평균 요청: 약 350건
- 평균 전환율: 2.5%
- 평균 객단가: 35,000원
- 1분 다운타임 예상 손실: 약 30만원
한 달에 4번 배포하고, 매번 5분씩 점검한다면 월 600만원의 기회비용이 발생합니다. 이런 숫자를 경영진에게 보여주니 무중단 배포 도입이 바로 승인되었습니다.
1. Blue-Green Deployment
Blue-Green Deployment는 현재 운영 환경(Blue)과 새 버전 환경(Green)을 동시에 운영하는 방식입니다. 로드밸런서의 트래픽 라우팅만 전환하면 즉시 새 버전으로 이동합니다.
구현 방법 (AWS ALB 기준)
# Terraform으로 Blue-Green 타겟 그룹 설정
resource "aws_lb_target_group" "blue" {
name = "app-blue"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
health_check {
path = "/health"
healthy_threshold = 2
unhealthy_threshold = 3
}
}
resource "aws_lb_target_group" "green" {
name = "app-green"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
health_check {
path = "/health"
healthy_threshold = 2
unhealthy_threshold = 3
}
}
# 리스너 룰로 트래픽 전환
resource "aws_lb_listener_rule" "main" {
listener_arn = aws_lb_listener.main.arn
action {
type = "forward"
target_group_arn = var.active_color == "blue" ?
aws_lb_target_group.blue.arn :
aws_lb_target_group.green.arn
}
}장점
- 즉시 롤백 가능: 문제 발생 시 ALB 타겟만 전환하면 됩니다
- 테스트 환경 확보: Green 환경에서 실제 트래픽 없이 테스트 가능
- 구조가 단순: 이해하기 쉽고 디버깅이 용이합니다
단점
- 리소스 2배 필요: 상시 두 환경을 유지해야 합니다
- DB 마이그레이션 복잡: 스키마 변경 시 양쪽 호환성 유지 필요
2. Rolling Deployment
Rolling Deployment는 서버 그룹을 단계적으로 새 버전으로 교체하는 방식입니다. Kubernetes의 기본 배포 전략이기도 합니다.
Kubernetes 설정 예시
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 6
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # 동시에 추가 생성할 Pod 수
maxUnavailable: 1 # 동시에 종료 가능한 Pod 수
template:
spec:
containers:
- name: app
image: my-app:v2.0
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5장점
- 리소스 효율적: 추가 인프라 없이 점진적 교체
- 점진적 배포: 문제 발생 시 일부만 영향
단점
- 롤백 시간 소요: 전체 롤백에 시간이 걸립니다
- 버전 혼재: 배포 중 구버전/신버전 동시 존재
3. Canary Deployment
Canary Deployment는 소수 사용자에게 새 버전을 먼저 배포하고 점진적으로 확대하는 전략입니다. 저희 팀이 최종 선택한 방식입니다.
Nginx를 활용한 가중치 기반 라우팅
# nginx.conf
upstream backend {
server app-stable:8080 weight=95; # 안정 버전 95%
server app-canary:8080 weight=5; # 카나리 버전 5%
}
# 특정 헤더로 카나리 강제 라우팅 (테스트용)
map $http_x_canary $backend_pool {
"true" canary;
default production;
}우리 팀의 Canary 배포 파이프라인
- 5% 배포: 내부 QA 팀 대상, 1시간 모니터링
- 25% 배포: 일반 사용자 일부, 에러율/지연시간 확인
- 50% 배포: 비즈니스 메트릭(전환율, 이탈률) 확인
- 100% 배포: 전체 전환
각 단계에서 자동화된 롤백 조건을 설정했습니다:
# 자동 롤백 조건 (Prometheus Alert)
- alert: CanaryHighErrorRate
expr: |
sum(rate(http_requests_total{version="canary",status=~"5.."}[5m]))
/ sum(rate(http_requests_total{version="canary"}[5m])) > 0.05
for: 2m
annotations:
action: "auto_rollback"최종 선택: Canary + Feature Flags
저희는 Canary Deployment와 Feature Flags를 결합한 방식을 채택했습니다. LaunchDarkly를 사용하여 기능 단위로 ON/OFF할 수 있게 구성했습니다.
이 조합의 장점:
- 배포와 기능 릴리스를 분리
- 문제 발생 시 전체 롤백 없이 해당 기능만 OFF
- A/B 테스트와 자연스럽게 연계
도입 성과
무중단 배포 도입 후 6개월간의 성과:
- 배포 빈도: 월 4회 → 주 3회 (300% 증가)
- 다운타임: 월 20분 → 0분
- 롤백 횟수: 월 2회 → 월 0.5회 (Canary 단계에서 조기 발견)
- MTTR: 15분 → 2분 (Feature Flag OFF로 즉시 대응)
무중단 배포는 단순히 기술적 도전이 아니라, 더 빠르고 안전하게 가치를 전달하기 위한 필수 역량입니다.