되돌아오는 질문은 편의 경계를 가로지른다 — 고를 때·터졌을 때·설명해야 할 때

CI/CD 일곱 편의 마지막. 앞 여섯 편이 나눠 답한 것을 질문이 오는 세 자리로 다시 세운다 — 고를 때·터졌을 때·설명해야 할 때.

막아야 할 것이 왔을 때 게이트가 정말 막는지는 무엇으로 아는가.

편6이 이 물음으로 닫혔다. 답은 마지막 절에 있다. 되돌아오는 질문은 성질이 같다 — 「롤백이 안 된다」 하나가 컨테이너 편과 무중단 편에 걸리듯 편의 경계를 가로지른다. 그래서 주제별로 훑지 않고 질문이 오는 세 자리로 나눈다.

자리언제 쓰나무엇이 놓이나
고를 때아직 아무것도 정하지 않았다선택지 열 갈래와 트레이드오프
터졌을 때멈췄거나, 멈췄어야 하는데 안 멈췄다실패 모드 열셋과 증상
설명해야 할 때그 선택의 근거를 남에게 대야 한다문답 스물아홉과 심화 다섯

앞 여섯 편이 이미 답한 것은 다시 설명하지 않는다 — 한 문장으로 답하고 그 편을 가리킨다. 새로 쓰는 자리는 장단점만 놓고 넘긴 자리에 선택 기준을 주는 곳과 처음 쓰는 곳뿐이다.

고를 때

열 갈래에 어느 편이 다뤘는지를 붙였다. 기준은 「무엇이 좋은가」가 아니라 「무엇을 내줄 수 있는가」다.

선택지얻는 것내주는 것언제 고르나앞 편
GitHub Actions설정이 간단하고 저장소와 동거한다자유도 한계, Private 과금, 사내망에 러너 필요표준적 빌드·테스트편4
Jenkins자유도가 최고, 사내망·규제 대응서버·플러그인 운영 부담, 설정이 UI에 갇힌다복잡한 다단계 배포편5
GitHub-hosted Runner관리 불필요, 매번 깨끗하다6시간 제한, 느리고 사내망에 안 닿는다빌드·테스트편4
Self-hosted Runner빠르고 제한이 없고 내부망에 닿고 배포 대상이 곧 러너다머신의 보안·유지 책임, 상태 오염배포, 장시간 빌드편4
Freestyle즉시 만들 수 있다코드가 아니라 감사도 복구도 안 된다일회성 작업편5
Declarative Pipeline가독성, SCM 관리, stage별 agent절차적 표현에 제약기본 선택편5
Merge Commit이력 보존, 되돌릴 대상이 명확히스토리가 복잡해진다공유 브랜치 통합편3
Rebase선형 이력이라 리뷰가 편하다히스토리 재작성 — 공유 브랜치에 위험개인 feature 정리편3
Blue-Green즉시 롤백인프라가 2배결제·핵심 서비스편6
Rolling추가 비용이 없다롤백이 느리고 신·구가 공존한다인스턴스가 다수편6

도구 · 실행 머신 · 정의 방식 · 병합 방식 · 배포 전략 다섯 짝이고 왼쪽이 편한 쪽, 오른쪽이 통제되는 쪽이다(6시간 제한·Private 과금·동적 조회 미지원은 2026년 7월 기준). 도구 두 행만 기본값이 없어 여기서 닫는다.

21 — GitHub Actions와 Jenkins의 선택 기준

「둘 다 알아야 한다」는 결론은 편1이 이미 냈다. 여기서 낼 것은 새로 세울 때 어느 쪽인가이고 판정은 대칭이 아니다 — 기본값은 GitHub Actions, Jenkins는 아래 셋 중 하나라도 참일 때다.

조건왜 이것만으로 갈리나
배포 시점에 사람이 목록에서 골라야 한다브랜치·태그의 동적 조회가 Actions의 대표 미지원 항목이다. 우회는 되지만 그 우회가 파이프라인의 본체가 된다
파이프라인 정의의 소유자가 앱 개발자와 다르다워크플로 파일이 앱 저장소에 동거하는 것이 Actions 모델의 전제다. 소유자를 가르는 선택지는 Jenkins에만 있다
파이프라인이 임의 로직을 돌려야 한다조건·반복·외부 호출이 YAML의 표현 범위를 넘으면 Groovy가 필요하다

