infra
Platform

모듈 맵

[SW Eng] CI/CD 파이프라인 — 머지부터 배포까지 자동화의 길

0 / 38 완료

펼치기
0 / 38 완료0%

PM·SRE를 위한 소프트웨어 엔지니어링 · 15 / 38

[SW Eng] CI/CD 파이프라인 — 머지부터 배포까지 자동화의 길

CI(지속적 통합)와 CD(지속적 전달/배포)가 무엇을 자동화하는지, 파이프라인 단계(빌드→테스트→배포)와 게이트를 PM·인프라 관점에서 정리합니다

🚨INCIDENT ALERT
HIGH

신규 팀원이 묻습니다. "제 코드 main에 머지됐는데, 언제 실서버에 반영돼요?" 한 팀은 "자동으로 5분 뒤요", 다른 팀은 "담당자가 수동으로 새벽에 올려요"라고 답합니다. 배포 사고가 나자 한쪽은 "파이프라인 로그 보면 어느 단계서 깨졌는지 나와요", 다른 쪽은 "누가 뭘 올렸는지 아무도 몰라요"가 됩니다. CI/CD는 '머지된 코드가 어떤 자동화된 길을 거쳐 사용자에게 닿는가'입니다. 이 길이 있느냐 없느냐가 배포의 속도와 안전을 가릅니다.

이번 챕터에서 배울 것
  • 1CI가 "자주 통합하고 자동 검증"하는 실천임을 설명할 수 있다
  • 2Continuous Delivery와 Deployment의 차이를 "마지막 승인 자동화 여부"로 구분할 수 있다
  • 3파이프라인 단계(빌드→테스트→산출물→배포)와 fail-fast 게이트를 설명할 수 있다
  • 4파이프라인 실패가 무시되는 상황의 위험과 대응을 제시할 수 있다

CI/CD 파이프라인 — 코드에서 프로덕션까지 자동 흐름확대 위 그림처럼 CI/CD 파이프라인은 git push 한 번이 빌드·테스트·보안 검사·배포까지 자동으로 이어지며, 어느 단계든 실패 시 즉시 차단합니다.

CI — 자주 통합하고 즉시 검증

💡개념

CI: 깨짐을 빨리 발견하는 안전망

CI(Continuous Integration)는 변경을 자주 통합하고, 통합할 때마다 자동으로 빌드·테스트해 문제를 즉시 잡는 실천입니다.

CI 파이프라인 흐름 — 개발자 push/PR이 CI를 트리거하면 체크아웃→빌드→자동 테스트→린트→보안 스캔, 하나라도 실패하면 즉시 멈추고(fail fast) 알림, "main은 항상 초록" 유지확대

CI의 심장은 테스트 전략에서 다룰 자동 테스트입니다. PR과 코드 리뷰의 머지 게이트가 "CI 통과"를 요구하므로, CI가 없으면 게이트도 무력합니다. CI는 브랜치 전략의 Trunk-based(작게 자주 통합)를 가능하게 하는 전제이기도 합니다 — 통합할 때마다 자동 검증되니 자주 통합해도 안전합니다.

CD — 전달 vs 배포

💡개념

언제든 배포 가능 vs 통과하면 곧장 배포

CD는 두 가지를 뜻할 수 있어 맥락으로 구분합니다.

  • Continuous Delivery(지속적 전달): 테스트 통과 후 '언제든 배포 가능한 산출물' 까지 자동으로 준비. 프로덕션 배포 '실행'만 사람이 버튼을 누름. → 배포 타이밍을 비즈니스가 통제.

  • Continuous Deployment(지속적 배포): 마지막 승인까지 완전 자동. 파이프라인을 통과하면 사람 개입 없이 프로덕션으로. → 자동화·테스트 신뢰가 높은 팀.

  • Delivery: CI → 테스트 통과 → 산출물 준비 → [사람이 승인] → prod

  • Deployment: CI → 테스트 통과 → 산출물 준비 → 자동 → prod (개입 없음)

PM 관점: Delivery면 "배포 시점"을 마케팅·릴리스 일정에 맞출 수 있고(기능 플래그와 함께 더 유연), Deployment면 "머지 = 곧 출시"이므로 작은 변경을 빠르게 내보냅니다. 어느 쪽이든 릴리스 전략의 점진 배포(카나리 등)와 결합해 위험을 관리합니다.

