🚀 DevOps — CI/CD 파이프라인

Notes / DevOps / CI/CD 완료

📖 CI/CD 개념과 원리

CI/CDContinuous Integration(지속적 통합)Continuous Delivery/Deployment(지속적 전달/배포)의 약자로, 소프트웨어를 개발하고 배포하는 과정을 자동화하는 방법론이다.

🍞 비유: 빵 공장

  • CI/CD 없는 개발 — 빵을 하나하나 손으로 만든 뒤, 다 만들고 나서야 맛을 확인. 100개를 만든 뒤 "밀가루 비율이 틀렸다"는 걸 알게 되면 전부 폐기.
  • CI/CD 있는 개발 — 컨베이어 벨트 위에서 반죽 → 발효 → 성형 → 굽기 → 품질 검사까지 자동. 반죽 단계 문제도 즉시 알림.

🔄 CI — Continuous Integration

여러 개발자가 작업한 코드를 하루에도 여러 번 공유 저장소에 합치고, 합칠 때마다 자동으로 빌드와 테스트를 실행한다.

flowchart LR DEV([개발자]) -->|git push| REPO[(Git Repository)] REPO -->|webhook 트리거| CI[CI Server
GitHub Actions · Jenkins] CI --> BLD[Build
컴파일·번들] BLD --> TST[Test
unit · lint] TST --> PKG[Package
Docker image · artifact] PKG -->|성공| OK([✅ 통합 완료]) TST -.실패.-> NOTIFY[❌ 개발자 알림]

🚢 CD — Delivery vs Deployment

구분Continuous DeliveryContinuous Deployment
배포 방식수동 승인 후 배포자동 배포
사람 개입필요 (승인 단계)불필요
적합 상황금융·의료 등 신중 배포빠른 반복이 중요한 웹 서비스
비유포장 완료, 출고 대기로봇이 자동으로 배송 차량에 탑재

🔧 CI/CD 파이프라인 표준 단계

  1. Source — 코드 변경 감지 (git push, PR 생성)
  2. Build — 컴파일 · Docker 이미지 빌드
  3. Test — 단위 테스트 · 통합 테스트 · 보안 스캔
  4. Deploy — 스테이징 또는 운영 배포
  5. Monitor — 배포 후 서비스 상태 모니터링
비유: 수도관(파이프) — 수도꼭지(Source)에서 물(코드)이 들어가 정수 필터(Build/Test)를 거쳐 수도관 끝(운영 서버)에서 깨끗한 물(검증된 코드)이 나온다. 필터가 막히면(테스트 실패) 물은 더 이상 흐르지 않는다.

🛠️ 대표 CI/CD 도구 비교

도구특징비용
GitHub ActionsGitHub 내장, YAML 기반, 클라우드 실행퍼블릭 무료, 프라이빗 월 2,000분 무료
Jenkins오픈소스, 자체 서버, 플러그인 1,800+무료 (서버 비용 별도)
GitLab CIGitLab 내장, Docker 기반 Runner퍼블릭 프로젝트 무료
AWS CodePipelineAWS 서비스 긴밀 통합파이프라인당 월 $1

⚡ GitHub Actions

GitHub 저장소에 내장된 CI/CD 도구. 별도 서버 없이 .github/workflows/에 YAML 파일 하나로 자동화가 가능하다.

핵심 용어 — 회사 조직도 비유

용어설명비유
Workflow전체 자동화 프로세스 (YAML 파일)회사 SOP 문서
EventWorkflow 시작 트리거 (push/PR/schedule)"이 상황이면 시작" 신호
Job병렬·순차 실행되는 작업 단위회사의 부서
StepJob 안에서 순서대로 실행되는 개별 명령부서 안의 업무 체크리스트
Action재사용 가능한 단위 기능 (마켓플레이스)외주 용역 업체
RunnerWorkflow가 실행되는 VM임시 직원 (끝나면 사라짐)

기본 구조

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

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

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: 저장소 체크아웃
        uses: actions/checkout@v4

      - name: Python 설정
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: 의존성 설치
        run: pip install -r requirements.txt

      - name: 테스트 실행
        run: python -m pytest
키워드: on = 트리거 · runs-on = 실행 환경 · uses = 마켓플레이스 Action(owner/repo@version) · run = 쉘 명령 · with = Action 입력값

📝 Actions 실전: Docker → ECR 푸시

name: Build and Push to ECR

on:
  push:
    branches: [ main ]

env:
  AWS_REGION: ap-northeast-2
  ECR_REPOSITORY: my-app

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: AWS 자격증명 설정
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}

      - name: ECR 로그인
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Docker 이미지 빌드 및 푸시
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

🔐 Secrets 관리

  • 경로: Settings → Secrets and variables → Actions → New repository secret
  • YAML에 API 키·비밀번호 직접 작성 금지 — 로그에서 *** 로 자동 마스킹
  • Organization 레벨에서 공유 Secrets 설정 시 여러 저장소 재사용 가능
  • Fork된 저장소의 PR에서는 Secrets 접근 불가 (보안 설계)

🧪 Matrix Strategy — 여러 환경 동시 테스트

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.9', '3.10', '3.11']
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: python -m pytest

💾 캐싱으로 빌드 단축

- name: 의존성 캐시
  uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}

🔨 Jenkins

Java로 만들어진 오픈소스 CI/CD 자동화 서버. 전 세계 기업 환경에서 가장 널리 쓰이는 CI/CD 도구.

비유: GitHub Actions가 관리 사무소에서 대신 돌려주는 서비스라면, Jenkins는 내가 직접 짓고 운영하는 단독 주택. 설계부터 인테리어까지 전부 내 손으로, 대신 완전한 자유.