사내망 접근은 이 목록에 없다. 가장 자주 들리는 근거지만 조건이 못 된다 — self-hosted 러너는 설치가 간편해 하나만 붙이면 Actions도 사내망에서 돈다.

push로 배포할 것인가 — 트리거가 배포 대상을 정한다

편4가 트리거 셋에 「배포 대상이 다르다」까지만 적었다. 위의 열 갈래에 무엇이 배포를 시작시키는가라는 축이 없다.

트리거올릴 것이 정해지는 시점그것을 부르는 이름되돌릴 때
push커밋이 들어오는 순간없다 — 브랜치가 그때 가리키던 커밋무엇으로 되돌릴지를 로그에서 다시 찾는다
release릴리즈를 게시하는 순간태그이전 릴리즈를 다시 게시한다
workflow_dispatch실행 버튼을 누르는 순간입력칸에 적힌 태그직전 태그를 적어 한 번 더 돌린다

셋째 열이 판정을 끝낸다. 되돌릴 것을 이름으로 지목해야 하면 push는 탈락하고, 남는 선택은 게시와 배포를 붙일 것인가 뗄 것인가다. 승인 게이트가 있는 도메인은 떼는 쪽이다 — 승인은 운영 반영 직전에 받기 때문이다.

터졌을 때

원인이 아니라 증상에서 출발하는 표다. 오른쪽 끝이 비어 있는 하나는 이 절이 답한다.

실패 모드 · 증상원인대응앞 편
헬스체크 게이트 무력화 — 죽은 앱에 트래픽이 간다재시도 조건 오류, 헬스 응답이 늘 200종료 코드 검증, 조건의 단위 테스트, 의존성 확인
디스크 풀no space left on device미사용 이미지·컨테이너 누적배포 끝에 docker system prune -f, 사용률 알람편3
배포 중 다운타임 — 요청 실패·5xx죽인 뒤 재기동하는 방식무중단 전략 — 교체를 트래픽 경로 밖으로편6
시크릿 유출 — 토큰이 저장소·로그에 남는다하드코딩, 키 파일 삭제 누락자격증명 저장소 강제, 유출 즉시 폐기·재발급편6
러너 오염 — 간헐적으로만 실패한다이전 빌드 잔여물, 전역 설정 변경워크스페이스 정리 옵션, 컨테이너 러너편4·편5
좀비 빌드가 슬롯 점유 — 큐 적체승인 대기·네트워크 무한 대기options { timeout }, 고착 빌드 강제 종료편5
강제 푸시로 히스토리 파괴 — 커밋이 사라진다공유 브랜치에서 이력을 다시 써 밀었다보호 브랜치, 공유 브랜치는 revert편2·편3
reset --hard로 작업 유실 — 커밋 안 한 변경이 사라진다어느 트리까지 가는 명령인지 몰랐다사전 stash, 스크립트의 대상 경로 검증편2
Job 간 파일 전달 실패 — deploy에 jar가 없다다른 머신인데 넘어갈 것으로 가정했다업로드·다운로드 액션으로 아티팩트를 경유편4
아키텍처 불일치exec format errorARM에서 빌드한 이미지를 x86에 올렸다docker build --platform linux/amd64 명시편3
웹훅 미수신 — 커밋해도 빌드가 안 돈다닿을 공인 주소가 없거나 방화벽이 막는다전송 이력 확인, 터널링, 차선은 Poll SCM편5
정적분석이 형식적 통과 — 취약점이 계속 유입Gate가 파이프라인을 실패시키지 않는다Gate 실패를 빌드 실패로 연결, 신규 코드 기준편6
DB 스키마 비호환 — 배포 중에만 에러가 난다신·구 공존 구간을 전제하지 않았다하위 호환 마이그레이션(확장 → 배포 → 정리)편6

정리 작업 셋(prune·키 파일 삭제·워크스페이스 정리)을 성공 경로에만 달면 실패가 쌓일 때 정리도 멈춘다. Actions의 if: always(), Jenkins의 post { always }가 그 자리인데 편5는 이름만 적었고 정리를 실패 경로에도 단다는 규칙은 없었다. 편5의 원격 유발 curl이 받는 403도 방화벽이 아니라 CSRF 보호라, crumb 토큰을 헤더에 실어야 한다.