배포 전략 — Blue-Green·Canary·Rolling 비교확대 위 그림처럼 Blue-Green은 즉시 롤백이 가능하고, Canary는 실 트래픽으로 검증하며, Rolling은 추가 인프라 없이 순차 교체합니다.

커밋 하나가 배포까지 가는 법 — 파이프라인 단계

💡개념

커밋 하나가 배포까지 가는 법 — CI/CD 파이프라인 7단계

git push 한 번, 또는 PR 머지 한 번. 몇 분 뒤 그 변경이 실서버에 떠 있습니다. 그 사이 트리거·체크아웃·빌드·테스트·이미지 빌드·배포·검증이 순서대로, 앞 단계가 통과해야만 다음으로 자동 실행됩니다. 이 단계 사슬을 알아야 파이프라인이 빨갛게 떴을 때 "어느 칸에서, 왜" 멈췄는지를 좁힐 수 있습니다 — 초반에 깨졌으면 코드·테스트, 후반이면 인프라·배포로 원인 계열이 갈립니다.

TEXT
[개발자]  git push / PR 머지
   │
   ① 트리거: webhook이 CI 서버에 이벤트 통지 (어느 브랜치·태그에 어느 워크플로)
   │
   ② 체크아웃: 해당 커밋을 러너로 가져옴 + 의존성 설치 (캐시 활용)
   │
   ③ 빌드: 소스 컴파일·번들 → 실패하면 즉시 중단 (fail-fast)
   │
   ④ 테스트: 린트 → 단위 → 통합/E2E (빠른 것 먼저) + 보안 스캔
   │
   ⑤ 산출물: 이미지 빌드 → 레지스트리 푸시 (digest로 고정)
   │
   ⑥ 배포: 스테이징 → 헬스체크 → [승인] → 프로덕션 (같은 산출물 승격)
   │
   ⑦ 배포 후 검증: 헬스체크·스모크 테스트 → 실패 시 롤백
   ▼
[프로덕션]  사용자에게 반영

각 단계에서 무슨 일이 일어나고, 깨지면 어떤 증상인가:

단계하는 일여기서 깨지면
① 트리거webhook이 어떤 이벤트(브랜치·태그)에 어떤 워크플로를 돌릴지 결정webhook 미설정·필터 오류 → 파이프라인이 아예 안 돎
② 체크아웃·설치커밋 소스 fetch + 의존성 설치, 캐시로 단축의존성·네트워크·오염된 캐시 → "로컬은 되는데 CI만 실패"
③ 빌드컴파일·번들. 실패하면 뒤 단계로 안 넘어감(fail-fast)컴파일 에러·버전 불일치 → 초반(1~2분)에 실패
④ 테스트·스캔린트·단위·통합·보안. 하나라도 실패하면 게이트가 머지·배포 차단테스트 실패는 회귀를 잡은 것(정상) / flaky는 간헐 실패로 신뢰를 무너뜨림
⑤ 산출물이미지 빌드 후 레지스트리 푸시. digest가 "검증한 바로 그 물건"환경마다 재빌드하면 스테이징과 프로덕션 산출물이 다른 물건이 됨
⑥ 배포스테이징 검증 후 승인(Delivery)·자동(Deployment)으로 prod. 같은 산출물 승격배포 잡에 동시성 제어 없음 → 배포 순서 역전(오래된 커밋이 최신을 덮음)
⑦ 배포 후 검증헬스체크·스모크로 확인, 실패 시 이전 버전으로 롤백검증 단계 없음 → 깨진 배포가 그대로 사용자에게 노출

각 단계는 앞 단계의 성공을 전제로만 시작됩니다(fail-fast) — 그래서 멈춘 칸 앞은 전부 통과했다는 뜻이고, 멈춘 칸이 곧 원인의 위치입니다. gh run view <run-id> --log-failed로 "어느 잡에서 멈췄나"를 보면, ②④(초반, 12분)면 코드·테스트·환경 문제, ⑥~⑦(후반)이면 배포 권한·동시성·인프라 문제로 의심 방향이 갈립니다. 파이프라인 진단은 "무엇이 틀렸나"보다 "어느 단계에서 멈췄나"를 먼저 읽는 데서 시작합니다.

