테마 선택

📚 지식 노트

AI·하드웨어·주변기기·게임·컴퓨터 시스템·이론 컴퓨터 과학·수학·개발과 운영·보안·응용 분야에 대해 알아 두면 좋은 내용을 정리한 노트다. 위에서 분야를 고르고 아래에서 노트를 고른다.

CI/CD와 인프라 코드

커밋이 테스트를 거쳐 운영에 닿기까지의 길을 정리한다. 파이프라인을 빠르게 만드는 법, 롤링·블루-그린·카나리 배포, 기능 플래그, Terraform과 GitOps로 인프라를 코드로 다루는 법, 비밀값과 공급망을 지키는 법, 그리고 이 모든 것이 잘 돌아가는지 재는 DORA 지표까지를 숫자로 계산해 가며 본다.

목차 (11)
  1. CI 파이프라인의 단계
  2. 캐시와 산출물
  3. 배포 전략: 롤링, 블루-그린, 카나리
  4. 기능 플래그: 배포와 출시를 떼어 놓기
  5. Terraform: plan, apply, state
  6. 선언형과 명령형
  7. GitOps: 저장소가 곧 운영 상태
  8. 파이프라인의 비밀값
  9. 공급망: 무엇을 배포하는지 증명하기
  10. DORA 지표: 잘 돌아가는지 재기
  11. 핵심 자료

지속적 통합(CI, continuous integration)은 모두의 변경을 자주(하루에 적어도 한 번) main에 합치고, 합칠 때마다 자동으로 빌드·시험하는 습관이다. 지속적 전달(continuous delivery)은 main이 언제든 운영에 내보낼 수 있는 상태로 유지되는 것이고, 지속적 배포(continuous deployment)는 사람의 버튼 없이 실제로 내보내기까지 하는 것이다. 브랜치를 어떻게 합치는지는 버전 관리 노트, 파이프라인 안에서 도는 테스트는 소프트웨어 테스트 노트에 있다.

CI 파이프라인의 단계

파이프라인은 대개 준비(코드 받기, 의존성 설치) → 검사(린트, 타입 검사, 보안 스캔) → 빌드 → 테스트(단위, 통합, E2E) → 패키징(컨테이너 이미지, 서명) 순서로 돈다. 단계는 앞 단계가 통과해야 넘어가고, 한 단계 안의 서로 독립인 작업은 동시에 돌린다. 그러면 전체 시간은 작업 시간의 합이 아니라 단계마다 가장 긴 작업을 이은 임계 경로가 정한다.

CI 파이프라인 시간표: 준비·검사·빌드·테스트·패키징 다섯 단계가 차례로 돌고, 검사와 테스트 단계 안의 작업은 동시에 돈다. 가장 긴 작업을 이은 임계 경로가 전체 시간을 정한다준비의존성 설치3분검사린트1분타입 검사2분빌드빌드4분테스트단위3분통합6분E2E8분패키징이미지·서명2분0분5분10분15분모두 차례로 돌리면 29분, 단계 안을 병렬로 돌리면 19분. 색칠한 막대가 임계 경로다.
예제 파이프라인의 시간표. 테스트 단계에서 단위·통합 테스트가 일찍 끝나도 E2E를 기다린다. 이 파이프라인을 줄이려면 E2E를 쪼개 여러 대에서 나눠 돌리는 것(샤딩)이 가장 효과가 크다.
  • 빨리 실패하기: 싸고 자주 깨지는 검사를 앞에 둔다. 린트가 1분 만에 실패하면 8분짜리 E2E를 돌릴 필요가 없다.
  • 10분 안팎: 피드백이 늦으면 개발자는 결과를 기다리지 않고 다음 일로 넘어가고, 깨진 main 위에 변경이 쌓인다. 예제는 차례로 돌리면 29분, 병렬이면 19분이다.
  • main이 깨지면 그것부터: 깨진 main 위에서는 아무도 자기 변경이 안전한지 알 수 없다. 고치기 어렵다면 문제 커밋을 되돌리는 것이 기본이다. 병합 전에 main 최신과 합친 결과로 다시 시험하는 머지 큐(merge queue)도 같은 목적이다.
  • 같은 환경에서: 파이프라인 정의를 저장소 안 파일(YAML 등)로 두고, 빌드는 컨테이너처럼 고정된 환경에서 돌린다. ‘내 컴퓨터에서는 되는데’를 없애는 첫걸음이다.

