본문으로 건너뛰기
AIDevOps
  • Learn
  • Learning Paths
  • Practice
  • Open Source
  • Books
  • Engineering

    AI DevOpsAI 서비스 개발·운영 전체 지도LLMOpsLLM 배포·평가·관측실전 프로젝트AI Agent 프로젝트 실습

    Knowledge

    Docs기술 문서 모음Blog엔지니어링 아티클Plogger개발 기록 피드

    Validate

    Certification3단계 역량 인증 · 준비 중
AI Models
LlamaMistralGemmaDeepSeekQwen
🐳 DevOps
DevOps 입문 & 로드맵LinuxDockerCI/CD|Kubernetes 기본K8s 심화/실무PrometheusGrafana
🤖 AI 실전 개발
AI 실전 입문 & 로드맵Hugging FaceLangChainLlamaIndexLLMOps|LangGraphMCPMulti-AgentAgent Evaluation
🧠 AI Core
AI 입문 & 로드맵ML FundamentalsLLM Fundamentals|Python AIC++|PyTorchTensorFlowJAX
🧠 AI Agent 개발
금융 AI AgentLLM API 서버주식 투자 AgentAIOps AI Agent교육 AI Agent코딩 AI Agent
🌱 Spring Cloud
Spring 입문 & 로드맵Spring Cloud GatewaySpring BootJava|Spring AISpring SecuritySpring BatchSpring JPA
🧱 인프라
인프라 입문 & 로드맵NginxRedis
☁️ 클라우드
클라우드 입문 & 로드맵AWSGCPAzureNCPCloudflare
🎨 Frontend
Frontend 입문 & 로드맵JavaScriptTypeScript|ReactNext.js|VueNuxt
📱 Mobile
Mobile 입문 & 로드맵KotlinAndroidFlutter
⚙️ Backend
Backend 입문 & 로드맵Python 기본FastAPIDjangoFlask|CGoGinNode.js
💾 Database
DB 입문 & 로드맵공통 SQLOracleMySQLPostgreSQL|MongoDB벡터 DB
🧪 검증
k6JMeternGrinder
AIDevOps

Engineering AI. From Code to Production.
AI와 AI Agent를 개발하고 운영하기 위한 엔지니어링 학습 플랫폼

Learn

  • 전체 가이드
  • Learning Paths
  • Practice
  • Books

Resources

  • AI DevOps
  • LLMOps
  • 실전 프로젝트
  • Docs
  • Blog
  • Plogger
  • Open Source
  • Certification (준비 중)

Start Here

  • AI Core 로드맵
  • AI 실전 개발 로드맵
  • Spring Cloud 로드맵
  • DevOps 로드맵
  • 인프라 로드맵

 

  • 클라우드 로드맵
  • Frontend 로드맵
  • Mobile 로드맵
  • Backend 로드맵
  • Database 로드맵
© 2026 AI DevOps Korea. All rights reserved.
이용약관개인정보처리방침Sitemaptestforge.kr
  1. Home
  2. Learn
  3. DevOps
  4. CI/CD
AI 서비스 배포 자동화 완전 가이드 — 파이프라인부터 GitOps까지

CI CI/CD 완전 가이드

Visitors

CI/CD의 기본 개념부터 브랜치 전략, GitHub Actions·Jenkins 파이프라인, 빌드 캐싱, OIDC 기반 시크릿 관리, 공급망 보안(SBOM·이미지 서명), Blue-Green·Canary 점진적 배포, GitOps(ArgoCD)까지 — AI Agent 서비스를 안전하고 빠르게 릴리스하는 전체 흐름을 정리합니다.

  • Intermediate · 중급
  • 업데이트 2026.09.20
  • 약 23분 읽기
  • 14개 섹션
  • 예제 코드 11개
  • 웹 IDE 실습 제공
CI

CI/CD 웹 IDE

설치 없이 브라우저에서 코드를 실행하고 단계별 예제로 익혀보세요.

웹 IDE 열기 →
CI/CD 파이프라인 설계빌드 속도 최적화 & 캐싱OIDC 시크릿리스 인증 & 공급망 보안점진적 배포 & GitOps

관련 프레임워크 & 개발환경

🐳Docker→☸️Kubernetes 기본→☸️K8s 심화/실무→🐧Linux→

목차

