CI와 CD: 변경은 어떻게 검증되어 사용자에게 전달되는가
변경, 검증, 산출물, 환경 배포와 사용자 공개를 나누고 각 단계의 입력·출력·통과 조건으로 신뢰할 수 있는 전달 흐름을 설계한다.
목차
표준·구현·측정·해석 표시는 무엇인가요?
- 표준웹 표준이나 언어 명세가 정한 동작
- 구현특정 기술이나 브라우저가 실제로 구현한 동작
- 측정명시한 환경에서 직접 실행해 관찰한 결과
- 해석앞선 근거에서 도출한 설계 판단
- 미확인아직 공식 근거나 재현 결과를 확인하지 못한 내용
30초 요약
CI와 CD를 한 줄로 기억하려면 다음 흐름을 떠올린다.
변경 → 빠른 검증 → 산출물 → 산출물 검증 → 배포 → 공개
- 변경: 작은 코드 변경을 공유 기준선에 자주 합친다.
- 빠른 검증: 정한 검사로 이번 변경과 합쳐진 코드가 작동하는지 일찍 확인한다.
- 산출물: 다음 단계가 사용할 실행 가능한 결과를 만든다.
- 산출물 검증: 만들어진 결과가 실제 브라우저·서버·장치 경계에서 작동하는지 확인한다.
- 배포: 선택한 결과를 특정 실행환경이 사용하게 한다.
- 공개: 의도한 사용자가 새 기능이나 버전을 이용하게 한다.
검증은 한 칸으로 끝나지 않는다. 소스 변경을 빠르게 거르는 검증과 실제 산출물을 실행해야만
볼 수 있는 검증이 산출물 앞뒤에 놓인다. 파이프라인에 따라 일부 빌드와 테스트는 나란히
실행될 수 있지만, 무엇을 검증하는가라는 두 책임은 구분한다. 각 화살표에는 통과 조건이
있으며 앞 단계의 출력이 명확하고 조건을 통과했을 때만 다음으로 넘긴다. CI/CD라는 도구를
설치하는 것보다 이 책임과 실패 경계를 분명히 하는 일이 먼저다.
그리고 CD는 두 뜻으로 쓰인다.
- 지속적 전달(continuous delivery): 언제든 요청에 따라 목표 환경에 배포하고 정한 공개 경계까지 안전하게 전달할 수 있는 상태.
- 지속적 배포(continuous deployment): 통과한 각 변경을 운영 환경에 자동 배포하는 방식.
CI는 검사 서버보다 통합 습관이 먼저다
따라서 아래 셋은 서로 다르다.
- CI 서비스가 있다 — 자동 작업을 실행할 도구가 있다.
- 검사 작업이 있다 — 코드 규칙 검사인 lint, 타입 검사와 테스트 같은 일부 검증을 자동 실행한다.
- 지속적 통합을 한다 — 작은 변경을 자주 합치고 공통 기준선을 계속 작동 가능한 상태로 지킨다.
첫째와 둘째는 셋째를 돕지만 자동으로 보장하지 않는다. 브랜치가 몇 주씩 갈라져 있으면 각자 테스트가 통과해도 합치는 순간 큰 충돌과 여러 변경의 상호작용이 한꺼번에 나타난다. CI의 ‘continuous’는 서버가 계속 켜져 있다는 뜻이 아니라 통합과 피드백의 간격을 짧게 유지한다는 뜻에 가깝다.
합치기 전 통과와 합친 뒤 통과는 다른 증거다
코드 병합 요청인 풀 리퀘스트 A와 B가 같은 기준선에서 각각 통과해도 둘을 모두 합친 결과는 다를 수 있다.
main ──┬── A 검사 통과
└── B 검사 통과
main + A + B ← 합쳐진 이 상태는 아직 별도 증거가 없다.합치기 전 검사는 결함이 공유 기준선에 들어오는 것을 일찍 막는다. 합친 뒤 검사는 실제 공통 상태가 여전히 빌드되고 핵심 테스트를 통과하는지 확인한다. 두 검사는 경쟁 관계가 아니라 서로 다른 시점의 질문이다.
CI가 모든 테스트를 커밋마다 실행해야 한다는 뜻도 아니다. 9편의 원칙처럼 빠른 신호는 자주 실행하고, 실제 장치나 전체 시스템이 필요한 느린 검증은 별도 단계에서 실행할 수 있다. 다만 어떤 검사가 어느 단계의 통과 조건인지, 늦게 실패하면 어느 산출물과 배포를 막는지는 명시한다.
파이프라인은 입력·출력·통과 조건의 연결이다
| 단계 | 받는 것 | 남기는 것 | 다음 단계로 가는 조건 |
|---|---|---|---|
| 변경 접수 | 소스 리비전과 설정 | 식별 가능한 변경 | 리뷰·정책 통과 |
| 빠른 검증(변경 검증) | 변경과 선언된 환경 | 검사 결과와 실패 기록 | 필수 검사가 모두 신뢰 가능하게 통과 |
| 산출물 생성 | 검증할 소스와 빌드 입력 | 배포 후보 산출물 | 빌드 성공과 필요한 부가 정보 생성 |
| 산출물 검증 | 후보 산출물과 테스트 환경 | 통합·E2E·보안 등 결과 | 배포에 필요한 관문 통과 |
| 환경 배포 | 선택한 산출물과 환경 설정 | 실행 중인 버전과 배포 기록 | 환경 상태 확인 |
| 사용자 공개 | 배포된 버전과 공개 규칙 | 사용자에게 보이는 기능 | 공개 결정과 대상 조건 충족 |
리비전(revision)은 저장소의 특정 코드 상태를 식별하는 값이다. E2E(end-to-end, 시작부터 끝까지 잇는) 테스트는 사용자의 행동에서 여러 실제 시스템 부분을 거친 결과를 확인한다. 관문(gate)은 다음 단계로 넘어가기 위해 반드시 충족해야 하는 조건이다. ‘테스트’ 같은 작업 이름만 적지 말고 무엇을 검증하고 실패하면 무엇을 막는지까지 적는다.
모든 단계가 순차일 필요는 없다. 서로 같은 입력만 읽고 독립적으로 실패를 보고할 수 있는 lint, 타입 검사와 단위 테스트는 나란히 실행할 수 있다. 반대로 배포가 산출물 생성을 필요로 한다면 앞 단계가 끝나기 전에 실행해서는 안 된다. 병렬화는 필요한 선후 관계를 없애는 것이 아니라 실제 선후 관계만 남기는 일이다.
산출물은 단계 사이의 책임 경계다
산출물은 단순히 dist 폴더가 생겼다는 표시가 아니다. 다음 단계가 받을 구체적인 출력이다.
웹이라면 정적 파일 묶음이나 서버 실행 이미지가 될 수 있고, React Native라면 서명 전후의 앱
패키지와 JavaScript 번들이 될 수 있다.
여기서는 책임만 기억한다.
검증 단계가 통과시킨 결과와 배포 단계가 받는 결과 사이에 이름 없는 재생성이 끼어들지 않아야 한다.
어떤 식별값으로 같은 결과임을 증명하고, 개발·스테이징·운영 환경으로 어떻게 승격할지는 다음 11편에서 자세히 다룬다.
CD에는 두 뜻이 있다
지속적 전달의 목표는 ‘오늘 꼭 배포한다’가 아니라 지금 배포하라고 결정해도 특별 작업 없이 평소 절차로 할 수 있다는 상태다. 야간에만 가능한 수동 체크리스트나 한 사람의 노트북에서만 되는 빌드는 이 상태와 거리가 멀다.
따라서 팀 문서에서 CD만 쓰면 다음 질문을 붙인다.
- delivery인가 deployment인가?
- 자동화의 끝은 스테이징, 운영 배포, 사용자 공개 중 어디인가?
- 사람이 남기는 결정은 산출물의 품질 판단인가, 공개 시점 판단인가?
CI/CD 완료보다 main 통합 검증 뒤 운영 배포 후보를 만들고, 승인 시 같은 후보를 운영에 배포한다처럼 책임을 쓰는 편이 오해가 적다.
승인은 준비와 시점 결정을 구분한다
예를 들어 다음은 구분해야 한다.
- 시점 결정: 검증된 후보가 준비되어 있고 담당자가 ‘지금 운영에 배포’만 승인한다.
- 수동 제조: 담당자가 로컬에서 다시 빌드하고 파일을 골라 업로드하며 결과를 눈으로 확인한다.
첫 흐름에서는 사람의 판단을 보존하면서 기계가 같은 절차를 반복한다. 둘째 흐름에서는 승인자의 환경과 기억이 새 입력이 되므로, 기다리는 동안에도 실제 배포 가능성을 확신하기 어렵다.
승인이 적을수록 언제나 좋다는 뜻은 아니다. 규제, 보안, 스토어 정책과 사업 공개 시점처럼 필요한 결정은 남길 수 있다. 대신 승인자가 무엇을 판단하는지, 승인 전까지 기계가 무엇을 증명했는지, 거절하면 어느 단계로 돌아가는지를 기록한다.
배포와 사용자 공개는 분리될 수 있다
두 사건이 항상 분리되는 것은 아니다.
- 정적 웹 파일을 운영 저장소에 교체하면 다음 요청부터 모든 사용자가 새 화면을 받을 수 있다. 이 시스템에서는 배포와 공개가 사실상 붙어 있다.
- 새 코드를 운영 서버에 배포하되 기능 플래그를 끄면 사용자는 기존 동작을 본다. 이후 내부 사용자, 일부 사용자, 전체 사용자 순으로 플래그를 켤 수 있다.
- 모바일 앱 파일을 스토어에 제출해도 심사, 배포 설정과 사용자 설치가 남을 수 있다.
따라서 ‘운영 배포 성공’만으로 사용자 영향이 시작됐다고 단정하지 않는다. 반대로 기능을 끈 상태여도 새 코드가 초기화, 데이터 읽기나 공통 경로에 영향을 줄 수 있으므로 ‘공개 전에는 위험이 0’이라고 단정해서도 안 된다.
Web과 React에서는 실행 형태를 먼저 확인한다
React는 UI를 만드는 라이브러리이며 CI/CD 방식을 정하지 않는다. 같은 React 코드도 정적 사이트, 브라우저와 서버가 나뉜 앱, 서버가 첫 HTML을 만드는 서버 렌더링 앱에 들어갈 수 있다. 먼저 무엇을 배포해야 사용자가 실행할 수 있는가를 확인한다.
정적 Web 예시는 다음처럼 읽을 수 있다.
소스 변경
→ lint·타입·빠른 테스트
→ HTML·JavaScript·CSS 빌드
→ 빌드 결과로 브라우저 통합 테스트
→ 정적 호스팅 환경 배포
→ 경로 또는 기능 공개서버 렌더링 앱이라면 서버 실행 산출물, 프로그램 실행 중 읽는 런타임 설정과 데이터 변경이 더해질 수 있다. 브라우저 파일만 배포하고 서버 계약을 검증하지 않으면 사용자 요청 전체를 증명하지 못한다. 반대로 UI 문구만 바꾼 변경에 모든 장치 E2E를 직렬로 붙이면 피드백이 불필요하게 늦어질 수 있다. 9편에서 고른 실패를 볼 수 있는 가장 작은 충분한 테스트를 알맞은 관문에 배치한다.
개발 중 변경을 화면에 빠르게 반영하는 Fast Refresh가 동작한 것은 개발 피드백이다. 운영 설정의 빌드, 실제 호스팅 경로와 사용자 공개가 성공했다는 증거는 아니다.
React Native는 배포 채널과 설치 경계가 남는다
React Native의 네이티브 전달 흐름은 Web보다 경계가 더 많고, 선택한 배포 채널에서 갈라진다.
JavaScript·네이티브 소스 변경
→ JavaScript 검사와 테스트
→ iOS·Android 출시 설정 빌드
→ 서명된 앱 패키지
→ 장치·에뮬레이터 검증
├─ 내부·직접 채널 → 배포 → 허용한 사용자에게 사용 가능(공개)
└─ 스토어 채널 → 제출·심사 → 스토어 배포 설정 → 설치 가능(공개) → 사용자별 설치JavaScript 검사가 통과해도 iOS·Android용 기계어와 앱 패키지를 만드는 네이티브 컴파일, 서명, 권한과 앱 시작은 증명되지 않는다. 스토어를 선택했다면 제출 가능성과 심사·배포 경계도 별도로 남는다. 반대로 모든 JavaScript 분기를 실제 장치 E2E로 반복할 필요도 없다. 각 실패가 생길 수 있는 경계를 알맞은 단계에 둔다.
실패는 뒤 단계를 막고 증거를 남긴다
한 관문이 실패하면 해당 실행에서 나온 산출물을 아래 단계로 보내지 않는다. 먼저 실패를 세 종류로 나눈다.
- 변경 결함: 같은 입력에서 같은 코드나 테스트 오류가 재현된다. 변경을 고치거나 되돌린다.
- 검증 신호 결함: 같은 조건에서 통과와 실패가 오락가락한다. 공유 상태, 시간, 네트워크와 순서 의존성을 조사한다.
- 실행 환경 장애: 실행기 중단, 저장소 접근 실패처럼 제품 판단을 만들지 못했다. 환경을 복구한 뒤 같은 입력으로 다시 실행한다.
재시도는 마지막 두 경우를 진단하는 제한된 수단일 수 있다. 그러나 실패 로그와 입력 식별값을 지우고 초록색이 나올 때까지 반복하면 실제 결함과 불안정 신호를 구분할 수 없다. 파이프라인의 목표는 초록색 화면이 아니라 어떤 변경이 어떤 증거로 다음 단계에 갈 자격을 얻었는지 남기는 것이다.
파이프라인을 설계할 때 묻는 순서
새 전달 흐름이나 실패한 흐름을 볼 때 다음 일곱 문장을 차례로 적는다.
- 변경 단위: 어떤 소스 리비전과 설정을 검증하는가?
- 빠른 신호: 합치기 전후 몇 분 안에 어떤 실패를 알려야 하는가?
- 산출물: 다음 단계가 실제로 받는 파일이나 패키지는 무엇인가?
- 관문: 어떤 검사가 실패하면 어느 뒤 단계를 막는가?
- 배포 대상: 개발·스테이징·운영 중 어느 환경을 바꾸는가?
- 공개 조건: 배포와 동시에 모두에게 보이는가, 별도 대상·시점 결정이 있는가?
- 실패 기록: 입력, 실행 결과와 현재 배포·공개 상태를 어떻게 찾는가?
이 질문에 답한 뒤에야 공급자, 자동화 설정 파일의 문법과 병렬 실행 수를 고른다. 도구를 바꿔도 입력·출력·통과 조건의 책임은 남는다.
다음 글과의 경계
이번 글은 변경에서 공개까지의 단계와 책임을 나눴다. 다음 내용은 분리한다.
- 테스트한 결과와 배포한 결과가 실제로 같은가: 다음 11편 배포 산출물의 동일성과 승격
- 배포 뒤 어떤 신호로 상태를 판단하는가: 12편 관측성 신호
- JavaScript 업데이트가 설치된 네이티브 앱과 맞는가: 14편 앱 버전과 호환성 계약
- 스토어를 거치지 않는 업데이트의 허용 범위는 무엇인가: 15편 OTA 업데이트
- 사용자 범위를 어떻게 조금씩 넓히는가: 17편 점진 배포와 카나리 배포
- 실패한 배포를 멈추고 되돌리는 방법은 무엇인가: 18편 롤백
마지막으로 한 줄만 기억한다. 변경 → 빠른 검증 → 산출물 → 산출물 검증 → 배포 → 공개. 검증은 산출물 앞뒤에서 다른 실패를 보고, 각 화살표는 앞 단계의 출력과 통과 조건을 설명할 수 있어야 한다.
Active recall
기억에서 꺼내 보기
답을 쓰지 않아도 됩니다. 먼저 머릿속으로 답한 뒤 펼쳐서 정답·이유·흔한 오해를 비교하세요.
01풀 리퀘스트에서 자동 테스트가 실행되면 곧 지속적 통합일까?
정답
아니다. 작은 변경을 공유 기준선에 자주 합치고, 합치기 전후를 검증하며, 깨진 기준선을 우선 복구하는 작업 방식까지 있어야 한다.
관련 설명 다시 읽기왜 그런가
검사 도구가 있어도 브랜치가 오래 갈라지거나 합친 결과를 검증하지 않으면 통합 피드백은 늦어진다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
02CI/CD의 CD는 언제나 같은 뜻일까?
정답
아니다. 지속적 전달은 언제든 요청에 따라 안전하게 전달할 수 있는 능력이고, 지속적 배포는 통과한 각 변경을 운영 환경에 자동 배포하는 방식이다.
관련 설명 다시 읽기왜 그런가
팀 문서에서 CD가 어느 뜻인지 쓰지 않으면 자동화 범위와 공개 결정의 책임을 서로 다르게 이해할 수 있다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
03운영 배포 전에 사람이 승인하면 지속적 전달이 아닐까?
정답
검증된 산출물이 언제든 반복 가능한 절차로 배포 준비되어 있고 사람은 배포 시점만 결정한다면 지속적 전달과 양립할 수 있다.
관련 설명 다시 읽기왜 그런가
반대로 승인 뒤 사람이 다시 빌드하거나 검사·업로드 절차를 임의로 수행해야 한다면 요청 즉시 안전하게 전달할 준비가 된 상태라고 보기 어렵다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
04운영 환경에 배포하면 모든 사용자가 곧 새 기능을 쓰게 될까?
정답
항상 그렇지는 않다. 기능 플래그나 트래픽 규칙이 있으면 코드를 먼저 배포하고 사용자 공개를 나중에 할 수 있다.
관련 설명 다시 읽기왜 그런가
두 동작이 결합된 시스템도 있으므로 실제 공개 조건을 파이프라인에 명시해야 한다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
05React Native도 웹처럼 운영 서버 파일만 바꾸면 새 네이티브 버전이 배포될까?
정답
아니다. 네이티브 변경은 서명된 출시 빌드와 장치 검증을 거치며, 스토어를 통해 공개한다면 제출·심사·배포 설정과 사용자 설치 경계도 남는다.
관련 설명 다시 읽기왜 그런가
서버의 웹 파일을 바꾸는 동작만으로 새 iOS·Android 앱 패키지가 사용자 장치에 전달되지는 않는다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
출처와 검증 범위
아래 날짜는 링크를 마지막으로 열어 본 날입니다. 문서 상단의 검증일은 글의 설명과 적용 범위를 다시 확인한 날입니다.
- DORA Capabilities — Continuous integrationDORA, Google Cloud · 공식 문서 · 확인 2026-08-04
- DORA Capabilities — Continuous deliveryDORA, Google Cloud · 공식 문서 · 확인 2026-08-04
- Site Reliability Engineering — Release EngineeringGoogle SRE · 공식 문서 · 확인 2026-08-04
- Deployment environmentsGitHub Docs · 공식 문서 · 확인 2026-08-04
- AWS DevOps Guidance — Deploy changes to production frequentlyAmazon Web Services · 공식 문서 · 확인 2026-08-04
- Progressive experimentation with feature flagsMicrosoft Learn · 공식 문서 · 확인 2026-08-04
- Publishing to Google Play StoreReact Native · 공식 문서 · 확인 2026-08-04
- Publishing to Apple App StoreReact Native · 공식 문서 · 확인 2026-08-04
- Publish your appAndroid Developers · 공식 문서 · 확인 2026-08-04