캐시와 산출물

둘 다 파이프라인 사이에 파일을 넘기지만 목적이 다르다. 캐시는 다시 만들 수 있지만 오래 걸리는 것(내려받은 의존성, 컴파일 중간 결과)을 재사용해 시간을 아낀다. 없거나 낡아도 결과는 같아야 한다. 산출물(artifact)은 파이프라인이 만든 결과 그 자체(바이너리, 컨테이너 이미지)이고, 뒤 단계와 배포가 이것을 그대로 쓴다.

캐시와 산출물: 위는 lockfile 내용의 해시로 캐시 키를 만들어 적중하면 복원하고 빗나가면 설치 후 저장하는 흐름, 아래는 한 번 빌드한 산출물을 스테이징과 운영에 그대로 올리는 흐름캐시: 다시 만들 수 있는 것을 재사용해 시간을 아낀다lockfile의존성 판 목록키 = OS + 내용 해시linux-npm-2086223f909e적중 → 복원하고 건너뜀빗나감 → 설치 후 저장산출물: 한 번 만든 것을 그대로 옮긴다(다시 빌드하지 않음)빌드 1회커밋 3f2a9c1산출물app:1.4.2스테이징같은 digest운영같은 digest환경마다 다른 것은 설정과 비밀값뿐이다. 시험한 바이트와 배포한 바이트가 같다.
위: lockfile 내용을 해시해 캐시 키로 쓰면 의존성이 바뀔 때만 캐시를 새로 만든다. 아래: 한 번 빌드한 산출물을 환경마다 다시 빌드하지 않고 그대로 올린다.
  • 캐시 키: lockfile이 같으면 같은 키, 한 글자라도 바뀌면 다른 키다. 설치가 캐시 없이 3분, 캐시로 0.5분이고 적중률이 90%면 기대 시간은 0.75분이다. 키가 너무 넓으면(lockfile을 안 넣으면) 낡은 의존성으로 시험하는 사고가 난다.
  • 한 번 빌드해 승격: 스테이징에서 시험한 이미지와 운영에 올린 이미지가 같은 바이트여야 시험의 의미가 있다. 이미지를 태그(:latest)가 아니라 내용 해시(digest)로 가리키면 중간에 바뀌지 않는다. 환경마다 다른 것은 설정과 비밀값으로만 넣는다.

배포 전략: 롤링, 블루-그린, 카나리

새 판을 운영에 올리는 방식은 ‘얼마나 많은 사용자가 새 판을 얼마나 빨리 만나는가’와 ‘문제가 생기면 얼마나 빨리 되돌리는가’ 사이의 선택이다. 세 전략을 같은 시간 축에 놓아 본다.

배포 전략 단계 그림: 롤링은 한 대씩 바꾸고, 블루-그린은 새 판 네 대를 띄운 뒤 트래픽을 한 번에 돌리며, 카나리는 트래픽을 5%, 25%, 50%, 100%로 올린다떠 있는 인스턴스v2로 가는 트래픽롤링블루-그린카나리v1v1v1v10%v1v1v1v10%v1v1v1v10%v1v1v1v225%v1v1v1v1v2v2v2v20%v1v1v1v1v25%v1v1v2v250%v1v1v1v1v2v2v2v20%v1v1v1v1v225%v1v2v2v275%v1v1v1v1v2v2v2v2100%v1v1v2v250%v2v2v2v2100%v1v1v1v1v2v2v2v2100%v2v2v2v2100%v2v2v2v2100%v2v2v2v2100%v2v2v2v2100%v1 = 옛 판, v2 = 새 판(색칠). 블루-그린의 앞 네 칸이 블루, 뒤 네 칸이 그린이다.
1 / 6

세 전략 모두 옛 판(v1) 4대가 모든 트래픽을 받는 상태에서 시작한다.

