CI/CD 용어 사전
파이프라인아티팩트 승격 · 환경 승격 · 승격 · 빌드 한 번 · build once

한 번 빌드, 여러 번 배포

환경마다 다시 빌드하지 않는다. 테스트한 그 산출물이 그대로 운영에 올라가야 한다.

파이프라인 설계의 가장 중요한 원칙 하나. 산출물은 한 번만 만들고, 그 똑같은 것을 스테이징 → 운영으로 옮긴다.

빌드 1회 → 아티팩트(이미지 sha256:abc…)
              ├→ 개발    배포
              ├→ 스테이징 배포   ← 여기서 테스트한 그것이
              └→ 운영    배포   ← 그대로 여기로 간다

환경마다 빌드하면 무엇이 깨지나

같은 커밋을 다시 빌드해도 결과가 같다는 보장이 없다.

  • 의존성 버전이 범위로 지정돼 있으면 그 사이 새 버전이 나온다
  • 베이스 이미지의 latest 태그가 바뀐다
  • 빌드 시각·환경 변수가 산출물에 박힌다

그러면 스테이징에서 검증한 것과 운영에 올라간 것이 다른 물건이 된다. "스테이징에선 됐는데" 의 상당수가 여기서 나오고, 무엇보다 테스트가 증명하는 대상이 사라진다 — 통과한 그것이 배포되지 않았으니까.

그럼 환경별 차이는 어떻게 주나

산출물이 하나여야 하니, 다른 점은 바깥에서 주입한다.

  • 설정은 환경 변수·설정 파일로 실행 시점에 주입
  • 비밀 값은 비밀 관리 시스템에서 실행 시점에 읽는다
  • 환경별로 다른 코드 경로를 컴파일해 넣지 않는다

"무엇을 실행하는가" 는 고정하고 "어떤 값으로 실행하는가" 만 바꾼다. 컨테이너 이미지가 이 원칙과 잘 맞는 것도 같은 이유다.

무엇이 산출물이 되나

컨테이너 이미지   registry/app@sha256:abc…   ← 가장 다루기 쉽다
JAR·바이너리      artifact 저장소의 버전 고정
정적 파일         해시가 붙은 파일명

공통점은 불변이라는 것이다. 한 번 만들어지면 내용이 바뀌지 않고, 이름만으로 그 내용이 특정된다. 이 성질이 있어야 "테스트한 그것" 이라는 말이 성립한다.

빌드 정보를 산출물에 심는다

LABEL org.opencontainers.image.revision=<git sha>
LABEL org.opencontainers.image.created=<빌드 시각>

운영에서 문제가 생겼을 때 떠 있는 것에서 커밋으로 거슬러 올라갈 수 있어야 한다. 애플리케이션이 자기 버전을 상태 확인 응답에 실어 주면 더 빠르다. 이것이 없으면 사고 대응의 첫 5분을 "무엇이 올라가 있나" 를 찾는 데 쓴다.

승격이 곧 추적이다

운영에 떠 있는 것이 어느 커밋인지 다이제스트 하나로 되짚을 수 있다. 태그는 옮길 수 있으므로 승격은 sha256: 다이제스트로 고정하는 것이 안전하다. 사고가 났을 때 "무엇이 올라가 있었나" 에 즉시 답할 수 있는지가 이 원칙을 지켰는지를 가른다.

그럼 무엇을 언제 검증하나

빌드 직후   단위 테스트 · 정적 분석 · 취약점 스캔
스테이징    통합 · E2E · 성능        ← 운영과 같은 산출물로
운영        스모크 테스트 · 지표 확인

산출물이 하나이므로 검증 결과가 누적된다. 스테이징에서 통과한 그 이미지가 운영으로 가므로, 앞 단계의 통과가 뒤 단계에 대한 근거가 된다. 환경마다 다시 빌드하면 이 누적이 성립하지 않아 매 단계 처음부터 다시 의심해야 한다.

설정도 버전 관리한다

산출물을 고정해도 설정이 손으로 바뀌면 재현성이 다시 깨진다. 운영에서만 누가 값을 하나 바꿔 뒀다면 그것은 기록되지 않은 변경이다. 설정을 저장소에 두고 같은 경로로 배포하면, 무엇이 다른지가 항상 diff 로 드러난다.

면접 함정

  • "환경마다 빌드해야 그 환경에 맞는 산출물이 나온다" → 차이는 설정으로 준다. 산출물이 달라지면 테스트가 무의미해진다.
  • "같은 커밋이면 같은 결과" → 의존성·베이스 이미지가 그 사이 바뀔 수 있다.
  • "태그로 승격하면 된다" → 태그는 옮겨질 수 있다. 다이제스트로 고정한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 무엇을 자동화하는 것인가 — CI·CD·배포 전략