선택 이유 3가지

  • 완전한 제어권 — 빌드 서버·실행 환경·보안 정책 모두 직접 관리 (금융/의료 적합)
  • 1,800+ 플러그인 — Git, Docker, Slack, AWS, Kubernetes 등 거의 모든 도구 연동
  • 복잡한 파이프라인 자유 설계 — Groovy 스크립트(Jenkinsfile)로 조건 분기·병렬·승인 단계 표현

🏗️ Controller-Agent 아키텍처

구성역할비유
Controller (Master)작업 스케줄링 · Web UI · 설정 관리건설 현장 현장소장
Agent (Slave)실제 빌드/테스트 수행 (VM · Docker · EC2)현장 작업자들 — 병렬 가능

🐳 Docker로 설치

docker run -d \
  --name jenkins \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts

# 초기 관리자 비밀번호 확인
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
  • -p 8080 = Web UI · -p 50000 = Agent 통신 포트
  • -v jenkins_home = Docker 볼륨에 설정·빌드 데이터 유지
  • :lts = 장기지원(안정) 버전

📄 Jenkinsfile — 파이프라인 설계도

프로젝트 루트에 Jenkinsfile을 두면 Jenkins가 자동으로 읽어 실행한다. 실무 표준은 Declarative Pipeline이다.

기본 구조

pipeline {
    agent any

    stages {
        stage('빌드') {
            steps { sh 'echo "빌드 중..."' }
        }
        stage('테스트') {
            steps { sh 'echo "테스트 중..."' }
        }
        stage('배포') {
            steps { sh 'echo "배포 중..."' }
        }
    }
}
키워드역할비유
pipeline최상위 블록레시피 책 전체
agent실행 환경 지정어떤 주방에서 요리할지
stages단계들의 목록레시피 전체 순서
stage하나의 단계"파 5분 섯는다"
steps단계 안 실제 명령"175°C로 예열"

실전 예제 — Spring Boot + Docker

pipeline {
    agent any

    environment {
        DOCKER_IMAGE = 'myapp'
        DOCKER_TAG = "${env.BUILD_NUMBER}"
    }

    stages {
        stage('체크아웃') { steps { checkout scm } }

        stage('빌드') {
            steps { sh './gradlew clean build -x test' }
        }

        stage('테스트') {
            steps { sh './gradlew test' }
            post {
                always { junit '**/build/test-results/**/*.xml' }
            }
        }

        stage('Docker 이미지 빌드') {
            steps {
                sh "docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} ."
            }
        }

        stage('배포') {
            when { branch 'main' }
            steps {
                sh "docker stop ${DOCKER_IMAGE} || true"
                sh "docker run -d --name ${DOCKER_IMAGE} -p 8080:8080 ${DOCKER_IMAGE}:${DOCKER_TAG}"
            }
        }
    }

    post {
        success { echo '파이프라인 성공!' }
        failure { echo '파이프라인 실패 - 로그 확인' }
    }
}

🔑 핵심 문법

environment + credentials

environment {
    DB_HOST = 'db.example.com'
    DB_PASSWORD = credentials('db-password-id')  // Jenkins 금고에서 참조
}

→ 로그에 ****로 자동 마스킹. 코드에 비밀번호 직접 작성 금지.

when — 조건부 실행

stage('운영 배포') {
    when { branch 'main' }
    steps { /* ... */ }
}
stage('스테이징') {
    when { branch 'develop' }
    steps { /* ... */ }
}

post — 결과 후처리

post {
    always  { cleanWs() }
    success { slackSend channel: '#deploys', message: "배포 성공: #${env.BUILD_NUMBER}" }
    failure { slackSend channel: '#alerts',  color: 'danger', message: "빌드 실패" }
}

parallel — 병렬 실행

stage('테스트') {
    parallel {
        stage('단위 테스트')   { steps { sh './gradlew test' } }
        stage('통합 테스트')   { steps { sh './gradlew integrationTest' } }
        stage('코드 분석')     { steps { sh './gradlew sonarqube' } }
    }
}

→ 한 명이 3시간 걸릴 일을 세 명이 나누면 1시간.

🪝 Webhook 자동 트리거

  1. Git 저장소 Settings → Webhooks
  2. Payload URL: http://<jenkins>:8080/github-webhook/
  3. Jenkins에서 GitHub hook trigger for GITScm polling 활성화

🔌 실무 필수 플러그인

  • Pipeline — Jenkinsfile 실행 (필수)
  • Git / Docker Pipeline / Credentials Binding
  • Slack Notification — 빌드 결과 알림
  • Blue Ocean — 파이프라인 시각화 모던 UI

⚖️ GitHub Actions vs Jenkins 선택 가이드

항목GitHub ActionsJenkins
설치/운영불필요 (SaaS)서버 직접 운영
설정 방식YAML (.github/workflows/)Groovy (Jenkinsfile)
러닝커브낮음중간~높음
보안GitHub SecretsCredentials + 자체 격리
플러그인마켓플레이스 Actions1,800+ 플러그인
적합 상황GitHub 사용 중·스타트업·오픈소스온프레미스·금융·커스텀 요구 많음
실전 팁: ① 테스트 자동화가 CI/CD의 전제 — 테스트 없는 파이프라인은 "자동 빌드 머신"에 불과 · ② 처음부터 완벽할 필요 없음 — git push → 빌드 → 테스트 1~2개로 시작 · ③ CI 없이 CD는 위험 — 검증 없는 자동 배포는 장애를 자동 발생시킬 뿐.