인스턴스 4대를 v1에서 v2로 바꾸는 세 방법. 칸은 떠 있는 인스턴스, 오른쪽 막대는 v2로 가는 트래픽 비율이다. 블루-그린은 잠깐 두 배의 자원을 쓰는 대신 한 번에 전환하고 한 번에 되돌린다. 카나리는 적은 트래픽으로 먼저 확인한다.
  • 롤링: 인스턴스를 몇 대씩 차례로 바꾼다. 쿠버네티스 Deployment의 기본이고, maxSurge(더 띄울 수)와 maxUnavailable(내릴 수)로 속도와 여유 자원을 조절한다. 그림처럼 한 대씩 내리고 올리면 최대 4대로 추가 자원이 없지만, 배포 중에는 두 판이 섞여 돈다.
  • 블루-그린: 똑같은 환경을 하나 더 띄워(최대 8대) 시험한 뒤 라우터를 한 번에 돌린다. 되돌리기도 라우터만 돌리면 되니 순간이다. 두 배의 자원이 잠깐 들고, DB처럼 둘이 함께 쓰는 것은 두 판 모두와 맞아야 한다.
  • 카나리: 새 판에 트래픽을 조금(그림은 5%)만 보내 오류율·지연을 옛 판과 비교하고, 괜찮으면 단계적으로 올린다. 분당 요청 2,000건인 서비스에 나쁜 판이 나가 감지까지 10분 걸린다면, 한 번에 바꿀 때는 20,000건, 5% 카나리면 1,000건이 나쁜 판을 만난다. 판정은 사람 눈보다 미리 정한 지표와 자동 비교에 맡기는 것이 좋다(SRE Workbook).
  • DB 스키마는 따로: 어느 전략이든 옛 판과 새 판이 잠시 같은 DB를 쓴다. 열 이름 바꾸기 같은 변경은 ‘새 열 추가 → 양쪽에 쓰기 → 옮기기 → 옛 열 제거’처럼 여러 번의 배포로 나눈다(expand-contract).

기능 플래그: 배포와 출시를 떼어 놓기

배포는 코드를 운영에 올리는 일이고, 출시는 사용자가 기능을 보게 하는 일이다. 기능 플래그는 이 둘을 떼어 놓는다. 덜 만든 기능도 꺼진 채 main에 합쳐 배포하고, 나중에 설정만 바꿔 직원 → 일부 사용자 → 모두 순으로 켠다. 문제가 생기면 다시 배포할 필요 없이 끈다. 진화적 아키텍처 관점의 이야기는 시스템 설계 › 진화적 아키텍처에 있다.

기능 플래그 점진 공개: 사용자 열 명의 버킷 값과, 공개 비율 30%와 50%에서 각각 기능이 켜지는 사용자. 비율을 올려도 이미 켜진 사용자는 그대로다플래그 new-checkout: 버킷 = hash(플래그, 사용자) mod 100u1u2u3u4u5u6u7u8u9u10버킷031205672988988368230% 공개켬끔켬끔끔끔끔끔끔끔50% 공개켬켬켬끔끔끔끔끔켬끔배포: 꺼진 채 운영에 올림직원·일부에게 켬출시: 모두에게 켬
점진 공개의 원리. 사용자 ID를 해시해 0~99 버킷에 고정해 두고 공개 비율보다 작은 버킷만 켠다. 그래서 같은 사용자는 새로 고침해도 같은 화면을 보고, 비율을 올려도 이미 켜진 사람은 그대로다. 열 명이라 30%에서 정확히 셋이 켜지지는 않는다.
  • 종류마다 수명이 다르다: 출시용 플래그는 몇 주 안에 지워야 하고, 운영용 차단 스위치(kill switch)나 권한 플래그는 오래 산다(Feature Toggles).
  • 플래그 빚: 다 켠 플래그를 지우지 않으면 코드에 아무도 안 타는 갈래가 쌓이고, 켜짐·꺼짐 조합만큼 시험할 경우가 늘어난다. 만들 때 지울 날짜와 담당자를 함께 적는다.