파이프라인 설계 판단 — 무엇을 어디서, 어떤 배포 전략으로
테스트를 CI 어느 단계에빠르고 자주 깨지는 것 먼저(린트·단위)→느린 것 나중(통합·E2E). 실패를 몇 초 안에 알리게. '빠른 피드백이 CI의 본질'
파이프라인이 자주 빨개서 무시됨flaky 테스트 격리·수정이 최우선 — 신뢰 잃은 CI는 안전망이 아니다. main을 빨간 채 두지 않기(머지 차단). '빨강을 일상으로 두면 진짜 장애를 놓침'
배포 전략 — Blue-Green vs Canary vs Rolling즉시 롤백 중요=Blue-Green(2배 인프라), 실트래픽 점진 검증=Canary, 인프라 절약·무중단=Rolling. '롤백 속도 vs 비용 vs 검증'
CD를 자동 배포 vs 수동 승인테스트 신뢰 높고 롤백 쉬우면 자동(Continuous Deployment), 규제·고위험이면 통과 후 수동 승인(Continuous Delivery). '되돌리기 쉬울수록 자동화 가능'
배포가 실패하면자동 롤백 또는 이전 버전 즉시 전환 경로를 미리 갖춰라. 헬스체크·스모크 테스트를 게이트로. 'push 전 docker run, 배포 후 헬스체크'
비밀(배포 키·토큰)을 파이프라인에코드/로그에 평문 금지 — CI 시크릿 저장소·OIDC. 로그에 마스킹. '파이프라인 로그는 누구나 본다'

파이프라인 읽기 — 직접 확인

1파이프라인 실행 상태와 실패 단계 확인

배포 사고나 지연 시, 파이프라인 로그가 "어느 단계에서 무엇이 깨졌나"를 알려줍니다. 코드를 못 짜도 단계별 성패는 읽을 수 있습니다.

로컬 터미널
# 최근 파이프라인 실행 목록(성공/실패/소요시간)
gh run list --limit 10

# 실패한 실행의 어느 잡/단계에서 깨졌는지
gh run view <run-id> --log-failed | head -40
OUTPUT
$ gh run list --limit 5
STATUS  WORKFLOW   BRANCH   EVENT  ELAPSED
✓       ci         main     push   4m12s
✗       ci         main     push   1m03s   ← 실패! 1분에 멈춤 = 초반(빌드/테스트)
✓       deploy     main     tag    6m40s

$ gh run view --log-failed
  ✗ test: payment.spec.ts > 중복결제 방지   FAILED
    Expected 1 charge, got 2             ← 테스트가 회귀 버그를 잡음(게이트 작동)
gh run list --limit 10
🔍실행 후 확인할 것
  • 실패가 초반(빌드/테스트, 1~2분)에 났으면 코드/테스트 문제 — fail fast가 잘 작동한 것. 후반(배포 단계) 실패면 인프라/환경 문제로 의심 방향이 다르다
  • --log-failed에서 실패한 테스트 이름이 곧 회귀가 난 기능 — 그 테스트가 "막아준" 것이므로 게이트가 정상. 통과시켜 배포했다면 그 버그가 prod로 갔을 것
  • 파이프라인 소요시간이 점점 길어지면(예: 4분→15분) 개발 피드백 루프 악화 → 테스트 병렬화·캐시로 단축 검토(인프라 과제)
  • 같은 테스트가 돌릴 때마다 성패가 바뀌면(flaky) → 격리/수정. 방치하면 팀이 빨간불을 무시하기 시작해 게이트 전체가 무력화된다

상황: CI가 간헐적으로(테스트 flaky·환경 불안정) 실패하자 팀이 "또 그거겠지" 하며 빨간불을 무시하기 시작합니다. 그러다 진짜로 깨진 빌드가 main에 섞여, 정작 배포해야 할 때 파이프라인이 막혀 모두가 멈춥니다.

원인: 경보 피로(alert fatigue) 입니다. 신뢰할 수 없는 신호(자주 거짓 실패)는 사람을 무감각하게 만들어, 신호 자체의 가치를 파괴합니다. "초록이 의미 없는" 상태가 되면 게이트는 형식만 남습니다.

진단:

로컬 터미널
# 최근 실패들의 원인이 같은 flaky 테스트인지 패턴 확인
gh run list --status failure --limit 20 --json conclusion,displayTitle
# 동일 테스트가 반복 실패↔성공이면 flaky 확정

해결: (1) flaky 테스트를 즉시 격리(quarantine)해 메인 신호에서 분리하고 별도 수정. (2) "main은 항상 초록"을 깨는 커밋은 머지 금지(보호 규칙). (3) 빨간불이 뜨면 새 작업보다 복구를 우선(stop-the-line)하는 규범. 신뢰할 수 있는 파이프라인은 자동화의 양이 아니라 '신호의 정직함'에서 옵니다. 인프라/SRE가 이 신뢰를 지키는 책임자입니다.

심화 — 초록 파이프라인이 보장하지 않는 것

💡개념

심화: 검증한 것과 배포한 것이 같은 물건인가 — 빌드 한 번 원칙

단계와 게이트를 갖춰도 사고가 나는 영역이 남습니다. 대부분 "스테이징에서 검증한 것과 프로덕션에 배포한 것이 같은 물건인가"라는, 파이프라인 설계자만 답할 수 있는 질문에서 시작됩니다.

  • 한 번 빌드, 여러 번 승격(build once, promote): 환경마다 다시 빌드하는 파이프라인은 stg에서 검증한 바이너리와 prod 바이너리가 다를 수 있습니다 — 빌드 시각에 따라 딸려 들어가는 의존성 버전이 달라지기 때문입니다. 검증은 산출물(이미지 digest)에 하고, 승격은 같은 산출물을 다음 환경으로 옮기는 것이어야 합니다. 재빌드가 끼어드는 순간 stg 검증은 참고자료로 격하됩니다.
  • 파이프라인 정의도 코드이고, 공격 표면입니다: 서드파티 액션·플러그인을 버전 태그로 참조하면 그 태그는 소유자가 언제든 다른 커밋으로 옮길 수 있습니다 — 커밋 해시로 고정하는 것이 안전합니다. 파이프라인 파일의 변경은 곧 '배포 권한을 가진 코드'의 변경이므로 애플리케이션 코드와 같은 리뷰(PR과 코드 리뷰)를 거쳐야 합니다.
  • 캐시는 양날입니다: 의존성 캐시는 파이프라인을 몇 배 빠르게 하지만, 오염된 캐시는 "로컬에선 되는데 CI만 실패"(또는 그 반대)라는 미궁을 만듭니다. 원인 불명 실패의 표준 절차에 '캐시 무효화 후 재실행'을 넣어두면 조사 시간이 크게 줄어듭니다.
  • 속도는 문화가 됩니다: CI가 15분을 넘기 시작하면 개발자들은 커밋을 모아서 올리고(작은 통합 붕괴), 결과를 안 기다리고 다음 일로 넘어가며, '급하니 스킵하자'는 요청이 늘어납니다. 파이프라인 소요시간은 기술 지표가 아니라 팀의 행동을 바꾸는 조직 지표로 관리해야 합니다.

상황: PR 두 개가 10분 간격으로 머지돼 각각 배포 파이프라인이 돌았습니다. 먼저 머지된 커밋의 파이프라인은 테스트 재시도 때문에 25분 걸렸고, 나중 커밋의 파이프라인은 12분 만에 끝났습니다. 결과: 나중 커밋이 먼저 배포되고, 그 뒤 먼저 커밋의 배포가 완료되며 더 오래된 코드로 프로덕션을 덮어썼습니다. 두 실행 모두 초록이라 아무 경보도 없었고, 개발자는 자기 변경이 사라진 것을 다음 날에야 발견했습니다.

원인: 배포 잡에 동시 실행·순서 제어가 없습니다. 각 파이프라인은 자기 커밋 기준으로 각자 성공했을 뿐, "지금 prod에 떠 있는 것보다 내가 최신인가"는 아무도 검사하지 않습니다. 재시도로 소요시간이 역전되면 배포 순서도 함께 뒤집힙니다.

진단:

