CI/CD란?

기능은 완성했는데 다른 사람의 코드를 합치는 데 오래 걸리고, 배포할 때마다 같은 명령어를 사람이 반복한다면 무엇부터 바꿔야 할까요?

CI/CD는 변경을 작게 통합하고, 반복 가능한 검증을 거쳐, 사용자에게 전달하는 과정입니다. 도구를 설치하는 것만으로 완성되지는 않습니다. 통합 주기와 실패에 대응하는 팀의 방식까지 포함해 이해해보겠습니다.

2022년에 정리한 개념을 바탕으로, Delivery와 Deployment의 차이, 프론트엔드 적용 예시와 운영 확인 절차를 보완했습니다.

CI: 자주 합치고 바로 확인한다

Continuous Integration, 지속적인 통합은 팀원들이 변경을 자주 공통 코드베이스에 통합하고 자동 빌드·테스트로 오류를 빠르게 찾는 개발 방식입니다. Martin Fowler의 설명은 적어도 매일 통합하는 실천을 강조합니다.

핵심은 커밋 횟수 자체가 아닙니다. 각자 브랜치에서 한 달 동안 테스트를 돌려도 서로의 변경을 합치지 않았다면 통합 위험은 쌓입니다. 텍스트 충돌이 없어도, 한 사람이 바꾼 API 응답과 다른 사람이 작성한 화면의 가정이 어긋날 수 있어요.

오래 분리된 코드 변경을 합칠 때 발생하는 충돌 예시 Merge Conflict는 통합 문제 중 눈에 잘 보이는 한 종류입니다.

작게 통합하면 한 번에 확인할 변화가 줄어 원인을 찾기 쉬워집니다. 아직 사용자에게 공개할 수 없는 기능은 기존 동작을 유지하는 작은 변경으로 나누거나 기능 플래그로 노출을 제어할 수 있습니다. 플래그도 제거 시점과 관리 책임이 필요하고요.

PR 검증과 통합 후 검증은 역할이 다르다

시점 확인하려는 것 실패하면
PR 생성·수정 변경을 합쳐도 될 만큼 기본 검증을 통과하는가? 수정 후 다시 검증
공통 브랜치에 통합 실제로 합쳐진 코드 전체가 동작하는가? 원인 수정 또는 해당 변경 되돌리기
배포 전 검증한 산출물이 목표 환경에서 실행 가능한가? 배포 중단
배포 후 실제 사용자 경로가 정상인가? 원인에 따라 롤백·수정 배포

PR 검증이 성공한 뒤 다른 변경이 먼저 합쳐질 수 있습니다. 그래서 PR 성공 표시와 실제 공통 브랜치의 상태가 언제나 같은 것은 아닙니다. 통합 결과에 대한 검증이 필요합니다.

코드 변경부터 빌드와 테스트로 이어지는 CI 구성 CI 파이프라인의 기본 구성

CI가 실패했는데 계속 변경을 쌓으면 어느 변경부터 깨졌는지 모호해집니다. 깨진 공통 브랜치를 빠르게 복구하고, 실패한 단계와 로그를 누구나 볼 수 있게 만드는 일도 CI에 포함됩니다.

CD는 두 가지 뜻으로 쓰인다

구분 자동화하는 범위 운영 배포 결정
Continuous Delivery, 지속적 제공 검증과 배포 준비를 자동화하고 배포 가능한 상태 유지 사람이 시점을 결정할 수 있음
Continuous Deployment, 지속적 배포 검증을 통과한 변경을 운영 환경까지 자동 배포 별도의 수동 승인 없이 진행

Delivery에서 “수동”일 수 있는 것은 배포 결정입니다. 사람이 서버에 접속해 파일을 복사해야 한다는 뜻은 아닙니다. 반대로 Deployment도 검증 없이 무조건 배포한다는 뜻은 아니에요. Continuous Delivery 원문은 배포 가능한 상태 유지와 실제 운영 배포를 구분합니다.

고객사별 설치 일정이 있는 구축형 제품은 매 변경을 즉시 운영에 배포하지 않아도 됩니다. 검증한 설치 패키지를 언제든 제공할 수 있다면 Delivery의 가치를 얻을 수 있어요. 배포 빈도만으로 팀의 수준을 평가하기 어려운 이유입니다.

프론트엔드 프로젝트라면 무엇을 자동화할까?

React·TypeScript 프로젝트를 가정해봅시다. 다음은 특정 CI 서비스의 설정이 아니라, 로컬과 CI가 공통으로 실행할 수 있는 명령 예시입니다. 각 스크립트는 프로젝트에 실제로 정의되어 있어야 합니다.

1
2
3
4
5
npm ci
npm run lint
npm run typecheck
npm run test:ci
npm run build

test:ci는 테스트 러너가 감시 모드로 기다리지 않고 종료하도록 설정합니다. typecheck는 TypeScript 검사, build는 배포 산출물 생성을 맡깁니다. 사용하는 번들러의 빌드 성공이 타입 검사 성공까지 의미하는지 확인해야 합니다.

npm ci는 lockfile을 기준으로 의존성을 설치하고, package.json과 lockfile이 맞지 않으면 실패합니다. Node.js와 패키지 관리자 버전도 팀이 검증한 범위로 맞춰야 “내 컴퓨터에서는 된다”는 차이를 줄일 수 있습니다. npm ci 공식 문서에 설치 조건과 옵션이 정리돼 있습니다.

모든 검증을 무겁게 만들 필요는 없습니다. 빠른 정적 검사와 핵심 로직 테스트를 먼저 두고, 실제 장애 위험이 큰 사용자 흐름을 브라우저 테스트로 확인하는 식으로 비용을 배분하면 됩니다. 간헐적으로 실패하는 테스트를 방치하면 팀이 빨간 표시를 무시하게 되므로 원인을 고치거나 책임자와 복구 기한을 정해야 합니다.

빌드 성공에서 배포 성공까지

예를 들어 프론트엔드 빌드는 성공했지만 배포 경로 설정이 틀렸다면 JS 파일은 404가 될 수 있습니다. 로그인 쿠키나 API 주소가 환경과 맞지 않으면 첫 화면 이후의 흐름이 깨질 수도 있어요.

그래서 배포 과정을 설계할 때 다음 질문을 함께 둡니다.

  1. 무엇을 배포했는가? 커밋과 산출물 버전을 연결합니다. 가능하면 검증한 산출물을 승격하고, 환경별 재빌드가 필요하다면 그 산출물도 다시 검증합니다.
  2. 어떤 경로가 살아 있어야 하는가? 페이지 응답뿐 아니라 핵심 정적 파일, 대표 탐색·조회 흐름까지 배포 후 확인합니다.
  3. 되돌릴 수 있는가? 이전 산출물을 보관하고 복구 절차를 확인합니다. DB 변경이 있으면 이전 코드와의 호환성도 따져야 합니다.
  4. 누가 실패를 확인하는가? 배포 상태와 사용자 오류 지표를 연결하고 대응 책임을 정합니다.

자동화가 충분한지는 YAML 파일의 길이보다 변경 후 피드백까지 걸리는 시간, 배포 실패와 복구에 드는 시간으로 판단하는 편이 좋겠습니다. 처음이라면 팀 누구나 같은 명령으로 검증하고, 합쳐진 코드가 깨지면 바로 알 수 있게 만드는 것부터 시작해도 좋습니다.