Terraform: plan, apply, state

인프라 코드(IaC, infrastructure as code)는 서버·네트워크·DB 같은 자원을 콘솔 클릭 대신 코드로 정의해 저장소에 두고 리뷰·이력·재현성을 얻는 방법이다. 대표 도구 Terraform은 HCL로 원하는 자원을 적고 세 가지를 비교한다. 코드(원하는 상태), state 파일(지난번 apply 때 만든 자원과 그 ID를 기억한 장부), 실제 클라우드다. terraform plan은 실제 상태를 다시 읽고(refresh) 코드와의 차이를 계획으로 보여 주고, terraform apply가 그 계획을 실행한다.

Terraform 계획 표: 자원 네 개마다 코드의 값과 실제 값을 비교해, 웹 서버는 AMI가 바뀌어 교체, DB는 저장 용량 변경, 로그 버킷은 생성, 옛 큐는 삭제로 정한다. 웹 서버의 인스턴스 타입은 콘솔에서 바뀐 드리프트다자원코드(원하는 상태)실제(refresh)계획instance.webami-v2 t3.smallami-v1 t3.medium-/+ 교체db_instance.main10050~ 변경sqs_queue.old(없음)4d- 삭제s3_bucket.logstrue(없음)+ 생성Plan: 2 to add, 1 to change, 2 to destroy.빨간 값: state 파일은 t3.small로 기억하는데 실제는 t3.medium — 누군가 콘솔에서 바꿨다
자원 네 개의 계획. 웹 서버는 이미지(AMI)를 바꾸면 그 자리에서 고칠 수 없는 속성이라 지우고 새로 만든다(교체). 교체는 추가와 삭제 양쪽에 세어지므로 요약 줄의 숫자가 자원 수보다 크다.
  • plan을 리뷰하기: 그림의 요약 줄은 Plan: 2 to add, 1 to change, 2 to destroy.다. 코드 변경보다 이 plan 출력이 더 중요하다. 한 줄 고쳤는데 DB가 ‘교체’로 나오면 데이터가 사라진다는 뜻이다. PR에 plan 결과를 붙여 함께 리뷰하고, apply는 리뷰한 그 plan 파일로 한다.
  • 드리프트: 누군가 콘솔에서 직접 바꾸면 코드·state·실제가 어긋난다. 그림의 웹 서버는 state에 t3.small로 적혀 있지만 실제는 t3.medium이다. 다음 plan이 이것을 되돌리려 하므로, 정기적으로 plan을 돌려 드리프트를 감지하고 콘솔 쓰기 권한을 줄인다.
  • state는 공유 자원: state에는 자원 ID와 때로 비밀번호까지 담기므로 암호화한 원격 저장소(S3, GCS 등)에 두고, 두 사람이 동시에 apply하지 못하게 잠근다. 잠금을 지원하는 백엔드라면 Terraform이 state를 쓸 수 있는 모든 작업에서 잠금을 저절로 걸고, 잠금을 못 얻으면 멈춘다. CI가 중간에 죽어 잠금이 남았을 때 쓰는 terraform force-unlock은 정말 아무도 apply하지 않는지 확인한 뒤에만 쓴다. 남이 잡고 있던 잠금을 풀면 두 작업이 같은 state를 동시에 쓴다.
  • 모듈: 자주 쓰는 묶음(VPC + 서브넷 + 라우팅)을 모듈로 만들어 입력 변수만 바꿔 재사용한다. 환경(dev·staging·prod)마다 같은 모듈을 다른 값으로 부르면 환경 사이 차이가 코드로 드러난다.
  • OpenTofu: HashiCorp가 2023년 Terraform의 라이선스를 BSL로 바꾸자, 그 직전 판에서 갈라져 나온 오픈소스 판이 OpenTofu다. 문법과 동작은 대부분 같다.

선언형과 명령형

명령형은 ‘무엇을 할지’(서버 3대를 더 만들어라)를, 선언형은 ‘무엇이어야 할지’(서버는 6대다)를 적는다. 선언형 도구는 지금 상태를 읽어 차이만큼만 고치므로, 같은 정의를 몇 번 적용해도 결과가 같다. 이 성질을 멱등성(idempotence)이라 한다.