0 / 16
  1. 가이드 사용법
  2. 구조 다이어그램
  3. CI/CD란 무엇인가
  4. 파이프라인 설계
  5. 브랜치 전략 & 트리거
  6. GitHub Actions
  7. Jenkins Pipeline
  8. 캐싱 & 빌드 속도 최적화
  9. Docker 이미지
  10. 시크릿 관리 & OIDC 연동
  11. 품질 게이트
  12. 공급망 보안 — SBOM & 이미지 서명
  13. 점진적 배포 전략 (Blue-Green·Canary)
  14. 배포와 롤백
  15. IaC 파이프라인 — Terraform & Ansible
  16. GitOps (ArgoCD)
목차 16개 섹션
  1. 가이드 사용법
  2. 구조 다이어그램
  3. CI/CD란 무엇인가
  4. 파이프라인 설계
  5. 브랜치 전략 & 트리거
  6. GitHub Actions
  7. Jenkins Pipeline
  8. 캐싱 & 빌드 속도 최적화
  9. Docker 이미지
  10. 시크릿 관리 & OIDC 연동
  11. 품질 게이트
  12. 공급망 보안 — SBOM & 이미지 서명
  13. 점진적 배포 전략 (Blue-Green·Canary)
  14. 배포와 롤백
  15. IaC 파이프라인 — Terraform & Ansible
  16. GitOps (ArgoCD)

가이드 사용법

읽는 방향

CI/CD를 실무 흐름으로 이해하기

CI/CD의 기본 개념부터 브랜치 전략, GitHub Actions·Jenkins 파이프라인, 빌드 캐싱, OIDC 기반 시크릿 관리, 공급망 보안(SBOM·이미지 서명), Blue-Green·Canary 점진적 배포, GitOps(ArgoCD)까지 — AI Agent 서비스를 안전하고 빠르게 릴리스하는 전체 흐름을 정리합니다. 이 가이드는 개념을 나열하기보다, 실제 프로젝트에서 판단해야 하는 순서대로 내용을 따라갈 수 있게 구성했습니다.

핵심 관점

인프라 / 운영

설치 명령을 외우기보다 트래픽, 런타임, 관측, 장애 대응이 어떤 순서로 이어지는지 파악합니다.

CI/CD 파이프라인 설계빌드 속도 최적화 & 캐싱OIDC 시크릿리스 인증 & 공급망 보안점진적 배포 & GitOps

구조 다이어그램

글로 읽은 내용을 머릿속에 오래 남기려면 먼저 흐름을 그림으로 잡는 편이 좋습니다. 아래 두 그림은 CI/CD를 학습할 때 계속 되돌아볼 수 있는 기준 지도입니다.

학습 흐름

다이어그램 렌더링 중…

아키텍처 관점

다이어그램 렌더링 중…

CI/CD란 무엇인가

CI/CD를 처음 펼칠 때는 세부 명령보다 큰 그림이 먼저입니다. 이 섹션에서는 앞으로 배울 개념들이 어떤 문제를 풀기 위해 등장했는지부터 잡아봅니다.

CI(Continuous Integration)는 여러 개발자가 작업한 코드를 자주 병합하고, 병합할 때마다 자동으로 빌드·테스트해 통합 문제를 조기에 발견하는 관행입니다. CD는 그 뒤를 잇는 두 단계로 나뉘는데, "언제든 배포할 수 있는 상태로 아티팩트를 준비"하는 Continuous Delivery와, 사람의 승인 없이 "실제로 운영까지 자동 배포"하는 Continuous Deployment는 이름은 비슷해도 자동화 범위가 다릅니다.
다이어그램 렌더링 중…
용어자동화 범위사람의 개입
CI (Continuous Integration)커밋마다 빌드 + 자동 테스트병합 여부는 리뷰어가 결정
Continuous DeliveryCI + 배포 아티팩트를 항상 준비된 상태로 유지운영 배포 버튼은 사람이 누름
Continuous DeploymentDelivery + 테스트 통과 시 운영까지 자동 배포개입 없음 (실패 시에만 알림)

Tip

한국에서도 "CD"를 관행적으로 Continuous Deployment라고 부르는 경우가 많지만, 대부분의 조직은 실제로는 운영 배포 전에 사람이 승인하는 Continuous Delivery 단계에 머물러 있습니다 — 두 개념을 구분해두면 "우리 팀의 CD는 어디까지 자동화됐는가"를 정확히 말할 수 있습니다.