아키텍처 불일치만 다르다. 빌드도 푸시도 성공하고 띄우는 순간에만 죽는다 — 틀린 것이 코드가 아니라 이미지의 대상 아키텍처여서다.

실패를 실패로 만들지 못하는 게이트

편6은 헬스체크 스크립트를 결함째 실었다 — 다섯 번 도는 루프에서 열 번째를 기다리는 조건이라 실패 갈래가 한 번도 안 돈다. 그 결론에 그래서 어떻게 하는가를 붙인다.

순서무엇을 하나무엇을 막나
판정을 종료 코드로만 한다루프가 정상 종료한 것이 통과로 읽히는 것
조건을 의도적으로 실패시켜 파이프라인이 멈추는지 본다조건식의 오프바이원이 조용히 사는 것
헬스 엔드포인트가 의존성까지 확인하게 만든다DB에 못 붙은 상태가 200으로 나가는 것

②만 다르다. 편6이 「안 닫히는 게이트는 있다는 것만 보인다」로 닫은 자리이고, 아는 방법은 막아야 할 것을 넣어 보는 것뿐이다 — 이 성질이 마지막 절까지 이어진다.

배포가 실패했는데 롤백이 안 된다

편1이 이 편에 배정한 질문이고 위 표 열셋 어디에도 없다. 실패 모드 목록은 「무엇이 터지는가」를 세지 「되돌아갈 곳이 있는가」는 세지 않는다. 편6의 답은 전환을 한 번 더 하는 조작이라 되돌릴 것이 남아 있을 때만 선다. 없는 경우가 셋이다.

없는 것어떻게 없어졌나되돌리는 대신 해야 하는 것
되돌아갈 산출물태그를 고정하지 않고 늘 같은 이름을 덮어썼다지금 도는 것과 직전 것에 다른 이름을 남기는 규칙이 먼저다. 없으면 롤백이 재빌드가 된다
되돌아갈 이력공유 브랜치에서 이력을 다시 쓰고 강제로 밀었다원격이 덮여 로컬 사본과 reflog를 뒤지는 복구가 된다. 예방은 보호 브랜치뿐이다
되돌릴 수 없는 상태배포와 함께 스키마를 파괴적으로 바꿨다코드를 되돌려도 데이터는 안 돌아온다

셋째가 가장 자주 물린다. 스키마 변경은 롤백의 대상이 아니라 롤백의 제약이다. 컬럼을 지우는 변경을 배포와 같은 순간에 반영하면 이전 버전 코드가 그때부터 못 돌아, 멀쩡한 이미지로 되돌려도 더 크게 터진다. 편6이 적은 걸음 나눔이 롤백 쪽에서 다시 읽힌다 — 걸음이 각각 다른 배포에 실려야 그 사이 어디서든 되돌아갈 자리가 생긴다.

설명해야 할 때

근거를 말로 옮기는 자리다. 스물아홉 문답이 먼저이고 줄이면 손해인 다섯을 뒤에 두었다. 답이 길어지면 그 편의 몫이라 오른쪽 열을 따라간다.