명령형과 선언형 비교: 서버 3대에서 시작해 명령형 스크립트를 세 번 실행하면 6, 9, 12대로 늘지만 선언형 정의는 매번 6대로 맞춘다명령형: 무엇을 할지repeat 3:create_server()선언형: 무엇이어야 할지servers:count: 6목표 6661회 실행962회 실행1263회 실행시작 3대. 선언형 도구는 지금 상태를 읽어 차이만 고치므로 다시 실행해도 안전하다.
3대에서 시작해 6대를 만들려는 두 방법을 세 번 실행한 결과. 실패 뒤 재시도, 실수로 두 번 돌린 파이프라인처럼 같은 작업이 반복되는 일은 흔하다.

명령형 스크립트는 세 번 돌리면 6 → 9 → 12대가 되고, 선언형은 6 → 6 → 6대로 머문다. 선언형이 늘 낫지는 않다. ‘DB를 백업하고 → 점검 모드로 바꾸고 → 마이그레이션하라’처럼 순서 자체가 중요한 작업은 명령형이 자연스럽다. Terraform·쿠버네티스 매니페스트·CloudFormation은 선언형, 셸 스크립트는 명령형이고, Pulumi·CDK는 일반 프로그래밍 언어(명령형)로 선언형 자원 그래프를 만들어 낸다.

GitOps: 저장소가 곧 운영 상태

GitOps는 선언형을 배포까지 밀고 간 방식이다. 운영 환경이 어때야 하는지를 Git 저장소에 선언해 두고, 클러스터 안의 에이전트가 그 저장소를 계속 읽어 실제 상태를 맞춘다. OpenGitOps는 이를 네 원칙(선언형, 버전 관리되고 불변, 자동으로 끌어옴, 계속 맞춤)으로 정리했다. 쿠버네티스에서는 Argo CD와 Flux가 대표적인 에이전트다.

푸시 방식은 CI가 클러스터 자격 증명을 들고 직접 적용하고, GitOps는 CI가 설정 저장소만 고치며 클러스터 안의 에이전트가 그 저장소를 계속 읽어 실제 상태를 맞춘다푸시 방식CIkubectl applyCI가 클러스터 자격 증명을 가짐클러스터GitOps(풀 방식)CI커밋설정 저장소원하는 상태(Git)클러스터에이전트워크로드맞춤비교에이전트가 저장소를계속 읽고 차이를 고친다.되돌리기 = git revert
푸시 방식과 GitOps. GitOps에서 CI는 이미지를 만들고 설정 저장소의 이미지 digest만 고친다. 클러스터에 손대는 것은 클러스터 안의 에이전트뿐이다.
  • 자격 증명이 안쪽에: CI가 클러스터 관리자 권한을 들고 있지 않아도 된다. CI가 털려도 할 수 있는 일은 저장소에 커밋을 남기는 것이고, 그것은 리뷰와 이력에 드러난다.
  • 되돌리기 = 커밋 되돌리기: 운영 상태의 이력이 곧 Git 이력이라, 언제 누가 무엇을 바꿨는지 보이고 git revert로 되돌린다.
  • 드리프트를 스스로 고침: 누가 kubectl edit로 직접 고쳐도 에이전트가 저장소 상태로 되돌린다(설정에 따라 알리기만 할 수도 있다).

파이프라인의 비밀값

파이프라인은 클라우드, 레지스트리, 결제 같은 곳의 자격 증명이 모이는 곳이라 공격자가 노리기 좋다. 가장 흔한 실수는 오래 사는 접근 키를 CI 설정에 넣어 두는 것이다. 한 번 새면 누군가 알아채고 바꿀 때까지 유효하다.