파이프라인 설계

여기서는 파이프라인 설계을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

AI Agent 서비스는 일반 웹 서비스보다 모델 응답 품질, RAG 검색 품질, 토큰 비용, 응답 지연이 함께 변합니다. 그래서 CI/CD는 단순 배포 자동화가 아니라 코드 품질, 모델 호출 안정성, 프롬프트 회귀, 성능 스모크 테스트를 함께 확인하는 운영 루프가 되어야 합니다.
다이어그램 렌더링 중…
단계목표대표 검증
Install의존성 고정과 재현성 확보npm ci, uv sync, lockfile 확인
Build프론트/백엔드 빌드 실패 조기 감지npm run build, Docker build
TestAPI와 Agent 핵심 흐름 검증unit test, API contract, RAG sample eval
Security시크릿 누출과 취약 이미지 차단secret scan, npm audit, image scan
Deploy스테이징 확인 후 운영 반영smoke test, health check, rollback point

브랜치 전략 & 트리거

여기서는 브랜치 전략 & 트리거을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

브랜치 전략은 곧 "언제 CI가 돌고 언제 배포가 일어나는가"를 결정합니다. 오래 살아남는 브랜치가 많을수록 병합 시점에 충돌과 통합 문제가 커지기 때문에, 대부분의 팀은 기능 브랜치를 하루이틀 안에 짧게 살고 죽게 만드는 Trunk-Based Development로 수렴하고 있습니다.
다이어그램 렌더링 중…
전략특징적합한 경우
Trunk-Based기능 브랜치가 하루이틀 안에 main으로 병합, feature flag로 미완성 기능 숨김빠른 배포 주기, CI/CD가 성숙한 대부분의 팀 (권장)
GitHub Flowmain + 기능 브랜치, PR 머지 즉시 배포단순한 웹 서비스, 소규모 팀
GitFlowmain/develop/release/hotfix 등 여러 장기 브랜치정해진 릴리스 주기가 있는 패키지 소프트웨어 (요즘은 과함)

Tip

  • on.pull_request는 병합 전 검증, on.push (branches: [main])는 병합된 뒤 배포, on.workflow_dispatch는 수동 실행, on.schedule은 정기 실행(야간 회귀 테스트 등)에 씁니다 — 이 네 가지 트리거 조합만 알아도 대부분의 파이프라인 구조를 설계할 수 있습니다.
  • GitFlow의 develop/release 브랜치는 "병합 대기 중인 코드"를 오래 쌓아두게 만들어 CI가 자주 돌아도 실제 통합 시점은 늦어지는 역설을 만듭니다 — 신규 프로젝트라면 Trunk-Based + feature flag 조합을 기본으로 시작하세요.

GitHub Actions 기본 워크플로

여기서는 GitHub Actions 기본 워크플로을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

PR에서는 빌드와 테스트만 수행하고, main 브랜치에 병합될 때 Docker 이미지를 만들고 배포합니다. AI Agent 프로젝트는 모델 API 키, DB URL, 벡터 DB 접속 정보가 필요하므로 GitHub Secrets에 분리해 저장합니다.
.github/workflows/ci.ymlYAML
name: CI

on:
  pull_request:
  push:
    branches: [main]

jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm run build
      - run: npm test -- --runInBand
        if: ${{ hashFiles('**/*.test.ts', '**/*.spec.ts') != '' }}

  deploy:
    needs: build-test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy
        run: ./scripts/deploy.sh
        env:
          DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
          DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}

Jenkins Pipeline 방식

여기서는 Jenkins Pipeline 방식을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