로컬 터미널
gh run list --workflow deploy --limit 5 --json headSha,startedAt,updatedAt
# run A(a1b2c3) 14:00 시작 → 14:25 완료
# run B(d4e5f6) 14:10 시작 → 14:22 완료  ← B가 먼저 끝나고 A가 나중에 덮음
kubectl get deploy app -o jsonpath='{.spec.template.spec.containers[0].image}'
# prod 이미지 태그가 a1b2c3(이전 커밋) → 역전 확정

해결: (1) 배포 잡에 동시성 제어를 겁니다 — 같은 환경으로의 배포는 한 번에 하나만 실행하고, 더 새 커밋이 대기 중이면 오래된 실행은 취소합니다(GitHub Actions의 concurrency group 등). (2) 배포 후 검증 단계에서 '배포된 버전 == 이 실행의 커밋'을 확인해 역전을 즉시 탐지합니다. (3) 구조적으로는 '커밋마다 배포 명령을 쏘는' 방식보다, 원하는 버전을 선언해 두면 시스템이 수렴하는 모델(GitOps)이 이 유형의 사고를 원천 차단합니다. 실행 하나하나는 옳았는데 겹치는 순간 사고가 되는 것 — 파이프라인을 잡 단위가 아니라 시스템으로 봐야 하는 이유입니다.

CI/CD 툴체인 — 단계별 도구 생태계확대 위 그림처럼 실제 CI/CD는 코드 관리·CI 서버·빌드·테스트·레지스트리·CD 배포 단계마다 전용 도구가 체인으로 연결됩니다.

💼
실무 맥락
현업 패턴

인프라/플랫폼 엔지니어로서 CI/CD 파이프라인은 당신이 만들고 지키는 핵심 자산입니다 — GitHub Actions·GitLab CI·Jenkins 등으로 빌드·테스트·스캔·배포를 코드로 정의하고, 브랜치 전략의 규칙(어느 브랜치/태그→어느 환경)을 파이프라인에 박습니다. 파이프라인 속도(피드백 루프)와 신뢰도(flaky 제거)를 함께 관리하는 것이 SRE의 일상입니다. PM은 CI/CD 덕분에 "머지=배포 후보"라는 빠른 흐름을 일정에 반영하고, Delivery 모델이면 배포 타이밍을 비즈니스 이벤트에 맞춰 통제합니다. 파이프라인은 단순 편의가 아니라, 변경을 안전하고 반복 가능하게 사용자에게 전달하는 조직의 동맥입니다.

다음 모듈에서는 이 파이프라인의 마지막 구간 — 프로덕션에 '어떻게' 내보낼지(블루그린·카나리·롤링·기능 플래그)를 다룹니다.

실전 랩으로 손에 익히기: CI/CD 파이프라인 설계 실습 — 파이프라인 단계·품질 게이트·배포 자동화를 직접 설계합니다.

지식 확인

퀴즈 — 8문제

Q1

CI(Continuous Integration)의 핵심은?

Q2

Continuous Delivery와 Continuous Deployment의 차이는?

Q3

전형적인 CI/CD 파이프라인 단계 순서로 적절한 것은?

Q4

파이프라인이 자주 빨갛게(실패) 뜨고 팀이 무시하기 시작할 때의 올바른 대응은?

Q5

CI(지속적 통합)의 핵심 효과는?

Q6

파이프라인이 실패했다. 원인을 빠르게 찾으려면?

Q7

[심화] 스테이징에서 충분히 검증했는데 프로덕션에서만 버그가 났다. 파이프라인이 환경마다 이미지를 다시 빌드하는 구조라면, 이 사고의 구조적 원인은?

Q8

[심화] PR 두 개가 10분 간격으로 머지돼 각각 배포 파이프라인이 돌았고 둘 다 초록인데, 프로덕션에는 더 오래된 커밋의 코드가 떠 있다. 원인 진단과 처방으로 옳은 것은?

0 / 8 답변

🧪 실습으로 확인하기

CI/CD 파이프라인 설계 — 단계·게이트·배포 자동화

중급

커밋에서 배포까지 흐르는 CI/CD 파이프라인을 설계한다. 단계(체크아웃·빌드·테스트·정적분석·아티팩트·배포)가 각각 무엇을 보장하는지 정하고, 통과 못하면 막는 품질 게이트를 걸고, 환경 승격·승인·자동 롤백까지 재현 가능한 흐름으로 확정한다.

55📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요