#질문어디
1CI와 CD를 구분해서 설명하라CI는 자주 합쳐 자동 빌드·테스트하는 쪽, CD는 릴리즈 가능 상태를 지키는 Delivery와 운영 반영까지 자동인 Deployment로 갈린다편1·편2
2git fetch --all은 무엇을 하나원격의 메타데이터와 객체를 .git으로만 내려받고 작업 디렉터리를 안 건드려 충돌할 자리가 없다편2
3reset --hard로 원격에 맞추는 위험은포인터·Stage·작업 디렉터리를 한꺼번에 덮어, 커밋 안 한 변경은 복구되지 않는다편2
4fetch와 pull의 차이pullfetch 다음 merge이고, 갈리는 것은 속도가 아니라 몇 번째 트리까지 가는가편2 · 심화 ①
5reset 세 모드의 차이되돌리는 범위가 포인터만 / 포인터와 Stage / 작업 디렉터리까지로 한 트리씩 넓어진다편2
6reset과 revert 중 무엇을 쓰나공유 브랜치는 되돌리는 새 커밋을 얹는 revert, 공개 전 이력 정리는 reset이다편2
7Fast-forward와 3-way merge의 차이베이스에 변경이 없으면 포인터만 옮기고, 갈라졌으면 셋을 견주어 병합 커밋을 만든다편3
8merge와 rebase 중 무엇을 쓰나이력 보존이면 merge, 선형 이력이면 rebase이며 공유 브랜치 rebase는 금지다편3
9Detached HEAD 상태란HEAD가 브랜치가 아니라 과거 커밋을 직접 가리켜, 여기서 커밋하면 부를 이름이 없다편2
10브랜치 전략을 어떻게 고르나릴리즈 주기·동시 지원 버전·자동화 성숙도·규제라는 조직 조건으로 정하며 은총알은 없다편3
11PR을 강제하는 이유운영에 배포되는 브랜치 앞에 리뷰·자동 검증·승인 수를 게이트로 세우려는 것이다편3
12컨테이너와 VM의 차이VM은 Guest OS를 따로 구동하고 컨테이너는 커널을 빌려 프로세스만 갈라, 빌드 결과를 그대로 나른다편3
13Dockerfile 최적화 방법안 바뀌는 명령을 위로 올려 캐시를 살리고, 멀티스테이지로 줄이며, --platform을 명시한다편3
14Workflow·Job·Step·Runner의 관계이벤트가 Workflow를, Workflow가 Job을, Job이 Runner 한 대의 Step을 가지며 Job끼리는 다른 머신이다편4
15Job 사이로 값과 파일을 어떻게 넘기나머신이 달라 자동 공유가 없고, 값은 outputsneeds로 파일은 아티팩트를 경유한다편4
16self-hosted runner의 이유와 리스크시간 제한과 설치 지연을 피하고 사내망에 닿는 대신, 저장소 쓰기 권한자가 그 머신을 쓰게 된다편4
17Jenkins Controller와 Agent의 역할Controller가 정의·스케줄·자격증명을, Agent가 빌드를 맡으며 Controller 빌드는 단일 장애점이다편5
18Freestyle과 Pipeline 중 무엇을 쓰나설정이 코드로 남아 리뷰와 되돌리기가 되는 Pipeline이 기본이고, Freestyle은 일회성뿐이다편5
19Declarative와 Scripted의 차이Declarative는 DSL이라 읽기 쉽고, 표현력이 모자란 자리에서만 script로 Groovy를 섞는다편5
20Webhook과 Poll SCM 중 무엇을 쓰나즉시성과 부하는 Webhook이 앞서지만 닿을 주소가 있어야 하고, 격리망이면 Poll SCM이다편5
21Actions와 Jenkins의 선택 기준기본값은 Actions이고 세 조건 중 하나라도 참일 때 Jenkins다「고를 때」
22왜 브랜치가 아니라 태그로 배포하나다섯 편에 흩어져 있어 바로 아래 절에서 모은다아래 절
23무중단 배포 전략을 비교하라Rolling은 여유 용량을, Blue-Green은 인프라 비용을, Canary는 시간을 내주고 롤백 속도를 산다편6
24Blue-Green의 실제 절차는한쪽을 트래픽에서 뺀 뒤 그쪽만 교체·검사하고, 통과하면 옮기고 반대쪽도 같게 바꾼다편6
25Rolling에서 DB 스키마는 어떻게 다루나신·구 공존을 전제로 확장과 정리를 서로 다른 배포에 나눠 싣는다편6 · 「터졌을 때」
26파이프라인에서 시크릿을 어떻게 다루나자격증명 저장소에만 두고, 파일로 떨궜으면 즉시 지우고 로그에 안 찍는다편6
27배포 자동화에서 가장 조심할 지점은실패를 실패로 만들지 못하는 게이트이고, 읽어서가 아니라 실패를 넣어 봐야 드러난다편6 · 「터졌을 때」
28결제 서비스 CI/CD의 차별점은태그 배포·승인 게이트·스크립트 형상관리·품질 게이트·무중단이 권장이 아니라 조건이 된다편6 · 심화 ④
29DevOps 조직을 어떻게 둘 것인가인프라팀 유무로 역할이 갈리고, 작으면 별도 조직 대신 백엔드의 부전공으로 두고 표준화한다편2

