신규 팀원이 묻습니다. "제 코드 main에 머지됐는데, 언제 실서버에 반영돼요?" 한 팀은 "자동으로 5분 뒤요", 다른 팀은 "담당자가 수동으로 새벽에 올려요"라고 답합니다. 배포 사고가 나자 한쪽은 "파이프라인 로그 보면 어느 단계서 깨졌는지 나와요", 다른 쪽은 "누가 뭘 올렸는지 아무도 몰라요"가 됩니다. CI/CD는 '머지된 코드가 어떤 자동화된 길을 거쳐 사용자에게 닿는가'입니다. 이 길이 있느냐 없느냐가 배포의 속도와 안전을 가릅니다.
- 1CI가 "자주 통합하고 자동 검증"하는 실천임을 설명할 수 있다
- 2Continuous Delivery와 Deployment의 차이를 "마지막 승인 자동화 여부"로 구분할 수 있다
- 3파이프라인 단계(빌드→테스트→산출물→배포)와 fail-fast 게이트를 설명할 수 있다
- 4파이프라인 실패가 무시되는 상황의 위험과 대응을 제시할 수 있다
CI — 자주 통합하고 즉시 검증
CI: 깨짐을 빨리 발견하는 안전망
CI(Continuous Integration)는 변경을 자주 통합하고, 통합할 때마다 자동으로 빌드·테스트해 문제를 즉시 잡는 실천입니다.
개발자 push / PR
│
▼ (CI 자동 트리거)
[체크아웃] → [빌드] → [자동 테스트] → [린트] → [보안 스캔]
│ 하나라도 실패하면
▼ 즉시 멈춤(fail fast) + 알림
"main은 항상 초록" 유지
CI의 심장은 [[test-strategy]]에서 다룰 자동 테스트입니다. [[code-review-pr]]의 머지 게이트가 "CI 통과"를 요구하므로, CI가 없으면 게이트도 무력합니다. CI는 [[branch-strategy]]의 Trunk-based(작게 자주 통합)를 가능하게 하는 전제이기도 합니다 — 통합할 때마다 자동 검증되니 자주 통합해도 안전합니다.
CD — 전달 vs 배포
언제든 배포 가능 vs 통과하면 곧장 배포
CD는 두 가지를 뜻할 수 있어 맥락으로 구분합니다.
- Continuous Delivery(지속적 전달): 테스트 통과 후 '언제든 배포 가능한 산출물' 까지 자동으로 준비. 프로덕션 배포 '실행'만 사람이 버튼을 누름. → 배포 타이밍을 비즈니스가 통제.
- Continuous Deployment(지속적 배포): 마지막 승인까지 완전 자동. 파이프라인을 통과하면 사람 개입 없이 프로덕션으로. → 자동화·테스트 신뢰가 높은 팀.
CI ──▶ Delivery: ...테스트 통과 → 산출물 준비 → [사람이 승인] → prod
CI ──▶ Deployment: ...테스트 통과 → 산출물 준비 → 자동 → prod (개입 없음)
PM 관점: Delivery면 "배포 시점"을 마케팅·릴리스 일정에 맞출 수 있고(기능 플래그와 함께 더 유연), Deployment면 "머지 = 곧 출시"이므로 작은 변경을 빠르게 내보냅니다. 어느 쪽이든 [[release-strategy]]의 점진 배포(카나리 등)와 결합해 위험을 관리합니다.
파이프라인 읽기 — 직접 확인
배포 사고나 지연 시, 파이프라인 로그가 "어느 단계에서 무엇이 깨졌나"를 알려줍니다. 코드를 못 짜도 단계별 성패는 읽을 수 있습니다.
# 최근 파이프라인 실행 목록(성공/실패/소요시간)
gh run list --limit 10
# 실패한 실행의 어느 잡/단계에서 깨졌는지
gh run view <run-id> --log-failed | head -40
$ 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가 이 신뢰를 지키는 책임자입니다.
인프라/플랫폼 엔지니어로서 CI/CD 파이프라인은 당신이 만들고 지키는 핵심 자산입니다 — GitHub Actions·GitLab CI·Jenkins 등으로 빌드·테스트·스캔·배포를 코드로 정의하고, [[branch-strategy]]의 규칙(어느 브랜치/태그→어느 환경)을 파이프라인에 박습니다. 파이프라인 속도(피드백 루프)와 신뢰도(flaky 제거)를 함께 관리하는 것이 SRE의 일상입니다. PM은 CI/CD 덕분에 "머지=배포 후보"라는 빠른 흐름을 일정에 반영하고, Delivery 모델이면 배포 타이밍을 비즈니스 이벤트에 맞춰 통제합니다. 파이프라인은 단순 편의가 아니라, 변경을 안전하고 반복 가능하게 사용자에게 전달하는 조직의 동맥입니다.
다음 모듈에서는 이 파이프라인의 마지막 구간 — 프로덕션에 '어떻게' 내보낼지(블루그린·카나리·롤링·기능 플래그)를 다룹니다.