Zero-Downtime Deployment: 무중단 배포 전략 완벽 가이드

서비스 규모가 커지면서 "배포 = 점검"이라는 공식은 더 이상 통하지 않습니다. 사용자들은 24시간 서비스를 기대하고, 잠깐의 다운타임도 매출 손실과 사용자 이탈로 이어집니다. 저희 팀은 최근 Zero-Downtime Deployment를 목표로 Blue-Green, Rolling, Canary 배포 전략을 모두 검토하고 실제 운영 환경에 적용했습니다.


 

zero downtime

 


왜 무중단 배포가 필요한가?

우리 서비스의 경우, 1분 다운타임의 비용을 계산해 보았습니다:

  • 일평균 트래픽: 50만 요청
  • 분당 평균 요청: 약 350건
  • 평균 전환율: 2.5%
  • 평균 객단가: 35,000원
  • 1분 다운타임 예상 손실: 약 30만원

한 달에 4번 배포하고, 매번 5분씩 점검한다면 월 600만원의 기회비용이 발생합니다. 이런 숫자를 경영진에게 보여주니 무중단 배포 도입이 바로 승인되었습니다.

1. Blue-Green Deployment

Blue-Green Deployment는 현재 운영 환경(Blue)과 새 버전 환경(Green)을 동시에 운영하는 방식입니다. 로드밸런서의 트래픽 라우팅만 전환하면 즉시 새 버전으로 이동합니다.

구현 방법 (AWS ALB 기준)

TERRAFORM
# 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 설정 예시

YAML
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
# 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 배포 파이프라인

  1. 5% 배포: 내부 QA 팀 대상, 1시간 모니터링
  2. 25% 배포: 일반 사용자 일부, 에러율/지연시간 확인
  3. 50% 배포: 비즈니스 메트릭(전환율, 이탈률) 확인
  4. 100% 배포: 전체 전환

각 단계에서 자동화된 롤백 조건을 설정했습니다:

YAML
# 자동 롤백 조건 (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로 즉시 대응)

무중단 배포는 단순히 기술적 도전이 아니라, 더 빠르고 안전하게 가치를 전달하기 위한 필수 역량입니다.