22 — 왜 브랜치가 아니라 태그로 배포하나

이 질문만 다섯 편에 흩어져 있다. 편2가 논증을, 편3이 이미지 이름을, 편4가 트리거를, 편5가 태그 고르는 화면을, 편6이 결제 도메인의 조건으로 한 조각씩 다뤘다. 편2가 예고한 자리이고, 편4가 싣지 않은 마지막 한 줄이 결론이다.

이 설계 하나가 「지금 운영에 뭐가 올라가 있나」에 즉답할 수 있느냐를 가른다.

즉답이 설계에 걸리는 이유는 그 질문이 사고 중에 온다는 데 있다. 커밋 해시를 읽어 주면 다음 물음 — 무엇이 들어 있나, 어디로 되돌리나 — 이 조회가 되지만 태그는 셋을 한 번에 끝낸다. 낱말도 못 박는다 — 앞 편들이 「배포 단위」와 「배포 대상」을 다른 뜻으로 썼는데 편1의 다의어표에 없다.

이 편이 쓰는 말가리키는 것그렇게 쓴 편
배포 대상무엇을 올릴지 지목하는 이름 — 태그편2·편6
배포 산출물그 이름으로 만들어져 실려 가는 물건 — 컨테이너 이미지편3
배포 지목 방식트리거가 정하는, 올릴 것이 정해지는 시점편4

이름 → 물건 → 시점으로 층이 달라 「배포 단위」도 편4가 쓴 「배포 대상」도 홀로 쓰면 셋 중 무엇인지 알 수 없어, 이 편은 둘 다 홀로 쓰지 않는다.

심화 ① git pullgit fetch + git merge와 정말 같은가

편2가 사실을 줬다. 이 질문이 되돌아오는 것은 알고 나서도 팀에 무엇을 규칙으로 걸지가 남기 때문이다.

기능적으로 pullfetchmerge를 실행하는 축약인 것은 맞다. 다만 결과가 같다는 것과 안전하다는 것은 다르다. pull은 원격 변경을 확인할 기회 없이 작업 디렉터리를 바로 병합하기 때문에, 충돌 해결을 준비 안 된 상태에서 시작하게 된다.

그래서 규칙을 두 갈래로 둔다. 개인 feature 작업 중 최신화는 fetch로 먼저 확인하고 필요한 시점에 병합한다. 공유 브랜치를 따라갈 때는 pull --rebase를 기본으로 두되, 이미 push한 커밋이 있으면 금지한다.

핵심은 명령을 외우게 하는 게 아니라 「지금 내가 세 트리 중 무엇을 바꾸고 있는가」를 팀이 인지하게 만드는 것이다.

규칙의 단위는 명령이 아니라 브랜치의 종류이고 같은 기준이 파이프라인으로 넘어간다 — reset --hard가 CI 워크스페이스에서는 재현성 장치이고 사람의 디렉터리에서는 사고다.

심화 ② GitHub Actions가 있는데 왜 아직도 Jenkins인가

앞 절의 세 조건이 「무엇을 새로 세우나」였다면 이 질문은 이미 있는 것을 어떻게 하나다. 근거는 편1에 있으니 무엇부터 결재하는가만 본다.

첫째, 자유도다. 배포 시점에 운영자가 태그를 골라야 하는 워크플로가 Jenkins에서는 플러그인 하나로 되지만 Actions에서는 우회가 필요하다.

둘째, 네트워크 경계다. 사내망·VPC 안의 DB, 사설 레지스트리, 온프레미스 서버에 접근해야 하는 파이프라인은 자체 서버로 도는 Jenkins가 자연스럽다.

셋째, 이미 축적된 자산이다. 수백 개 Job과 플러그인 조합, 권한 체계가 이미 감사 대상으로 등록돼 있으면 전환 자체가 프로젝트가 된다.