Jenkins는 사내망, 전용 빌드 서버, 폐쇄망 배포, 승인 단계가 필요한 조직에서 여전히 강력합니다. Jenkinsfile을 저장소에 함께 두면 빌드 절차를 코드로 관리할 수 있고, Credentials에 모델 API 키와 레지스트리 토큰을 안전하게 보관할 수 있습니다.
JenkinsfileGROOVY
pipeline {
  agent any

  environment {
    NODE_VERSION = '22'
    IMAGE_NAME = 'registry.example.com/aidevops-agent'
    IMAGE_TAG = "${env.GIT_COMMIT}"
  }

  options {
    timestamps()
    disableConcurrentBuilds()
    buildDiscarder(logRotator(numToKeepStr: '20'))
  }

  stages {
    stage('Checkout') {
      steps {
        checkout scm
      }
    }

    stage('Install') {
      steps {
        sh 'node --version'
        sh 'npm ci'
      }
    }

    stage('Build') {
      steps {
        sh 'npm run build'
      }
    }

    stage('Test') {
      steps {
        sh 'npm test -- --runInBand || true'
        sh 'bash scripts/ci-smoke.sh'
      }
    }

    stage('Docker Build') {
      steps {
        sh 'docker build -t $IMAGE_NAME:$IMAGE_TAG -t $IMAGE_NAME:latest .'
      }
    }

    stage('Docker Push') {
      when { branch 'main' }
      steps {
        withCredentials([usernamePassword(
          credentialsId: 'container-registry',
          usernameVariable: 'REGISTRY_USER',
          passwordVariable: 'REGISTRY_PASSWORD'
        )]) {
          sh 'echo $REGISTRY_PASSWORD | docker login registry.example.com -u $REGISTRY_USER --password-stdin'
          sh 'docker push $IMAGE_NAME:$IMAGE_TAG'
          sh 'docker push $IMAGE_NAME:latest'
        }
      }
    }

    stage('Deploy Staging') {
      when { branch 'main' }
      steps {
        sh 'ssh deploy@staging "cd /opt/aidevops-agent && docker compose pull && docker compose up -d"'
        sh 'BASE_URL=https://staging.example.com bash scripts/ci-smoke.sh'
      }
    }

    stage('Approve Production') {
      when { branch 'main' }
      steps {
        input message: 'Deploy to production?', ok: 'Deploy'
      }
    }

    stage('Deploy Production') {
      when { branch 'main' }
      steps {
        sh 'ssh deploy@prod "cd /opt/aidevops-agent && docker compose pull && docker compose up -d"'
        sh 'BASE_URL=https://www.aidevops.kr bash scripts/ci-smoke.sh'
      }
    }
  }

  post {
    failure {
      echo 'Pipeline failed. Check build logs and rollback if production deploy started.'
    }
    always {
      sh 'docker image prune -f || true'
    }
  }
}
구성 요소권장 방식주의점
AgentDocker 사용 가능 Jenkins nodeDocker socket 권한과 빌드 격리 확인
CredentialsJenkins Credentials BindingAPI 키를 로그에 출력하지 않기
StagesInstall, Build, Test, Image, Deploystage별 실패 지점을 명확히 분리
Approvalinput step으로 운영 배포 승인스테이징 smoke test 이후 승인
Rollback이전 이미지 태그 또는 kubectl rollout undo배포 전 현재 태그 기록

캐싱 & 빌드 속도 최적화

여기서는 캐싱 & 빌드 속도 최적화을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

CI 파이프라인이 느려지면 개발자는 리뷰를 기다리다 다른 일을 하게 되고, 그만큼 컨텍스트 전환 비용이 커집니다. 의존성 설치와 Docker 레이어를 캐싱하고 테스트를 병렬로 나눠 돌리는 것만으로도 5~10분 걸리던 파이프라인을 1~2분대로 줄일 수 있는 경우가 많습니다.
다이어그램 렌더링 중…
.github/workflows/ci.yml (캐싱 + 매트릭스 병렬 테스트)YAML
jobs:
  test:
    strategy:
      matrix:
        shard: [1, 2, 3, 4]   # 테스트를 4개로 쪼개 동시에 실행
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm           # package-lock.json 해시 기준 자동 캐싱
      - run: npm ci
      - run: npm test -- --shard=${{ matrix.shard }}/4
캐시 범위문제해결
너무 넓은 키 (예: 브랜치명만)의존성이 바뀌어도 오래된 캐시를 계속 사용 — 미묘한 버그 유발캐시 키에 lockfile 해시를 반드시 포함
너무 좁은 키 (예: 커밋 SHA)커밋마다 캐시가 달라져 사실상 캐시 재사용이 안 됨lockfile·OS·언어 버전처럼 실제로 캐시 유효성에 영향을 주는 값만 키에 포함

Tip

Docker 이미지 빌드도 cache-from/cache-to: type=gha를 쓰면 GitHub Actions의 캐시 스토리지에 레이어를 저장해, 러너가 매번 새로 뜨는 환경에서도 이전 빌드의 레이어를 재사용할 수 있습니다.

Docker 이미지 빌드와 배포

