CI/CD 파이프라인과 배포 전략의 기준
CI/CD의 기본 흐름을 격리된 빌드, 불변 아티팩트, 파이프라인 as Code 관점에서 정리한다. OIDC 인증, 배포 전략 선택, 캐시 최적화, 주요 장애 진단 포인트까지 함께 짚는다.
Script Companion
오디오와 함께 스크립트 보기
- 01
BackOps에서 배포는 반복되는 일상 업무다. 코드를 머지한 뒤 서버에 반영되기까지 어떤 단계가 이어지는지 모르면, 배포 실패가 났을 때 어느 지점을 봐야 하는지 알기 어렵다. CI/CD는 단순히 자동으로 배포해 주는 장치가 아니라, 빌드와 테스트와 배포를 재현 가능한 흐름으로 묶어 개발자 경험을 개선하는 기반이다. 플랫폼 엔지니어링에서 배포 자동화가 체감이 큰 이유도 여기에 있다다라기보다는, 팀이 매일 겪는 대기 시간과 불확실성을 직접 줄이기 때문이다.
- 02
CI, Continuous Integration은 코드를 공유 브랜치에 자주 머지하고, 머지할 때마다 자동으로 린트, 테스트, 빌드를 실행하는 방식이다. 핵심 목적은 깨진 코드가 메인 브랜치에 들어가는 것을 막는 데 있다. CD는 두 의미로 나뉜다. Continuous Delivery는 배포 가능한 상태까지 자동화하되 실제 배포에는 수동 승인이 남아 있고, Continuous Deployment는 테스트를 통과하면 프로덕션 배포까지 자동으로 이어진다. 그래서 CI/CD를 볼 때는 자동화 범위가 어디까지인지 먼저 구분해야 한다.
- 03
도구가 GitHub Actions든 GitLab CI든 Jenkins든 CircleCI든, CI/CD 파이프라인에는 변하지 않는 판단 기준이 있다. 첫째, 매 실행은 클린한 격리 환경에서 시작해야 한다. 그래야 내 로컬에서는 됐다는 식의 차이를 줄일 수 있고, Docker 컨테이너는 이 격리를 보장하는 표준 수단이다. 둘째, 빌드 단계에서 만든 이미지나 바이너리는 테스트, 스테이징, 프로덕션에서 같은 아티팩트로 이동해야 한다. 환경마다 다시 빌드하면 재현성이 깨진다. 셋째, 파이프라인 설정 파일은 앱 코드와 같은 git 저장소에 두어 PR 리뷰와 롤백이 가능해야 한다.
- 04
GitHub Actions를 예로 보면, 워크플로 파일 하나 뒤에도 분명한 실행 흐름이 있다. GitHub이 push나 pull_request 같은 이벤트를 감지하고, GitHub이 관리하는 Ubuntu VM인 Runner를 할당한 뒤, YAML에 정의된 Jobs와 Steps 순서대로 실행한다. 결과는 PR 체크 상태로 표시된다. 중요한 점은 Runner가 매 실행마다 새로 초기화되는 격리된 VM이라는 것이다. 이전 실행의 파일이나 환경이 남지 않으므로, actions checkout이나 npm ci 같은 준비 단계가 항상 필요하다. 캐시를 잘 활용하면 이 클린 실행 구조를 유지하면서도 빌드 시간을 줄일 수 있다.
- 05
인증에서는 OIDC가 중요한 전환점이다. GitHub Actions가 AWS에 자신이 어떤 Repository에서 실행된 워크플로인지 증명하면, AWS가 짧게 살아 있는 임시 자격증명을 발급하는 구조다. 영구적인 AWS_ACCESS_KEY를 GitHub Secrets에 저장하지 않아도 되고, 장기 자격증명이 유출되어 무기한 악용되는 위험도 줄어든다. IAM 신뢰 정책에서 특정 Repository와 브랜치만 역할을 가정할 수 있게 제한하면 더 안전하다. 이 흐름은 AWS만의 특수 기능이 아니라 OIDC Workload Identity Federation이라는 공통 패턴이다. AWS, GCP, Azure 모두 subject 클레임으로 특정 저장소와 브랜치만 신뢰하도록 제한할 수 있다.
- 06
파이프라인 속도는 개발자 경험과 바로 연결된다. 문서에서 강조하는 핵심 캐시는 두 가지다. npm 캐시는 package-lock.json이 바뀌지 않았을 때 의존성 설치를 다시 하지 않게 돕고, Docker 레이어 캐시는 package.json이 바뀌지 않았을 때 npm install 레이어를 재실행하지 않게 한다. CI가 PR마다 5분에서 10분씩 걸리고 npm install이 매번 전체 재실행된다면, 캐시가 빠져 있는지 먼저 봐야 한다. 빠른 파이프라인은 단지 기분 좋은 최적화가 아니라, 리뷰와 머지와 배포의 반복 속도를 실제로 바꾸는 요소다.
- 07
배포 전략은 Rolling, Blue-Green, Canary로 나눠 볼 수 있다. Rolling은 인스턴스를 하나씩 교체하는 기본 전략이고, 인프라 비용이 낮지만 롤백에는 재배포가 필요해 느릴 수 있다. Blue-Green은 새 버전을 별도 환경에 띄운 뒤 트래픽을 한 번에 전환하므로, 롤백이 1분 이내로 빨라야 하는 SLA 조건에서는 강제될 수 있다. 대신 두 배 환경이 필요해 비용이 높다. Canary는 새 버전에 트래픽 일부만 보내고 검증한 뒤 전체 전환한다. 새 기능의 비즈니스 임팩트를 실데이터로 확인해야 한다면 Canary가 유일한 선택으로 제시된다.
- 08
DORA 관점에서는 배포 전략이 배포 빈도, 변경 실패율, MTTR, 리드타임에 영향을 준다. Rolling은 배포 빈도와 리드타임에는 유리하지만 즉시 전체 노출되기 때문에 변경 실패율이 높아질 수 있고, 재배포가 필요해 MTTR이 느릴 수 있다. Blue-Green은 환경 준비 시간이 있어 배포 빈도는 중간이지만, 트래픽 전환으로 복구할 수 있어 MTTR이 1분 미만으로 제시된다. Canary는 단계별 검증 때문에 리드타임은 길지만, 소수 사용자에게 먼저 노출하므로 변경 실패율을 낮추는 데 유리하다. 결제나 인증처럼 에러율이 1%를 넘으면 즉시 롤백해야 하는 서비스는 Blue-Green 판단이 강해진다.
- 09
실제 장애 진단에서는 파이프라인 단계와 배포 후 런타임을 나눠 봐야 한다. 워크플로가 아예 실행되지 않으면 on 트리거 조건과 실제 브랜치가 맞는지, 파일이 .github/workflows 아래에 있는지 확인한다. npm ci가 CI에서만 실패하면 package.json과 package-lock.json의 싱크, 그리고 lock 파일 커밋 여부를 봐야 한다. GitHub Actions 단계는 모두 성공했는데 ECS 배포 후 502가 난다면, 이미지 빌드 성공과 서비스 정상 동작을 분리해서 생각해야 한다. ECS 서비스 Events, 태스크 RUNNING 여부, Stopped Reason, 헬스체크 실패나 OOM 가능성, NestJS 앱의 health 엔드포인트 여부를 확인하는 흐름이 필요하다.
- 10
보안 쪽에서는 시크릿과 외부 액션 버전을 함께 조심해야 한다. AWS 자격증명과 API Key는 코드에 직접 넣지 않고 GitHub Secrets나 AWS Secrets Manager를 통해 환경변수로 주입한다. Secrets가 빈 값으로 처리된다면 Repository Secrets와 Environment Secrets의 위치 차이, fork된 PR에서 Secrets가 노출되지 않는 보안 정책, 이름의 대소문자 오타를 확인해야 한다. Action 버전도 main 브랜치를 따라가게 두면 외부 의존성 위험이 생길 수 있으므로, v4 같은 특정 버전 태그나 커밋 SHA로 고정한다. 정리하면 CI/CD는 Push, 빌드, 테스트, 이미지 생성, 배포를 자동화하되, 격리된 실행과 불변 아티팩트와 안전한 인증이라는 기준으로 봐야 한다.
같은 레이어
L5에서 이어 듣기
- 오디오 파일
- /podcasts/l5-cicd-basics.mp3