둘째는 앞 절이 이미 뺐고, 셋째가 리더에게 가장 무겁다. 전환이 프로젝트라는 말은 일정과 인원과 실패 가능성을 가진 항목이 된다는 뜻인데, 옮기기 전에는 무엇을 옮기는지가 목록으로 없다 — UI 폼에 갇힌 설정은 세어 볼 수가 없다. 그래서 먼저 하는 것은 교체가 아니라 코드화다. 정의를 파일로 옮겨야 목록이 생기고 그제야 전환의 값이 계산되는데, 값어치가 없다는 결과도 자주 나온다.

심화 ③ 자동화를 도입했는데 오히려 장애가 늘었다

편1이 자동화의 값을 「멈출 자리 셋을 남긴 채 빨라진 것」으로 정리했고 편6이 그중 하나가 안 닫히는 실물을 보였다. 남은 것은 보는 순서다.

자동화 자체가 아니라 게이트가 제대로 작동하는지를 먼저 본다. 수동 배포에서는 사람이 눈으로 확인하던 단계가 자동화에서는 조건문 한 줄로 압축되는데, 그 한 줄이 틀리면 검증이 통째로 사라진다.

그래서 순서를 이렇게 잡는다. 첫째, 각 게이트가 실패 시 실제로 파이프라인을 중단시키는지 의도적으로 실패를 주입해 확인한다. 둘째, 롤백 경로를 배포 경로만큼 자주 실행해 본다. 셋째, 배포 빈도·변경 실패율·복구 시간을 측정해 개선 방향을 데이터로 잡는다.

인과가 뒤집혀 있다. 장애가 는 원인은 자동화가 검증을 없앤 것이 아니라 검증을 한 줄로 압축한 것이다. 사람의 확인은 부분적으로 틀리지만 조건문은 틀리면 전부 틀리므로, 줄일 것은 검증되지 않은 조건문이다. 셋 중 첫째는 「터졌을 때」의 ②, 둘째는 되돌아갈 것이 남았는지 확인하는 유일한 방법, 셋째는 마지막 절이 받는다.

심화 ④ 결제 서비스의 CI/CD는 무엇이 다른가

편6이 결제 도메인의 요구를 정리하며 새 기법은 없다고 적었다. 각 요구가 어느 편의 장치를 부르는지를 잇는다.

자동화의 목표를 속도가 아니라 재현성과 통제 가능성으로 바꾼다.

배포 대상은 브랜치가 아니라 태그로 고정한다. 지금 운영에 무엇이 올라가 있고 무엇이 포함됐는지를 한 단어로 지목할 수 있어야 감사와 롤백이 성립한다.

운영 전환 직전에는 승인 게이트를 둔다. Jenkins라면 input 스텝에서 승인자를 검증하고 기록까지 남기되, 승인 대기가 실행 슬롯을 잡아먹지 않도록 timeout을 함께 건다.

파이프라인 스크립트는 애플리케이션 저장소와 분리해 형상관리한다. 소유자가 다르고, 파이프라인 변경 자체가 감사 대상이기 때문이다.

품질 게이트는 실패로 연결한다. 정적분석과 API 회귀 테스트가 리포트만 남기고 통과하면 없는 것과 같다. 결제 트랜잭션이 끊기는 순간이 곧 금전 손실이라 무중단 전환과 즉시 롤백은 선택이 아니라 전제다.

다섯 문단이 다른 편에서 온다. 태그 고정은 편2와 편3, 승인자 검증과 timeout은 편5, 스크립트 분리는 같은 편의 소유권 결정, 품질 게이트와 무중단은 편6이다. 하나가 더해진다 — 스크립트 분리와 권한 관리는 한 짝이라 감사 대상은 저장소만이 아니라 거기 쓸 수 있는 사람까지다.

심화 ⑤ 리더로서 CI/CD 문화를 무엇부터 정착시키는가

재료가 앞 세 편에 있다. 편1이 배포 절차가 머릿속에 있던 시절을, 편2가 그 절차를 누가 맡을지를, 편3이 브랜치 전략의 다섯 축이 조직 조건이라는 것을 다뤘다. 순서로 세우는 것이 답이다.

도구 도입을 먼저 하지 않는다. 먼저 하는 건 현재 배포 절차를 글로 적게 하는 것이다. 배포 담당자마다 순서와 명령어가 달랐고 그래서 배포가 손 떨리는 작업이 됐는데, 절차가 문서로 수렴되기 전에는 무엇을 자동화할지도 정할 수 없다.

