왜 배포 프리즈가 필요한가
연말 쇼핑 시즌, 대규모 마케팅 이벤트, 규제 심사 기간처럼 장애 비용이 급증하는 구간이 있다. 이때는 평소라면 무해했을 배포도 리스크가 된다. 롤백 인력이 부족한 새벽·주말, 관계사와의 계약상 안정성 보장 기간도 마찬가지다. 배포 프리즈(change freeze)는 이런 구간에 프로덕션 변경을 의도적으로 막아 "예상치 못한 배포로 인한 장애" 자체를 제거하는 통제 장치다.
문제는 프리즈를 사람의 공지와 선의에만 맡기면 반드시 뚫린다는 점이다. 슬랙 공지를 못 본 팀, "이건 핫픽스라 예외"라고 스스로 판단한 개발자, 자동 스케줄 파이프라인이 각각 구멍이 된다. 그래서 프리즈는 파이프라인 레벨에서 강제되어야 한다.
동결의 세 가지 층위
동결은 하나가 아니라 대상별로 나눠 설계해야 한다. 전부 막으면 보안 패치까지 막혀 오히려 위험하다.
| 층위 | 대상 | 기본 정책 |
|---|---|---|
| 전체 동결 | 모든 프로덕션 배포 | 차단, 승인 시 예외 |
| 선택 동결 | 기능/스키마 변경 | 차단 |
| 상시 허용 | 보안 핫픽스, 롤백 | 허용(추적 필수) |
핵심은 "롤백과 보안 패치는 언제나 허용"이라는 원칙이다. 프리즈의 목적은 변경을 줄이는 것이지 장애 대응 능력을 없애는 것이 아니다.
프리즈 윈도우를 코드로 관리하기
동결 기간을 위키나 캘린더가 아닌 버전 관리되는 파일로 두면, 변경 이력이 남고 파이프라인이 그대로 읽어 쓸 수 있다.
freezes:
- name: "2026-year-end-sale"
start: "2026-11-25T00:00:00+09:00"
end: "2026-12-02T09:00:00+09:00"
scope: [prod]
allow_labels: [hotfix, rollback]
- name: "audit-window"
start: "2026-09-20T18:00:00+09:00"
end: "2026-09-22T09:00:00+09:00"
scope: [prod]
allow_labels: [rollback]
파이프라인 게이트 구현
배포 잡 앞단에 게이트 스텝을 두고, 현재 시각이 동결 구간에 들어가는지 검사한다. 예외 라벨이 있으면 통과시키되 반드시 로그를 남긴다.
import sys, yaml
from datetime import datetime, timezone
def is_frozen(now, cfg, env, label):
for f in cfg["freezes"]:
start = datetime.fromisoformat(f["start"])
end = datetime.fromisoformat(f["end"])
if env in f["scope"] and start <= now <= end:
if label in f.get("allow_labels", []):
print(f"[freeze] {f['name']}: '{label}' 예외 허용")
return False
print(f"[freeze] {f['name']} 활성: 배포 차단")
return True
return False
cfg = yaml.safe_load(open("freezes.yaml"))
now = datetime.now(timezone.utc)
frozen = is_frozen(now, cfg, sys.argv[1], sys.argv[2] or "")
sys.exit(1 if frozen else 0)
CI에서는 이 스크립트를 배포 전에 호출하고, 종료 코드가 0이 아니면 파이프라인을 실패시킨다.
deploy-prod:
stage: deploy
script:
- python check_freeze.py prod "$DEPLOY_LABEL" || exit 1
- ./deploy.sh prod
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
예외 승인 흐름
진짜 급한 배포는 반드시 생긴다. 이때 개인이 게이트를 우회하게 두면 통제가 무너진다. 대신 명시적 승인 경로를 만든다. 예외를 신청하면 온콜 리드가 승인하고, 승인 토큰이나 라벨이 부여될 때만 게이트를 통과하게 한다. 승인 기록은 누가·언제·왜 배포했는지 사후 추적할 수 있어야 하며, 이는 사고 후 리뷰와 감사 대응의 근거가 된다.
주의점
몇 가지 함정을 피해야 한다.
- 타임존: 설정 파일과 CI 러너의 시각 기준이 다르면 경계 시간에 오작동한다. 내부 비교는 UTC로 통일하라.
- 프리즈 해제 순간의 폭주: 동결이 풀리자마자 밀린 배포가 몰리면 그 자체가 장애다. 해제 직후는 배포 큐를 순차 처리하거나 카나리로 완충하라.
- 과도한 범위: 스테이징·개발까지 얼리면 프리즈 종료 후 검증 안 된 변경이 한꺼번에 나간다. scope는 prod로 좁혀라.
- 게이트 자체의 신뢰성: 설정 파일 파싱 실패 시 "통과"가 아니라 "차단"으로 fail-safe 처리해야 한다.
결국 배포 프리즈는 정책이 아니라 실행 가능한 코드일 때만 지켜진다. 사람의 기억 대신 파이프라인이 판단하게 만드는 것이 자동화의 핵심이다.