🔁
배포 자동화 가이드

CI/CD 완전 가이드

👥 방문자 수

CI/CD 핵심 개념부터 GitHub Actions 파이프라인, Docker 이미지 빌드, Kubernetes 배포 자동화, GitOps, Blue-Green/Canary 배포 전략까지 실무 예제로 학습합니다.

GitHub Actions GitOps Blue-Green Canary

1. CI/CD란?

CI/CD는 코드 변경 사항을 빠르고 안전하게 프로덕션까지 전달하기 위한 자동화 프랙티스입니다. 사람이 수동으로 빌드·테스트·배포하는 과정을 파이프라인으로 대체합니다.

용어의미
CI (Continuous Integration)코드를 자주 통합하고, 커밋마다 자동으로 빌드·테스트하여 문제를 조기 발견
CD (Continuous Delivery)테스트를 통과한 빌드를 언제든 배포 가능한 상태로 유지 (배포는 수동 승인)
CD (Continuous Deployment)승인 없이 통과된 빌드를 자동으로 프로덕션까지 배포
PipelineCI/CD의 각 단계를 정의한 자동화 워크플로우

2. 파이프라인 단계

전형적인 파이프라인은 아래 단계를 순서대로 거치며, 각 단계가 실패하면 다음 단계로 진행하지 않습니다.

단계내용
Lint / Format정적 분석으로 코드 스타일·잠재적 버그 검사
Build소스 컴파일, 의존성 설치, 아티팩트 생성
Test단위/통합 테스트 실행, 커버리지 측정
PackageDocker 이미지 빌드 등 배포 가능한 산출물 생성
Deploy스테이징 → 프로덕션 순으로 배포
Verify헬스체크, 스모크 테스트로 배포 성공 확인

3. GitHub Actions 기초

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run buildyaml
키워드의미
on워크플로우를 트리거하는 이벤트 (push, pull_request, schedule 등)
jobs병렬로 실행되는 작업 단위. 기본적으로 독립된 러너에서 실행
stepsJob 내에서 순차 실행되는 명령어/액션 목록
uses재사용 가능한 Action(마켓플레이스 또는 자체 제작) 호출
secretsRepository/Organization Settings에 등록한 민감 값 참조

4. 빌드 & 테스트 파이프라인

name: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]   # 여러 버전에서 동시 테스트
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      - run: npm ci
      - run: npm test -- --coverage
      - uses: actions/upload-artifact@v4
        with:
          name: coverage-${{ matrix.node-version }}
          path: coverage/
        if: always()yaml
💡
strategy.matrix는 Job을 조합별로 병렬 실행합니다. Node 버전 호환성 검증, OS별 테스트(ubuntu/windows/macos) 등에 유용합니다.

5. Docker 이미지 빌드 & 레지스트리 푸시

name: Build & Push

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  docker:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write   # GHCR 푸시 권한
    steps:
      - uses: actions/checkout@v4

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: |
            ghcr.io/${{ github.repository }}:${{ github.sha }}
            ghcr.io/${{ github.repository }}:latest
          cache-from: type=gha
          cache-to: type=gha,mode=maxyaml

Dockerfile 작성 규칙과 멀티스테이지 빌드는 Docker 가이드를 참고하세요.

6. Kubernetes 배포 자동화

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: azure/setup-kubectl@v4

      - name: Configure kubeconfig
        run: echo "${{ secrets.KUBECONFIG_B64 }}" | base64 -d > kubeconfig

      - name: Rolling update
        run: |
          export KUBECONFIG=kubeconfig
          kubectl set image deployment/myapp app=ghcr.io/${{ github.repository }}:${{ github.sha }}
          kubectl rollout status deployment/myapp --timeout=120syaml
⚠️
장기 자격 증명(kubeconfig, 클라우드 키)을 CI에 그대로 두면 유출 위험이 큽니다. 가능하면 OIDC 기반 단기 토큰 발급(GitHub → AWS/GCP/Azure) 방식을 사용하세요.

7. GitOps (ArgoCD)

GitOps는 "배포하고 싶은 상태"를 Git 저장소에 선언하고, 클러스터 내부의 컨트롤러가 그 상태와 실제 상태를 지속적으로 동기화하는 방식입니다. CI가 클러스터에 직접 kubectl apply하는 대신, Git에 매니페스트만 반영하면 배포가 완료됩니다.

# ArgoCD Application 정의
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/org/myapp-manifests
    targetRevision: main
    path: overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true       # Git에서 삭제된 리소스는 클러스터에서도 제거
      selfHeal: true     # 수동 변경을 감지하면 Git 상태로 자동 복구yaml
Push 기반 CI/CD (기존)GitOps (Pull 기반)
CI가 클러스터 자격 증명을 직접 보유클러스터 내부 컨트롤러만 Git을 읽음 (자격 증명 노출 최소화)
배포 이력이 CI 로그에 흩어짐배포 이력이 Git 커밋 히스토리로 남음
드리프트(수동 변경) 감지 어려움selfHeal로 드리프트 자동 복구

8. 배포 전략

전략동작 방식장단점
Rolling Update구버전 Pod를 하나씩 신버전으로 교체K8s 기본 전략, 리소스 효율적 / 롤백 중 두 버전 공존
Blue-Green신버전(Green)을 완전히 띄운 뒤 트래픽을 한 번에 전환즉시 롤백 가능 / 리소스 2배 필요
Canary신버전에 트래픽 일부(예: 5%)만 우선 전달 후 점진 확대실사용자 기반 검증 / 라우팅 설정 복잡도 증가
Feature Flag배포와 기능 노출을 분리, 코드는 배포하되 플래그로 온/오프배포·릴리스 분리 / 플래그 관리 부채 발생 가능
# Canary 예시 — Ingress 트래픽 분할 (nginx-ingress annotation)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "5"   # 신버전으로 5% 트래픽
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-v2
            port: { number: 80 }yaml

9. 다음 단계

🚀
CI/CD 심화 로드맵

Progressive Delivery: Argo Rollouts / Flagger로 Canary·Blue-Green을 자동화하고 메트릭 기반 자동 롤백
Supply Chain 보안: SBOM 생성, 이미지 서명(Cosign), 취약점 스캔(Trivy)을 파이프라인에 통합
Self-hosted Runner: GitHub Actions/Jenkins Agent를 자체 인프라(Kubernetes)에서 운영
모니터링 연동: 배포 이벤트를 Grafana 대시보드에 마킹하여 배포-장애 상관관계 추적

연계 가이드: Jenkins 가이드 · Docker 가이드 · Kubernetes 실전/심화 가이드 · 📊 Grafana 가이드