여기서는 Docker 이미지 빌드와 배포을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

운영 배포는 소스 코드를 서버에서 직접 빌드하기보다, CI에서 검증된 Docker 이미지를 레지스트리에 올리고 서버는 해당 태그를 pull하도록 구성하는 편이 안정적입니다. 태그는 커밋 SHA를 사용하면 어떤 코드가 배포됐는지 추적하기 쉽습니다.
.github/workflows/docker.ymlYAML
name: Docker Image

on:
  push:
    branches: [main]

env:
  IMAGE_NAME: ghcr.io/${{ github.repository }}/aidevops-agent

jobs:
  docker:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    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: |
            ${{ env.IMAGE_NAME }}:${{ github.sha }}
            ${{ env.IMAGE_NAME }}:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

시크릿 관리 & OIDC 연동

여기서는 시크릿 관리 & OIDC 연동을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

AWS_ACCESS_KEY_ID 같은 장기 액세스 키를 GitHub Secrets에 넣어두면, 그 키가 유출됐을 때 만료시키기 전까지 계속 악용될 수 있습니다. OIDC(OpenID Connect) 연동을 쓰면 CI 작업이 실행되는 그 순간에만 유효한 단기 자격 증명을 클라우드 provider로부터 직접 발급받기 때문에, 애초에 GitHub Secrets에 저장해둘 클라우드 키 자체가 없어집니다.
다이어그램 렌더링 중…
.github/workflows/deploy.ymlYAML
permissions:
  id-token: write   # OIDC 토큰 발급에 필요
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-deployer
          aws-region: ap-northeast-2
          # AWS_ACCESS_KEY_ID/SECRET 없이 여기서 임시 자격 증명이 발급됨
      - run: aws ecs update-service --cluster prod --service api --force-new-deployment
방식유출 시 위험만료
장기 액세스 키만료 전까지 무제한 악용 가능수동으로 로테이션하지 않으면 영구
OIDC 단기 토큰이미 만료된 뒤라 재사용 불가능한 경우가 대부분보통 15분~1시간

Tip

OIDC는 "이 GitHub 저장소의 이 브랜치에서 실행되는 워크플로만 이 Role을 맡을 수 있다"는 신뢰 관계를 클라우드 쪽 IAM 설정에서 좁게 지정할 수 있습니다 — 다른 저장소가 같은 조직에 있어도 명시적으로 허용하지 않으면 그 Role을 가져갈 수 없습니다.

AI Agent 품질 게이트

여기서는 AI Agent 품질 게이트을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

AI 서비스는 빌드가 성공해도 답변 품질이 나빠질 수 있습니다. 최소한 고정 질문 세트, RAG 검색 샘플, 응답 시간 기준, 비용 기준을 CI에서 확인하세요.
scripts/ci-smoke.shBASH
#!/usr/bin/env bash
set -euo pipefail

BASE_URL="${BASE_URL:-http://localhost:3000}"

curl -fsS "$BASE_URL/health"
curl -fsS "$BASE_URL/api/search?q=refund-policy" | jq '.results | length > 0'
curl -fsS -X POST "$BASE_URL/api/chat" \
  -H 'content-type: application/json' \
  -d '{"message":"서비스 상태를 요약해줘"}' | jq -e '.answer'

Tip

  • RAG 샘플 질문 10~30개를 두고 기대 문서가 검색되는지 확인합니다.
  • 프롬프트 변경 PR에는 대표 답변 스냅샷을 남겨 리뷰할 수 있게 합니다.
  • k6 smoke test로 /health, /api/chat, /api/search의 p95 지연을 확인합니다.
  • 운영 시크릿은 GitHub Secrets 또는 Cloudflare/Vercel 환경 변수로만 주입합니다.
  • 모델 API 장애에 대비해 fallback 모델과 timeout, retry, circuit breaker를 둡니다.

공급망 보안 — SBOM & 이미지 서명

여기서는 공급망 보안 — SBOM & 이미지 서명을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

이미지 자체에 취약점이 없어도, 빌드 과정에서 의존성이 몰래 변조되거나 검증되지 않은 이미지가 그대로 배포되는 공급망 공격은 막을 수 없습니다. SBOM(Software Bill of Materials)으로 이미지에 어떤 패키지가 정확히 어떤 버전으로 들어있는지 기록해두고, 이미지에 서명을 남겨 배포 직전에 "이 이미지가 정말 우리 CI가 만든 것인지"를 검증하는 것이 공급망 보안의 핵심입니다.
다이어그램 렌더링 중…
.github/workflows/docker.yml (SBOM 생성 + 서명)YAML
permissions:
  contents: read
  packages: write
  id-token: write   # keyless 서명에 필요