그다음은 가장 아픈 지점 하나만 자동화한다. 대개 빌드·테스트가 아니라 배포 직전의 수작업이다. 여기서 성공 경험이 나오면 확장은 팀이 스스로 한다.

그리고 파이프라인을 코드로 만들어 리뷰 대상에 올린다. 배포 절차가 리뷰되기 시작하면 그때부터 문화가 된다.

마지막으로 지표를 본다. 배포 빈도와 변경 실패율, 복구 시간이 개선되지 않으면 자동화가 아니라 자동화된 혼란일 뿐이다.

순서가 뒤집히지 않는다는 것이 판정이다. 흔한 실패는 첫 걸음을 건너뛰는 것인데, 그러면 담당자마다 다르던 절차 중 하나가 우연히 표준이 된다. 자동화가 합의를 만들지 않는다 — 합의를 기록한 것이 자동화될 뿐이다.

셋째 걸음이 임계점이다. 파이프라인이 리뷰에 오르면 개선이 개인의 습관이 아니라 팀의 변경 이력이 된다 — 심화 ②의 코드화가 도구 전환의 전제였듯 여기서는 문화의 전제다.

30 — 게이트가 정말 막는지를 무엇으로 아는가

실패 주입은 게이트 하나에 대한 답이다. 스무 개면 스무 번 넣어야 하고, 매번 하는지는 다시 아무도 모른다. 그래서 판정을 파이프라인 밖으로 옮긴다 — 게이트가 일을 하고 있으면 결과가 지표로 나타난다. 도구 도입이 아니라 이 변화로 말하라는 것이 원본의 결론이고, 네 지표를 묶어 부르는 이름이 DORA다.

지표무엇을 재나무엇이 움직이면 바뀌나
배포 빈도운영에 반영이 일어나는 횟수트리거와 파이프라인 소요 시간
변경 리드 타임커밋이 운영에 닿기까지 걸리는 시간승인 게이트와 남아 있는 수작업
변경 실패율배포가 롤백이나 긴급 수정을 부른 비율품질 게이트와 회귀 테스트
평균 복구 시간(MTTR)장애를 알아챈 때부터 복구까지롤백 경로가 실제로 도는가

앞의 둘은 빨라지는 쪽, 뒤의 둘은 멈추고 되돌리는 쪽이라 넷을 함께 봐야 자동화가 무엇을 사고 무엇을 팔았는지 보인다.

이것이 편6의 물음에 대한 답이다. 게이트가 막아야 할 것을 막으면 변경 실패율이 내려가고 복구 시간이 짧아진다. 잔뜩 달았는데 이 둘이 그대로면 통과 도장을 찍고 있을 뿐이다 — 파이프라인 안에서는 안 보이던 것이 지표 위에서는 아무것도 하지 않은 자리로 나타난다. 다만 채울 값은 이 글에 없다 — 지표는 정의이지 성적표가 아니다.

정리

  • 되돌아오는 질문은 세 자리에서 온다. 아직 고르는 중이거나, 이미 터졌거나, 근거를 대야 하거나다.
  • 선택 기준은 장단점 목록에서 나오지 않는다. 도구는 기본값과 뒤집는 조건 셋으로, 트리거는 되돌릴 대상에 이름이 붙느냐로 갈린다.
  • 롤백은 실패한 뒤에 준비할 수 없다. 되돌아갈 이름도 이력도 스키마의 세 걸음도 배포가 성공했을 때 해 두는 일이다.
  • 게이트가 닫히는지는 게이트를 봐서 알 수 없다. 하나는 실패를 주입해 알고, 전체는 변경 실패율과 복구 시간으로 안다.

일곱 편의 문제는 두 도막이었다. 손으로 하던 통합·배포를 기계에 어떻게 옮기고, 그 기계를 어떻게 멈출 수 있게 만드는가. 여섯 편이 앞을 맡았고 이 편이 남긴 것은 그 장치가 실제로 멈추는지 확인하는 방법이다. 확인 없이 놓인 게이트는 자동화된 통과 도장이고, 가려내는 데 도구 선택은 아무 도움도 주지 않는다.