CI/CD 기본은 알겠는데, 파이프라인을 어떻게 설계하고, 배포 전략은 서비스 규모에 따라 어떻게 달라질까요?

이게 뭔가요?

CI/CD 심화는 기본 파이프라인을 넘어, 멀티 스테이지 빌드, 아티팩트 관리, 고급 배포 전략, GitOps까지 포괄하는 영역입니다. 서비스가 커지면 "빌드하고 배포한다"라는 단순한 흐름으로는 부족합니다.

왜 필요한가요?

  • 팀이 커지면 파이프라인 충돌과 병목이 발생
  • 프로덕션 배포의 위험을 최소화하는 전략이 필요
  • 롤백, 관찰, 점진적 적용 같은 안전 장치가 필수

파이프라인 설계 패턴

멀티 스테이지 파이프라인

YAML
# GitHub Actions: 단계별 파이프라인
name: Production Pipeline

on:
  push:
    branches: [main]

jobs:
  # 1단계: 빌드 + 단위 테스트
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build & Unit Test
        run: ./gradlew build
      - name: Upload Artifact
        uses: actions/upload-artifact@v4
        with:
          name: app-jar
          path: build/libs/*.jar

  # 2단계: 통합 테스트 (DB, 외부 서비스 포함)
  integration-test:
    needs: build
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_DB: test
          POSTGRES_PASSWORD: test
    steps:
      - uses: actions/checkout@v4
      - name: Integration Test
        run: ./gradlew integrationTest

  # 3단계: 보안 스캔
  security:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: SAST Scan
        uses: github/codeql-action/analyze@v3

  # 4단계: 스테이징 배포
  deploy-staging:
    needs: [integration-test, security]
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Deploy to Staging
        run: ./deploy.sh staging

  # 5단계: 프로덕션 배포 (수동 승인)
  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment:
      name: production
      # GitHub UI에서 수동 승인 필요
    steps:
      - name: Deploy to Production
        run: ./deploy.sh production

병렬 실행으로 시간 단축

PLAINTEXT
직렬 실행: Build → Unit Test → Integration Test → Security → Deploy
           (15분)    (3분)        (5분)           (2분)     (3분) = 28분

병렬 실행:
Build (15분) ─┬→ Unit Test (3분) ──┐
              ├→ Integration Test ─┤→ Deploy (3분) = 20분
              └→ Security (2분) ──┘

통합 테스트와 보안 스캔처럼 독립적인 작업은 병렬로 실행해서 전체 시간을 줄입니다.

아티팩트 관리

PLAINTEXT
빌드 결과물(아티팩트)을 버전 관리하는 것이 핵심

소스 코드 → 빌드 → 아티팩트(Docker 이미지) → 배포

이미지 태깅 전략:
✗ latest       → 어떤 버전인지 알 수 없음
✓ v1.2.3       → 시맨틱 버전
✓ abc123f      → Git 커밋 해시
✓ 2027.01.31-1 → 날짜 + 빌드 번호
YAML
# Docker 이미지 빌드 + 레지스트리 푸시
- name: Build & Push Docker Image
  run: |
    docker build -t myapp:${{ github.sha }} .
    docker tag myapp:${{ github.sha }} registry/myapp:${{ github.sha }}
    docker push registry/myapp:${{ github.sha }}

배포 전략 심화

롤링 배포 (Rolling Update)

PLAINTEXT
시작: [v1] [v1] [v1] [v1]

1단계: [v2] [v1] [v1] [v1]   ← 하나씩 교체
2단계: [v2] [v2] [v1] [v1]
3단계: [v2] [v2] [v2] [v1]
완료:  [v2] [v2] [v2] [v2]
YAML
# Kubernetes 롤링 업데이트 설정
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # 최대 1개 추가 생성
      maxUnavailable: 0  # 0개까지 사용 불가 허용 (무중단)
  • 장점: 추가 인프라 불필요, 점진적 교체
  • 단점: v1과 v2가 동시에 존재하는 과도기 발생, 롤백 시간이 김

블루-그린 배포 심화

PLAINTEXT
1. 현재: Blue(v1)에 트래픽, Green은 유휴
2. Green에 v2 배포 및 테스트
3. 트래픽을 Green으로 전환 (로드밸런서 설정 변경)
4. 문제 없으면 Blue를 정리

롤백: 로드밸런서를 다시 Blue로 전환 (수 초)
YAML
# Kubernetes: Service의 selector를 변경하여 전환
apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
    version: green  # blue → green으로 변경하면 트래픽 전환
  • 장점: 즉시 롤백 가능, 과도기 없음
  • 단점: 인프라 2배 필요, DB 스키마 변경이 있으면 복잡

카나리 배포 심화

PLAINTEXT
1단계: 5% 트래픽을 v2로
  [v1] [v1] [v1] [v1] [v1] [v1] [v1] [v1] [v1] [v2]
  → 에러율, 응답시간 모니터링

2단계: 25% → 50% → 75% → 100%
  → 각 단계에서 메트릭 확인 후 진행

자동 롤백 조건:
  - 에러율 > 1%
  - P99 응답시간 > 500ms
  - 5xx 응답 비율 증가
YAML
# Argo Rollouts: 자동화된 카나리 배포
apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
  strategy:
    canary:
      steps:
        - setWeight: 5
        - pause: { duration: 5m }    # 5분 관찰
        - setWeight: 25
        - pause: { duration: 10m }   # 10분 관찰
        - setWeight: 50
        - pause: { duration: 10m }
        - setWeight: 100
      analysis:
        templates:
          - templateName: success-rate
        startingStep: 1

배포 전략 비교

구분롤링블루-그린카나리
추가 인프라최소2배소량
롤백 속도느림즉시빠름
위험도중간낮음가장 낮음
복잡도낮음중간높음
과도기있음없음있음 (제어됨)
적합한 규모소규모중규모대규모

GitOps

Git 저장소를 배포의 Single Source of Truth로 사용하는 방식입니다.

PLAINTEXT
전통적인 CI/CD:
  코드 푸시 → CI 빌드 → CD가 직접 kubectl apply

GitOps:
  코드 푸시 → CI 빌드 → 매니페스트 저장소 업데이트
  ArgoCD/Flux가 매니페스트 저장소를 감시 → 클러스터에 자동 동기화

장점:
- Git 히스토리 = 배포 히스토리
- git revert = 롤백
- 선언적 상태 관리 (현재 상태 vs 원하는 상태 비교)

자주 헷갈리는 포인트

  1. "카나리와 A/B 테스트는 같다" — 카나리는 새 버전의 안정성 검증이 목적이고, A/B 테스트는 비즈니스 메트릭(전환율 등) 비교가 목적입니다. 기술적으로는 비슷하지만 목적이 다릅니다.

  2. "블루-그린은 항상 좋다" — DB 스키마 변경이 동반되면 v1과 v2가 같은 DB를 공유하기 때문에 하위 호환성 문제가 생깁니다. Expand-Contract 마이그레이션과 함께 사용해야 합니다.

  3. "GitOps는 GitHub Actions다" — GitHub Actions는 CI 도구이고, GitOps는 배포 철학입니다. ArgoCD, Flux 같은 도구가 GitOps를 구현합니다.

정리

  • 파이프라인은 독립적인 작업을 병렬로 실행하여 전체 시간을 단축
  • 아티팩트는 커밋 해시나 시맨틱 버전으로 태깅하고, latest는 지양
  • 롤링(간단) → 블루-그린(안전) → 카나리(가장 안전) 순으로 복잡도와 안전도 증가
  • 카나리 배포는 자동 롤백 조건(에러율, 응답시간)을 미리 정의해야 효과적
  • GitOps로 Git 저장소를 배포의 유일한 출처로 관리하면 추적성과 롤백이 쉬워짐
댓글 로딩 중...