steps:
  - uses: docker/build-push-action@v6
    id: build
    with:
      push: true
      tags: ${{ env.IMAGE_NAME }}:${{ github.sha }}
      sbom: true             # SBOM을 이미지에 함께 첨부

  - uses: sigstore/cosign-installer@v3
  - name: 이미지 서명 (keyless — GitHub OIDC 신원으로 서명)
    run: cosign sign --yes ${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
BASH
# 배포 서버/CD 파이프라인에서 배포 직전에 서명 검증
cosign verify \
  --certificate-identity-regexp "https://github.com/myorg/myrepo/.*" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/myorg/myapp@sha256:abc123...

# 검증 실패 시 exit code가 0이 아니므로 CD 스크립트에서 바로 배포를 중단할 수 있음
도구/개념역할
SBOM이미지 안의 모든 패키지·버전 목록 — 새 CVE가 발표됐을 때 영향받는 이미지를 즉시 검색 가능
cosign sign (keyless)GitHub OIDC 신원으로 이미지에 서명 — 개인 키를 별도로 관리할 필요 없음
cosign verify서명이 신뢰할 수 있는 CI 파이프라인에서 만들어졌는지 배포 전에 확인

Tip

keyless 서명은 서명용 개인 키를 어딘가에 보관할 필요가 없다는 뜻이지 "서명이 없다"는 뜻이 아닙니다 — Sigstore의 투명성 로그(Rekor)에 서명 기록이 공개적으로 남아 나중에도 검증할 수 있습니다.

점진적 배포 전략 (Blue-Green·Canary)

여기서는 점진적 배포 전략 (Blue-Green·Canary)을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

새 버전을 한 번에 100% 트래픽으로 전환하면, 문제가 있을 때 모든 사용자가 동시에 영향을 받습니다. Blue-Green과 Canary는 모두 "새 버전을 일부에게만 먼저 노출하고 문제가 없으면 점진적으로 넓힌다"는 같은 목표를 다른 방식으로 구현합니다.
다이어그램 렌더링 중…
전략전환 방식장점단점
Blue-Green검증된 신규 환경으로 트래픽을 한 번에 전환롤백이 즉시 가능 (트래픽을 원래대로 되돌리기만 하면 됨)두 배의 인프라 리소스가 순간적으로 필요
Canary일부 트래픽만 신규 버전으로 보내고 점진적으로 비중 확대실제 트래픽으로 소규모 검증, 문제 시 영향 범위가 작음두 버전이 공존하는 동안 호환성(DB 스키마 등) 관리 필요
Rolling (참고)docker/kubernetes 가이드에서 다룬 방식 — 인스턴스를 하나씩 순차 교체추가 리소스 없이 적용 가능전환 중 신규/구버전이 동시에 트래픽을 받음

Tip

Canary 배포 중에는 신규 버전과 기존 버전이 동시에 같은 DB를 바라보는 경우가 많습니다 — 새 버전에서만 읽을 수 있는 컬럼을 추가하는 식의 스키마 변경은 구버전이 완전히 사라진 뒤에 해야 안전합니다.

배포와 롤백

여기서는 배포와 롤백을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

운영 배포는 무조건 빠른 것보다 되돌릴 수 있는 것이 중요합니다. 배포 전 현재 이미지 태그를 기록하고, 새 이미지 health check가 실패하면 즉시 이전 태그로 되돌립니다.
scripts/deploy.shBASH
#!/usr/bin/env bash
set -euo pipefail

APP_DIR="/opt/aidevops-agent"
IMAGE="ghcr.io/org/aidevops-agent:${GITHUB_SHA:-latest}"

ssh "$DEPLOY_USER@$DEPLOY_HOST" <<EOF
  set -euo pipefail
  cd "$APP_DIR"
  docker compose ps
  docker compose pull
  docker compose up -d
  sleep 10
  curl -fsS http://localhost:3000/health
EOF

# Kubernetes를 사용한다면:
# kubectl set image deployment/aidevops-agent app=$IMAGE
# kubectl rollout status deployment/aidevops-agent
# kubectl rollout undo deployment/aidevops-agent

IaC 파이프라인 — Terraform & Ansible

여기서는 IaC 파이프라인 — Terraform & Ansible을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

CI/CD가 애플리케이션 코드를 빌드·배포한다면, Terraform과 Ansible은 그 애플리케이션이 올라갈 인프라 자체를 코드로 관리합니다. Terraform은 "인프라가 어떤 상태여야 하는지"를 선언해 VPC·EKS·RDS 같은 리소스를 프로비저닝하는 도구이고, Ansible은 이미 존재하는 서버에 패키지 설치·설정 파일 배포 같은 구성을 SSH로 맞추는 도구입니다 — 둘 다 별도의 파이프라인 스테이지로 CI/CD에 자연스럽게 편입됩니다.
다이어그램 렌더링 중…
.github/workflows/terraform.ymlYAML
jobs:
  plan:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform plan -out=tfplan   # 결과를 PR 코멘트로 게시

  apply:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform apply -auto-approve
      - run: ansible-playbook -i inventory/prod.ini deploy.yml
항목TerraformAnsible
방식선언형 (원하는 최종 상태를 기술)절차형 (수행할 작업 순서를 기술)
주 용도클라우드 리소스 프로비저닝 (VPC, EKS, RDS 등)이미 있는 서버의 설정·배포 자동화
상태 관리state 파일로 현재 인프라 상태를 추적상태 파일 없음 — 실행할 때마다 대상 서버를 직접 확인

Tip

terraform apply를 여러 사람이 동시에 실행하면 state 파일이 꼬일 수 있으므로 S3+DynamoDB 락 같은 원격 백엔드로 상태를 관리하고, Atlantis나 Terraform Cloud로 "PR=plan, merge=apply"를 자동화하면 인프라 변경도 GitOps와 같은 방식으로 리뷰 가능한 이력을 남길 수 있습니다.

GitOps (ArgoCD)

여기서는 GitOps (ArgoCD)을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.

지금까지 다룬 방식은 모두 CI 파이프라인이 클러스터에 직접 접근해 kubectl apply나 docker compose up을 실행하는 "Push 기반" 배포입니다. GitOps는 반대로, Git 저장소의 매니페스트를 "이 클러스터가 도달해야 할 상태"로 선언해두면 클러스터 안에서 실행되는 에이전트(ArgoCD, Flux)가 그 상태와 실제 클러스터를 지속적으로 비교해 스스로 맞춰가는 "Pull 기반" 방식입니다.
다이어그램 렌더링 중…
argocd-application.yamlYAML
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/myapp-manifests.git
    targetRevision: main
    path: overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true       # Git에서 삭제된 리소스는 클러스터에서도 자동 삭제
      selfHeal: true     # 누군가 kubectl로 수동 변경해도 Git 상태로 자동 복원
비교 항목Push 기반 CI/CDGitOps (Pull 기반)
클러스터 접근 자격 증명CI 시스템이 클러스터 접근 권한을 가져야 함클러스터 밖에서 접근할 필요 없음 — 공격 표면 감소
배포 이력CI 로그를 따로 확인해야 함Git 커밋 이력 자체가 배포 이력
롤백이전 배포 스크립트를 다시 실행git revert 한 번으로 이전 상태로 자동 동기화
설정 드리프트누군가 수동으로 kubectl 변경하면 그대로 남음selfHeal로 Git과 다르면 자동으로 되돌림

Tip

  • GitOps는 "CI가 사라진다"는 뜻이 아닙니다 — 빌드·테스트·이미지 생성은 여전히 기존 CI 파이프라인이 담당하고, GitOps는 그 결과물을 클러스터에 실제로 반영하는 마지막 CD 단계만 대체합니다. 두 흐름을 나누면 CI 파이프라인에 클러스터 자격 증명을 전혀 넣지 않아도 됩니다.
  • ArgoCD 생태계에는 여러 클러스터/환경에 하나의 템플릿으로 배포하는 ApplicationSet, Blue-Green/Canary를 컨트롤러가 자동으로 수행하는 Argo Rollouts, ArgoCD 설정 자체도 Git으로 관리하는 App of Apps 패턴 같은 확장이 있습니다 — 필요해지는 시점에 하나씩 도입하면 됩니다.
← 이전 가이드Docker다음 가이드 →Kubernetes