비밀값 두 방식: 위는 CI 설정에 저장한 장기 키를 그대로 클라우드에 쓰는 방식, 아래는 CI가 저장소·브랜치 정보가 담긴 서명된 ID 토큰을 내밀어 클라우드에서 한 시간짜리 자격 증명을 받는 OIDC 방식장기 키 저장CI 비밀값 설정ACCESS_KEY=AKIA…키를 그대로 사용클라우드 API새어 나가면 누군가 키를 바꿀 때까지 몇 달이고 유효하다OIDC 연동CI 실행저장소·브랜치가 적힌 토큰① 서명된 ID 토큰③ 1시간짜리 자격 증명클라우드 STS② 신뢰 정책과 대조저장할 키가 없다. main 브랜치의 배포 작업에만 권한을 주는 식으로 좁힐 수 있다
장기 키 대신 OIDC. CI 플랫폼이 실행마다 ‘이 저장소의 이 브랜치에서 도는 이 작업’이라고 서명한 토큰을 주고, 클라우드는 신뢰 정책과 맞는지 확인한 뒤 짧게 사는 자격 증명을 준다.
  • OIDC 연동: GitHub Actions 등은 실행마다 OpenID Connect 토큰을 발급한다. 클라우드 쪽 신뢰 정책에 ‘이 저장소의 main 브랜치’처럼 조건을 걸면, 포크나 다른 브랜치의 작업은 같은 권한을 얻지 못한다.
  • 최소 권한과 나누기: 빌드 작업과 배포 작업의 권한을 나누고, 운영 배포 권한은 보호된 브랜치·환경에서만 쓰게 한다. 외부 기여자의 PR이 비밀값에 닿는 경로가 없는지 확인한다. GitHub Actions의 pull_request_target·workflow_run은 본 저장소의 권한과 비밀값을 갖고 도는 트리거라, 여기서 포크 PR의 코드를 체크아웃해 빌드하면 그 코드가 비밀값과 쓰기 권한을 얻는다(GitHub 보안 사용 안내).
  • 로그에 찍지 않기: CI는 등록된 비밀값을 로그에서 가리지만, 인코딩을 바꾸거나 잘라 찍으면 그대로 나온다. 비밀값은 환경 변수나 비밀 관리 서비스(Vault, 클라우드 Secret Manager)에서 실행 시점에 받는다.

공급망: 무엇을 배포하는지 증명하기

내가 쓴 코드가 안전해도, 빌드 서버가 오염되거나 레지스트리의 이미지가 바꿔치기되면 사용자에게는 다른 것이 간다. 소스에서 배포까지의 고리 전체가 소프트웨어 공급망이다. 의존성 나무와 lockfile, 코드 서명의 원리는 보안 › 시스템·소프트웨어 보안에서 다뤘고, 여기서는 파이프라인이 할 일을 본다.

공급망 고리: 소스, 빌드, 산출물, 레지스트리, 배포 전 검증이 이어지고 고리 사이마다 소스 변조, 빌더 오염, 바꿔치기, 검증 생략 같은 공격이 있다. 산출물에는 출처 증명, 서명, SBOM이 붙어 배포 전에 검증된다소스 변조빌더 오염바꿔치기검증 생략소스빌드산출물레지스트리배포 전 검증출처 증명(SLSA)어디서 무엇으로 빌드했나서명(Sigstore)누가 만들었고 안 바뀌었나SBOM안에 무엇이 들어 있나산출물에함께 붙이는 것검증 단계는 서명자·빌드 출처가 다르거나 알려진 취약점이 있으면 배포를 막는다.
공급망의 고리와 산출물에 붙이는 증거. 배포 전 검증 단계가 증거를 확인하지 않으면 앞의 모든 노력이 소용없다.
  • SLSA: 빌드 트랙의 수준이 올라갈수록 요구가 커진다. L1은 출처 증명(provenance: 어느 소스 커밋을 어느 빌더가 어떤 명령으로 빌드했나)이 있을 것, L2는 호스팅된 빌드 플랫폼이 그 증명에 서명할 것, L3은 빌드끼리 격리돼 한 빌드가 다른 빌드나 서명 키를 건드릴 수 없을 것이다.
  • 서명: Sigstore(cosign)는 CI의 OIDC 신원으로 짧게 사는 인증서를 받아 서명하고, 서명 기록을 공개 투명성 로그에 남긴다. 오래 보관할 서명 키가 없어진다.
  • SBOM: 산출물에 든 구성 요소와 판의 목록이다. SPDX와 CycloneDX가 표준 형식이다. 새 취약점이 공개되면 ‘우리 어느 서비스에 이 판이 들어 있나’를 바로 답할 수 있다.
  • 파이프라인 자체의 의존성: CI에서 가져다 쓰는 액션·플러그인도 공급망이다. 태그(@v4)는 나중에 다른 코드를 가리키게 바뀔 수 있으니 커밋 해시로 고정하고, 갱신은 봇이 PR로 올리게 한다.

