CI-CD 파이프라인 — 빌드, 테스트, 배포 자동화의 기본 개념
코드를 푸시하면 자동으로 테스트가 돌고, 문제가 없으면 바로 서버에 반영되는 구조를 어떻게 만들까요?
CI/CD는 현대 소프트웨어 개발의 기본 인프라입니다. 공부하다 보니 용어가 비슷비슷해서 헷갈리는 부분이 많았는데, 핵심 개념부터 차근차근 정리해보겠습니다.
CI — Continuous Integration
코드 변경을 메인 브랜치에 자주 통합하고, 매번 자동으로 빌드와 테스트를 실행하는 것입니다.
핵심 원칙:
- 개발자가 하루에 한 번 이상 코드를 통합
- 통합할 때마다 자동으로 빌드 + 테스트 실행
- 실패하면 즉시 알림 → 빠른 수정
CI가 없으면 생기는 문제:
- "내 로컬에선 되는데?" — 통합 환경에서만 발생하는 버그
- 머지 데이 지옥 — 오랫동안 분리된 브랜치를 합칠 때 대량 충돌
- "누가 깨뜨렸어?" — 빌드 실패 원인 추적이 어려움
CD — Continuous Delivery vs Continuous Deployment
여기서 많이 헷갈리는 부분이 있습니다. CD는 두 가지 의미가 있습니다.
Continuous Delivery (지속적 전달):
- 프로덕션 배포 ** 준비 **까지 자동화
- 실제 배포는 수동 승인(버튼 클릭)을 거침
- 대부분의 기업이 채택하는 방식
Continuous Deployment (지속적 배포):
- 모든 단계가 자동 — 테스트 통과하면 바로 프로덕션에 배포
- 높은 테스트 커버리지와 모니터링이 전제
- Netflix, GitHub 등 성숙한 조직에서 사용
면접에서 "CD가 뭐냐"고 물으면 둘 다 설명하고 차이를 명확히 하는 것이 포인트입니다.
파이프라인 구성
전형적인 CI/CD 파이프라인의 흐름입니다:
코드 푸시 → 빌드 → 테스트 → 보안 검사 → 스테이징 배포 → 승인 → 프로덕션 배포
각 단계를 살펴보겠습니다:
- ** 소스** — 코드 푸시 또는 PR 생성 시 파이프라인 트리거
- ** 빌드** — 컴파일, 의존성 설치, 아티팩트(JAR, Docker 이미지) 생성
- ** 테스트** — 단위 → 통합 → E2E 순서로 실행
- ** 보안 검사** — SAST/DAST 도구로 취약점 스캔
- ** 스테이징 배포** — 프로덕션과 동일한 환경에서 검증
- ** 프로덕션 배포** — 승인 후 실제 사용자에게 배포
테스트 피라미드 적용
CI/CD 파이프라인에서 테스트는 피라미드 구조를 따릅니다:
/ E2E \ ← 느리고, 비쌈 (소수)
/ 통합 \ ← 중간 (적당히)
/ 단위 테스트 \ ← 빠르고, 저렴 (다수)
- ** 단위 테스트** — 함수/메서드 단위, 수초 내 실행. 전체의 70~80%
- ** 통합 테스트** — DB, 외부 API 연동 검증. 전체의 15~20%
- E2E 테스트 — 사용자 시나리오 전체 검증. 전체의 5~10%
파이프라인에서는 빠른 테스트부터 실행합니다. 단위 테스트가 실패하면 통합 테스트를 굳이 돌릴 필요가 없습니다.
GitHub Actions 기본 문법
2026년 기준 GitHub Actions가 CI/CD 도구의 사실상 표준입니다.
# .github/workflows/ci.yml
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
# 소스 코드 체크아웃
- uses: actions/checkout@v4
# JDK 설정
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
# 빌드 및 테스트
- name: Build & Test
run: ./gradlew build
# 테스트 결과 리포트
- name: Publish Test Report
if: always()
uses: dorny/test-reporter@v1
with:
name: Test Results
path: build/test-results/test/*.xml
reporter: java-junit
핵심 개념:
- on — 트리거 조건 (push, PR, 스케줄 등)
- jobs — 병렬 실행 가능한 작업 단위
- steps — 순차 실행되는 각 단계
- uses — 재사용 가능한 액션 (마켓플레이스)
브랜치 전략과 CI/CD
트렁크 기반 개발 (Trunk-Based)
main ──●──●──●──●──●──●──
\ / \ /
feature feature
(1~2일) (1~2일)
- 메인 브랜치에 자주 통합 (하루 1회 이상)
- 피처 브랜치 수명 1~2일 이내
- CI/CD와 궁합이 좋음 — 작은 변경을 자주 배포
Gitflow
main ─────────────────────────
└── develop ──●──●──●──●──
\ /
feature branch
(수일~수주)
- 장기 피처 브랜치 + develop/release 브랜치 분리
- 릴리스 주기가 긴 프로젝트에 적합
- CI/CD 복잡도 증가 — 여러 브랜치에 파이프라인 설정 필요
최근 추세는 트렁크 기반 개발 + 피처 플래그 조합입니다.
시프트 레프트 보안
보안 검사를 개발/빌드 단계로 앞당기는 접근입니다. 2026년 기준 선택이 아닌 필수가 되었습니다.
- SAST (Static Application Security Testing) — 소스 코드 정적 분석. 빌드 시점에 실행
- DAST (Dynamic Application Security Testing) — 실행 중인 앱에 공격 시뮬레이션
- SCA (Software Composition Analysis) — 의존성 라이브러리 취약점 검사
- ** 시크릿 스캔** — 코드에 포함된 API 키, 비밀번호 탐지
# GitHub Actions에서 보안 스캔 예시
- name: Security Scan
uses: github/codeql-action/analyze@v3
with:
languages: java
환경 분리
dev → staging → production
- dev — 개발자 로컬 또는 공유 개발 환경. 자유롭게 배포
- staging — 프로덕션과 동일한 구성. QA 및 최종 검증
- production — 실제 사용자가 접근하는 환경
각 환경별로 설정(DB 주소, API 키 등)을 분리하고, 시크릿은 환경 변수나 시크릿 매니저로 관리합니다.
배포 전략
블루-그린 배포
Blue (현재) ──── 트래픽 ────→ 사용자
Green (새 버전) ── 대기 ──
배포 시:
Blue (이전) ──── 대기 ──
Green (새 버전) ── 트래픽 ──→ 사용자
- 두 개의 동일한 환경을 운영
- 트래픽을 한 번에 전환 (로드밸런서 설정 변경)
- 롤백이 빠름 — 다시 블루로 전환하면 됨
- 단점: 인프라 비용 2배
카나리 배포
기존 버전 ── 95% 트래픽 ──→ 사용자
새 버전 ── 5% 트래픽 ──→ 사용자 (모니터링)
- 소수 사용자에게만 새 버전 노출
- 메트릭(에러율, 응답시간) 확인 후 점진적으로 비율 증가
- 문제 발견 시 빠르게 롤백
- 대규모 서비스에서 선호하는 방식
정리
- CI 는 자주 통합하고 자동 테스트, CD 는 배포 자동화 (Delivery vs Deployment 구분)
- 테스트 피라미드: 단위 > 통합 > E2E 순으로 많이 작성
- GitHub Actions로 빌드 → 테스트 → 보안 검사 → 배포 파이프라인 구성
- 시프트 레프트 보안은 더 이상 선택이 아닌 필수
- 블루-그린은 빠른 롤백, 카나리는 점진적 검증에 적합
- 트렁크 기반 개발이 CI/CD와 가장 잘 맞는 브랜치 전략
댓글 로딩 중...