DORA 지표: 잘 돌아가는지 재기

DORA(DevOps Research and Assessment) 연구는 소프트웨어 전달 성과를 몇 개의 지표로 잰다. 처음에는 네 지표였고, 지금은 다섯 지표를 처리량과 불안정성 두 묶음으로 나눈다. 처리량은 변경 리드 타임(커밋에서 운영까지), 배포 빈도, 실패 배포 복구 시간이고, 불안정성은 변경 실패율(곧바로 되돌리거나 핫픽스가 필요했던 배포 비율)과 재작업 배포 비율(사고 때문에 계획에 없이 한 배포 비율)이다.

DORA 지표 계산 예: 4주 동안 배포 12번 중 2번이 실패했고 그 뒤 재작업 배포가 2번 있었다. 여기서 배포 빈도, 리드 타임, 복구 시간, 변경 실패율, 재작업 비율을 낸다4주 동안의 배포 12번0일7일14일21일28일정상실패재작업(핫픽스)처리량불안정성주 3회배포 빈도11시간변경 리드 타임(중앙값)68분실패 배포 복구시간(중앙값)17%변경 실패율17%재작업 배포비율지표는 서비스 하나 단위로 보고, 목표치로 삼기보다 추세를 본다.
4주 동안의 배포 기록으로 계산한 다섯 지표. 실패한 배포 뒤에 바로 이어진 핫픽스 배포가 재작업으로 세어진다.

예제 팀은 주 3회 배포하고, 리드 타임 중앙값은 11시간, 변경 실패율은 17%, 실패에서 복구하는 데 중앙값 68분이 걸렸다. DORA 연구가 되풀이해 보여 주는 결론은 속도와 안정성이 맞바꾸는 관계가 아니라는 것이다. 작은 변경을 자주 내보내는 팀이 대개 실패도 적고 복구도 빠르다. 다만 지표를 목표로 삼으면(‘하루 열 번 배포하라’) 숫자만 맞추는 행동이 생기므로, 서비스 하나 단위로 추세를 보며 병목을 찾는 데 쓴다.

핵심 자료

자료한 줄 요지
Continuous Integration (Martin Fowler)CI의 원래 뜻을 정리한 글. 모두가 하루에 적어도 한 번 main에 합치고, 자동 빌드·테스트가 늘 초록이어야 한다.
BlueGreenDeployment (Martin Fowler)똑같은 환경 둘을 두고 라우터만 바꿔 배포·되돌리기를 순간에 하는 방법.
Canarying Releases (Google SRE Workbook)카나리의 크기·기간·지표 고르기와, 카나리와 대조군을 비교해 판정하는 방법을 실무 관점에서 다룬다.
Feature Toggles (Pete Hodgson)기능 플래그를 출시·실험·운영·권한 네 종류로 나누고, 수명과 관리 비용을 다룬 표준 글.
Terraform 문서: Statestate 파일이 왜 필요한지, 원격 저장과 잠금, 민감 정보 취급을 설명한다.
OpenGitOpsCNCF 작업 그룹이 정한 GitOps 네 원칙: 선언형, 버전 관리·불변, 자동으로 끌어옴, 계속 맞춤.
SLSA빌드 출처 증명과 빌드 환경 강화를 수준별로 정한 공급망 보안 틀.
DORA 소프트웨어 전달 지표처리량(리드 타임·배포 빈도·복구 시간)과 불안정성(변경 실패율·재작업 비율) 다섯 지표의 정의.