Engineering & Operations 가이드

롤백 가능한 배포를 만드는 법: 코드·설정·DB·트래픽을 함께 설계하기

핵심 답변

롤백 가능한 배포는 이전 코드가 남아 있는 상태가 아니라, 이전 버전과 새 버전이 일정 기간 같은 설정·DB·데이터 계약을 처리할 수 있고 기능 노출과 트래픽을 독립적으로 중단하며 복구 행동과 책임자를 미리 정해 둔 상태다.

코드 설정 데이터 트래픽이 이전 버전으로 되돌아갈 수 있는 배포 구조

롤백 가능한 배포는 이전 버전의 실행 파일을 보관해 둔 상태가 아니다. 이전 버전과 새 버전이 일정 기간 같은 설정, 데이터베이스 스키마, 데이터 형식과 외부 계약을 함께 처리할 수 있어야 한다. 여기에 기능 노출과 트래픽을 별도로 줄이거나 끌 수 있고 어떤 신호가 나타나면 누가 어떤 행동을 할지도 정해져 있어야 한다.

코드만 이전 버전으로 돌렸는데 장애가 더 커지는 경우가 있다. 새 배포가 이미 컬럼을 삭제했거나 데이터를 손실이 있는 형태로 변환했을 수 있다. Secret이 폐기됐거나 설정이 새로운 외부 시스템을 바라보고 있을 수도 있다. 새 형식의 메시지가 큐에 쌓인 뒤라면 이전 코드는 이를 읽지 못한다. 이런 상황에서 이전 바이너리를 다시 띄우는 것은 복구가 아니라 또 하나의 비호환 변경이다.

배포 도구는 정해진 행동을 실행하는 장치일 뿐이다. Kubernetes의 Deployment revision은 Pod template을 중심으로 관리되며 외부의 설정·DB·데이터를 함께 되돌리지 않는다. 진행이 멈춘 Deployment도 상태를 보고할 뿐, 해당 변경에 Rollback·Pause·Forward Fix 중 무엇이 맞는지는 상위 운영 체계가 결정해야 한다. (Kubernetes)

배포를 하나의 변경이 아니라 열 개의 계층으로 본다

안전한 배포를 설계하려면 “이번에 어떤 코드가 바뀌었는가”보다 “이번 변경이 어떤 상태와 계약을 바꾸는가”를 먼저 적어야 한다. 다음 표는 배포 전에 작성할 Layer-by-layer Rollback Contract다.

Layer-by-layer Rollback Contract

Layer 배포 전에 고정할 계약 실패 시 우선 행동 호환성 제거 조건 Owner
Code / Artifact 동일한 소스와 입력으로 식별 가능한 Artifact를 만들고 Digest·빌드 출처·이전 Artifact를 보존한다. 검증된 이전 Artifact로 트래픽을 돌리거나 해당 Replica를 다시 확장한다. Rollback Window가 닫히고 새 Artifact가 안정 상태로 승인된 뒤 Release Owner
Dependency Lockfile, Base Image, Runtime, SDK와 외부 API Version을 기록한다. 이전 Dependency 묶음을 사용하거나 호환 Adapter를 활성화한다. 이전 Runtime·API를 사용하는 실행 주체가 없어졌을 때 Application Owner
Configuration 설정에 Version과 Owner를 부여하고 형식뿐 아니라 의미 검증을 수행한다. 변경 가능한 외부 참조를 그대로 따라가지 않게 한다. 이전 설정 Version으로 복귀하거나 설정 Rollout을 중단한다. 이전·새 코드 모두 새 설정을 정상 처리하고 이전 참조가 제거됐을 때 Service / Platform Owner
Secret Secret Version, 유효 대상, 교체 순서와 Provider 장애 시 동작을 정한다. 보안상 허용되는 경우에만 짧은 중복 유효 기간을 둔다. 아직 유효한 Secret으로 전환하거나 새 Secret을 다시 배포한다. 유출된 Secret을 복원하지 않는다. 모든 이전 Consumer가 사라지고 새 Secret 사용이 확인된 뒤 Security / Platform Owner
DB Schema 먼저 추가적인 변경을 하고 일정 기간 이전·새 코드가 같은 Schema에서 동작하도록 한다. 이전 코드를 다시 사용하되 확장된 Schema는 유지한다. 이전 컬럼·테이블·제약을 사용하는 코드와 작업이 완전히 사라졌을 때 DB Owner
Data Migration Ledger, 재실행 가능성, 중단·재개 조건, 정합성 검사와 보상 방법을 정한다. Backfill을 멈추고 데이터를 보정하거나 Forward Fix한다. 필요하면 격리된 복구본에서 데이터를 재구성한다. Backfill·검증·대사가 끝나고 손실 없는 전환이 확인된 뒤 Data / Application Owner
Feature exposure Flag의 기본값, Provider 오류 시 값, 전파 지연, 권한과 감사 기록을 정의한다. Kill Switch를 실제로 시험한다. 기능 노출을 끄고 기존 동작으로 우회한다. 기능이 안정화되고 Flag가 더 이상 복구 수단이 아닐 때 Product + Application Owner
Traffic Version별 Route, Weight, Session Stickiness, Connection Drain, 비동기 Traffic의 귀속을 기록한다. Candidate Traffic을 0으로 낮추거나 이전 환경으로 전환한다. 이전 Version으로 돌아갈 운영 필요가 사라졌을 때 Traffic / Platform Owner
Health Signal Candidate와 Control을 구분할 수 있는 신호, 관찰 기간, 최소 Evidence와 행동을 연결한다. 확장 중단, Flag Off, Traffic 회수, Rollback 또는 Forward Fix 중 사전 지정된 행동을 실행한다. 배포 평가가 끝나고 증거와 결정 기록이 보존됐을 때 Service Owner / Incident Commander
Owner 중단 권한, Rollback 승인자, DB 변경 책임자, Traffic 실행자, 수동 Override와 Escalation을 명시한다. 담당자가 없는 자동화는 중단한다. Incident Mode로 전환해 하나의 의사결정권을 세운다. 변경 종료 기록과 후속 책임이 인계됐을 때 Change Owner

Google SRE는 Artifact의 재현성과 자동화, 설정의 소유자·Version·Semantic Validation, 점진 적용과 중단 가능성을 별개의 운영 조건으로 다룬다. 설정이 실행 시점마다 변경 가능한 외부 값을 따라가면 같은 Version으로 돌아가도 같은 상태가 재현되지 않을 수 있다. (Google SRE)

Deployment State Machine

배포 파이프라인을 실행 → 성공 또는 실패의 두 상태로 만들면 중간에서 할 수 있는 일이 Rollback 하나뿐이 된다. 실제 운영에는 적어도 다음 상태가 필요하다.

구조 다이어그램

text
Prepared
   │
   ▼
Partial Exposure
   │
   ▼
Evaluate / Bake
   ├────────► Expand
   ├────────► Pause
   ├────────► Rollback
   └────────► Forward Fix

Prepared에서는 Artifact, 설정, Secret, Schema 확장, Route와 관측 신호가 준비된다. 이전 Version으로 돌아갈 경로도 이때 검증해야 한다.

Partial Exposure에서는 새 Version을 제한된 Replica, 사용자 집단, 요청 비율 또는 Feature Flag 범위에만 노출한다.

Evaluate / Bake에서는 단순히 시간이 지나기를 기다리는 것이 아니라 Candidate와 Control의 차이, 비동기 작업의 완료, Cache와 Queue의 영향이 나타날 때까지 관찰한다.

결과가 좋으면 Expand, Evidence가 부족하거나 신호가 오염됐으면 Pause한다. 이전 상태와 호환성이 살아 있다면 Rollback할 수 있다. 데이터나 외부 상태가 이미 비가역적으로 바뀌었다면 수정 Version과 보상 작업을 적용하는 Forward Fix가 더 적절하다. Canary는 제한된 배포와 평가 절차를 결합한 것이며 Traffic을 적게 보냈다는 사실만으로 충분하지 않다. (Google SRE)

여기서 Pause는 중요한 상태다. 신호가 불확실한데 자동으로 이전 Version을 다시 배포하면, 원인과 무관한 두 번째 변경을 만들어 상황을 복잡하게 할 수 있다. 확장을 멈추되 현재 상태를 보존하면 비교와 진단에 필요한 Evidence를 잃지 않는다.

Backward Compatibility Window

이전 Version으로 돌아갈 수 있는 기간은 단순한 “Artifact 보관 기간”이 아니다. 이전 코드가 새 Schema와 새 데이터를 읽을 수 있고 새 코드도 아직 남아 있는 이전 데이터와 요청을 처리할 수 있는 기간이다.

구조 다이어그램

text
T0              T1                T2                 T3               T4              T5
│               │                 │                  │                │               │
Expand          N 배포            부분 노출·이전      전체 노출        Rollback         Contract
Schema·Config   기능은 비노출      Backfill·Dual Path  + Bake           Window 종료      파괴적 정리
│               │                 │                  │                │               │
N-1 계속 동작 ────────────────────────────────────────────────────────┘
N 새 경로      ────────────────────────────────────────────────────────────────────────►

실무에서 호환성을 유지해야 할 기간은 다음 항목 중 가장 긴 것보다 짧아서는 안 된다.

text 예시

text
호환성 유지 기간 ≥ max(
  Rollback 판단에 필요한 시간,
  가장 오래 실행되는 Batch·Job,
  Queue·Event의 최대 체류 시간,
  Client·Session·Cache의 수명,
  Backfill과 정합성 검증 시간,
  Secret 중복 유효 기간,
  복제 지연과 복구 검증 시간
)

이는 특정 도구의 공식 공식이 아니라, Parallel Change와 점진 배포 원칙을 하나의 운영 기준으로 통합한 모델이다. 오래된 Client나 Queue 메시지가 남아 있는데 호환 컬럼과 Adapter를 제거하면, 전체 트래픽이 새 Version으로 전환됐더라도 배포는 아직 끝난 것이 아니다. (martinfowler.com)

DB 변경은 Expand–Migrate–Contract로 나눈다

호환되지 않는 DB 변경을 코드 배포와 같은 순간에 실행하면 Rollback Window가 거의 즉시 사라진다. 이를 피하는 대표적인 방식이 Expand–Migrate–Contract다.

예를 들어 customer_name 컬럼을 display_name으로 바꾸려 한다고 하자.

1. Expand

새 컬럼을 추가하되 기존 컬럼을 지우지 않는다. 이전 코드와 새 코드가 모두 동작할 수 있는 Schema를 먼저 만든다. 새 컬럼이 비어 있어도 오류가 발생하지 않게 읽기 경로를 설계한다.

2. Migrate

새로 생성되는 데이터는 필요한 기간 동안 두 경로에 기록하거나, 한쪽을 원장으로 유지하면서 다른 쪽을 비동기로 채운다. 기존 데이터는 작은 단위로 Backfill하며 작업 위치와 결과를 기록한다. 중단 후 재개해도 중복 변환이나 데이터 손상이 없어야 한다.

3. Contract

읽기 경로가 새 컬럼으로 전환됐고 이전 Version·Batch·Queue Consumer가 더 이상 기존 컬럼을 사용하지 않는다는 Evidence를 확인한 뒤 별도 배포에서 기존 컬럼을 제거한다. “새 코드가 정상 배포됐다”와 “이전 계약을 제거해도 된다”는 서로 다른 결정이다. (martinfowler.com)

DB 엔진에 따라서도 운영 조건은 달라진다.

DB 공식 문서에서 확인할 점 배포 설계에 미치는 영향
PostgreSQL 18 ALTER TABLE은 하위 명령에 따라 강한 잠금을 얻거나 Table Rewrite를 일으킬 수 있다. 상수 Default 추가처럼 Rewrite를 피할 수 있는 경우도 있지만 조건을 확인해야 한다. (PostgreSQL) Migration 파일이 실행된다는 사실과 운영 중 안전하다는 사실은 다르다. 예상 Lock, Rewrite, 실행 시간, 복제 영향을 확인한다.
MySQL 8.4 Atomic DDL은 장애 시 일관성을 높이는 개념이지 사용자가 임의로 되돌리는 Transactional DDL과 같지 않다. 여러 DDL은 암묵적 Commit을 발생시키며 Metadata Lock의 영향을 받는다. (MySQL) 애플리케이션 Transaction과 같은 방식으로 DDL을 취소할 수 있다고 가정하지 않는다. Online DDL 지원 범위와 대기 Transaction을 별도로 검토한다.

시점 복구(Point-in-time Recovery)도 일반 배포 Rollback과는 다르다. PostgreSQL은 Base Backup과 WAL을 이용해 Cluster 전체를 특정 시점으로 복구하며 설정 파일은 별도 대상이다. MySQL 역시 전체 Backup과 Binary Log 재생을 결합한다. 운영 DB를 과거 시점으로 되돌리면 목표 시점 이후의 정상 변경까지 영향을 받을 수 있으므로, 먼저 격리된 복구본에서 필요한 데이터를 추출하고 현재 상태와 대사하는 방식이 더 적절한 경우가 많다. (PostgreSQL)

비가역 데이터 변경은 처음부터 표시한다

다음 변경에는 완전한 역변환이 없거나 비용이 지나치게 클 수 있다.

  • 여러 값을 하나로 합치는 손실성 집계
  • 원본을 버린 채 수행한 암호화·재인코딩
  • 중복 계정이나 레코드를 하나로 병합하는 작업
  • 외부 결제, 이메일, 메시지, Webhook 전송
  • 이미 소비된 Event와 비동기 작업
  • 복구 불가능하게 폐기한 암호화 키
  • 새 형식으로만 저장된 뒤 삭제된 원본 필드

이 경우 Rollback Contract의 행동은 “이전 코드 재배포”가 아니라 새 쓰기 중단 → 영향 범위 식별 → 수정 Version 배포 → 보상 Transaction 또는 데이터 Repair → 정합성 재검증이 될 수 있다.

비가역 여부가 불분명한 변경은 배포 문서에서 숨기지 말고 명시적으로 Forward Recovery Required로 분류해야 한다. 그래야 장애 중에 존재하지 않는 복구 경로를 찾느라 시간을 잃지 않는다.

Feature Flag와 Kill Switch는 같은 말이 아니다

Feature Flag는 Binary 배포와 사용자 노출을 분리한다. 새 코드를 배포하되 기능은 숨긴 채 두거나, 특정 사용자·Tenant·지역에만 열 수 있다. Google SRE도 Feature Flag를 Binary Release와 Launch를 분리하고 문제가 있는 기능을 선택적으로 끄는 수단으로 설명한다. (Google SRE)

그러나 모든 Flag가 운영용 Kill Switch인 것은 아니다. 안전한 Kill Switch로 사용하려면 다음 계약이 필요하다.

  • Flag Provider가 응답하지 않을 때 사용할 안전한 기본값
  • 변경이 모든 Instance에 전파되는 최대 시간
  • 사용자·Tenant·지역별 적용 범위
  • 변경 권한과 감사 기록
  • 비상 상황에서 별도 배포 없이 조작할 수 있는 경로
  • 실제 운영 조건을 반영한 Off 경로 테스트
  • 제거 예정일과 담당자

OpenFeature는 Flag 평가 API, Provider, Evaluation Context, Hook와 Provider 상태 이벤트를 표준화한다. 평가 오류 시 애플리케이션이 전달한 기본값을 반환하도록 정의하지만 어떤 기본값이 안전한지와 Flag 변경이 데이터 부작용을 되돌릴 수 있는지는 애플리케이션 설계의 책임이다. (OpenFeature)

이미 새 형식의 데이터를 기록했거나 외부 요청을 전송했다면 Flag를 꺼도 해당 상태는 남는다. Feature Flag는 노출을 중단하는 제어 장치이지 데이터 복구 장치가 아니다.

Rolling·Canary·Blue-green·Traffic Split의 역할

네 용어는 서로 배타적인 선택지가 아니다. Canary를 별도 Deployment와 Traffic Split으로 구현할 수도 있고 Blue-green 환경 사이에서 일부 Traffic만 새 환경으로 보내며 평가할 수도 있다.

방식 무엇을 바꾸는가 장점 숨은 호환성 조건 대표 복구 행동
Rolling 실행 중인 Instance를 순차적으로 새 Version으로 교체한다. 추가 환경을 크게 늘리지 않고 점진 교체할 수 있다. 이전·새 Version이 동시에 실행되므로 DB·API·Message 계약이 호환돼야 한다. Rollout 중단, 이전 Replica 확장
Canary 일부 Instance·사용자·요청에 Candidate를 제한된 시간 노출한다. 영향 범위를 줄이고 Candidate와 Control을 비교할 수 있다. 표본이 대표성을 가져야 하며 공유 DB·Cache·Dependency가 Control까지 오염시킬 수 있다. 노출 중단, Traffic 회수, Flag Off
Blue-green 이전 환경과 새 환경을 병렬로 유지하고 Route를 전환한다. 이전 환경을 보존한 채 새 환경을 검증하고 Route를 빠르게 되돌릴 수 있다. 공유 DB, Session, Connection, Secret과 외부 부작용이 이전 환경에서도 처리 가능해야 한다. Route를 이전 환경으로 되돌림
Traffic Split Router나 Gateway에서 Version별 요청 비율을 조정한다. 1%·10% 같은 비율뿐 아니라 사용자·Tenant·지역 기준으로 노출을 제어할 수 있다. Session Stickiness, WebSocket, Queue·Batch와 공유 상태를 별도로 다뤄야 한다. Candidate Weight를 낮추거나 0으로 전환

Kubernetes의 RollingUpdate에서는 교체 중 이전·새 Pod가 동시에 존재할 수 있다. Google SRE는 Canary를 부분적이고 시간 제한이 있는 배포와 평가 절차로 정의하며 대표 Traffic·측정 주기·공유 Dependency의 영향을 함께 고려하도록 한다. Blue-green은 Route 전환을 빠르게 할 수 있지만 DB와 상태 계약까지 자동으로 분리하지는 않는다. (Kubernetes)

Bake Time은 고정된 분 단위가 아니다

Bake Time은 “배포 후 30분 대기”처럼 정해 두는 휴식 시간이 아니다. 이번 변경의 주요 실패가 관측될 만큼 대표적인 작업이 실제로 지나가는 기간이다.

다음 항목에 따라 필요한 시간이 달라진다.

  • 요청량과 사용자 유형의 다양성
  • 주간·야간, 평일·주말의 Traffic Pattern
  • 가장 오래 걸리는 Batch와 비동기 작업
  • Queue 지연과 Retry 간격
  • Cache·Session의 수명
  • 외부 Dependency의 호출 빈도
  • Metric 집계 주기와 지연
  • 데이터 Backfill과 정합성 검증 시간

Traffic이 적은 서비스에서는 짧은 Canary보다 Synthetic Request나 명시적 검증 시나리오가 더 필요할 수 있다. 반대로 요청량이 많아도 Candidate와 Control을 구분하지 않은 전체 평균만 보면 Candidate의 오류가 정상 Traffic에 가려질 수 있다. (Google SRE)

Rollback Trigger는 다음 정도로 구체화해야 한다.

yaml 예시

text
signal: "이미 정의된 사용자·서비스 건강 신호"
scope: "candidate | control | 전체 시스템"
condition: "Candidate와 Control의 허용 차이 또는 절대 차단 조건"
observation_window: "해당 실패가 나타나는 데 필요한 기간"
minimum_evidence: "최소 요청·작업·사용자 집단"
action: "pause | flag_off | traffic_zero | rollback | forward_fix"
owner: "결정권자와 실행자"
manual_override: "권한, 사유 기록, 만료 조건"

어떤 사용자 여정을 어떤 SLI로 만들 것인지는 별도 관측 설계의 영역이다. 이 글에서는 이미 정의된 건강 신호를 배포 행동과 연결하는 데서 멈춘다.

자동 Rollback이 더 위험해지는 경우

자동화가 가장 먼저 해야 할 행동은 항상 이전 Version 재배포가 아니다. 다음 상황에서는 자동 Pause나 노출 중단이 더 안전할 수 있다.

상황 자동 Rollback의 위험 더 적절한 첫 행동
Candidate가 공유 DB에 이전 코드가 읽지 못하는 데이터를 기록함 이전 코드가 같은 데이터를 읽으며 추가 오류를 만든다. 새 쓰기 중단, Traffic 분리, Forward Repair
보안 취약점을 막기 위해 이전 Version과 Secret을 폐기함 이전 Version으로 돌아가며 취약점이나 폐기된 Credential을 되살린다. 수정 Version 배포, 새 Secret 재발급
외부 Dependency 장애가 Candidate 오류처럼 보임 원인과 무관한 재배포로 부하와 변수를 늘린다. 확장 중단, Candidate·Control 비교
결제·메일·Webhook 같은 외부 부작용이 이미 발생함 코드만 바뀌고 외부 세계의 상태는 남는다. 중복 실행 차단, 보상 작업
이전 환경의 Cache가 차갑거나 용량이 부족함 Traffic 복귀가 새로운 과부하를 만든다. 점진 Traffic 회수, 용량 확보
여러 Canary나 설정 변경이 동시에 진행 중임 신호의 원인을 구분하지 못한 채 반복 Rollback이 발생한다. 모든 확장 중단, 변경 분리
신호가 짧게 흔들리며 자동화가 반복 동작함 Version이 오가는 Flapping과 추가 장애가 발생한다. Cooldown, 수동 승인, Incident Mode
이전 Artifact·설정이 실제로 재검증되지 않음 돌아간 뒤에야 이전 상태가 이미 사용할 수 없음을 알게 된다. 이전 경로 점검 후 수동 결정

Google SRE는 Canary 평가에서 Candidate와 Control의 오염, 관찰 기간, Rollout 중단과 사람의 판단을 함께 다룬다. Kubernetes 역시 진행 실패를 상태로 표시하지만 복구 행동을 대신 결정하지 않는다. DB의 Lock·Rewrite·PITR 범위까지 고려하면, DB·데이터·Secret·Restore 경로를 무조건 자동화하는 것보다 Traffic 확장 중단을 먼저 자동화하는 편이 안전한 경우가 많다. (Google SRE)

Rollback·Roll-forward·Failover·Restore는 서로 다른 행동이다

행동 바꾸는 대상 적합한 상황 데이터에 미치는 영향 주요 위험
Rollback Code, Config, Feature exposure, Traffic을 이전의 호환 가능한 상태로 돌린다. 이전 상태와의 계약이 아직 유효하고 Candidate 영향이 제한적일 때 일반적으로 현재 데이터를 유지하지만 이전 코드가 이를 처리할 수 있어야 한다. Schema·Data·Secret이 비호환이면 실패
Roll-forward / Forward Recovery 수정 코드, Adapter, Migration 또는 데이터 Repair를 새 Version으로 적용한다. 상태 변경이 비가역적이거나 이전 Version이 보안·호환성상 사용할 수 없을 때 현재 상태를 보존하며 잘못된 부분을 수정한다. 수정이 충분히 검증되지 않으면 추가 변경 위험
Failover Traffic이나 역할을 정상 Replica·Region·Environment로 전환한다. 특정 Instance·Zone·Region 또는 Primary가 사용할 수 없을 때 복제 상태와 RPO에 따라 최신 데이터 차이가 날 수 있다. 동일한 결함 Version이 대상 환경에도 있으면 문제 지속
Restore Backup·Snapshot·WAL·Binary Log로 데이터 상태를 재구성한다. 삭제·손상·오염으로 현재 데이터 자체를 신뢰할 수 없을 때 목표 시점 이후 변경을 잃거나 별도 대사가 필요할 수 있다. 긴 복구 시간, 정상 변경 손실, 의존 시스템과 불일치

Failover는 실행 위치를 바꾸는 행동이고 Restore는 데이터를 재구성하는 행동이다. 소프트웨어 결함이 모든 환경에 배포됐다면 Failover만으로 해결되지 않는다. 데이터가 손상되지 않았다면 전체 Restore는 오히려 정상 Transaction까지 과거로 돌릴 수 있다. (Microsoft Learn)

Pre-deployment Rollback Readiness Checklist

Artifact와 Dependency

  • 배포할 Artifact의 Digest와 Build Provenance가 기록돼 있다.
  • 개발 환경에서 다시 Build하는 것이 아니라 검증된 동일 Artifact를 승격한다.
  • 이전 Artifact가 실제 실행 가능한 상태로 보존돼 있다.
  • Lockfile, Base Image, Runtime과 주요 SDK Version을 확인했다.
  • 외부 API·Message·Event 계약의 이전·새 Version 호환성을 확인했다.

Configuration과 Secret

  • Configuration에 Version과 Owner가 있다.
  • 형식 검사 외에 Endpoint, 범위, 단위, 상호 배타 조건을 포함한 의미 검증을 수행했다.
  • 실행 시점에 바뀌는 외부 참조를 그대로 따라가지 않는다.
  • Secret 교체 순서와 이전 Secret의 유효 종료 조건이 있다.
  • Provider 장애 시 Feature Flag와 Secret 조회의 기본 동작을 확인했다.
  • 유출·폐기된 Secret을 Rollback 대상으로 사용하지 않는다.

DB Schema와 Data

  • 파괴적 변경 전에 Additive Expand를 수행했다.
  • 이전 Version이 Expanded Schema에서 읽고 쓸 수 있다.
  • Migration이 중단·재개·재실행 가능하다.
  • Backfill 진행 위치와 정합성 검사 결과를 기록한다.
  • Dual Write를 사용한다면 불일치 탐지와 대사 방법이 있다.
  • 비가역 데이터 변경과 외부 부작용을 별도로 표시했다.
  • Rollback이 불가능한 변경에는 Forward Recovery 절차가 있다.
  • DB 엔진과 Version별 Lock·Rewrite·암묵적 Commit 조건을 확인했다.

Feature exposure와 Traffic

  • Binary 배포와 기능 노출을 분리할 수 있다.
  • Kill Switch의 Off 경로를 실제 운영 조건으로 시험했다.
  • Candidate와 Control을 구분하는 Route·Label이 있다.
  • Traffic Weight를 낮추거나 0으로 만드는 권한과 절차가 있다.
  • Session, Connection Drain, WebSocket, Queue·Batch Traffic을 고려했다.
  • 이전 환경에 Traffic을 되돌릴 때 필요한 용량을 확인했다.

Signal과 결정

  • 배포 전 이미 정의된 건강 신호를 Candidate 기준으로 볼 수 있다.
  • Rollback Trigger에 관찰 기간과 최소 Evidence가 포함돼 있다.
  • Pause, Flag Off, Traffic Zero, Rollback, Forward Fix가 구분돼 있다.
  • 자동 행동의 Cooldown과 수동 Override가 있다.
  • 중단 권한자와 실행 담당자가 명시돼 있다.
  • 야간·휴일·담당자 부재 시 Escalation 경로가 있다.

복구 검증

  • 이전 Artifact·Config로 실제 복귀하는 Rehearsal을 수행했다.
  • Backup 존재 여부와 별도로 Restore 절차를 시험했다.
  • 복구 소요 시간과 데이터 손실 범위를 기록했다.
  • Incident 중 변경을 하나로 통제할 책임자가 있다.
  • 배포·판정·Override 기록을 보존할 위치가 있다.

Post-deployment Compatibility Removal Checklist

전체 Traffic이 새 Version으로 전환됐다고 곧바로 이전 계약을 제거하지 않는다.

  • 이전 Version으로 향하는 동기 Traffic이 없다.
  • 오래된 Client·Session·Cache가 더 이상 이전 계약을 사용하지 않는다.
  • 이전 형식의 Queue·Event·Batch 작업이 모두 처리됐다.
  • Backfill이 완료됐고 원본과 대상의 정합성을 확인했다.
  • Dual Write 불일치가 없거나 승인된 허용 범위 안에 있다.
  • 이전 컬럼·API·Message Schema 사용량이 0임을 확인했다.
  • 이전 Secret을 사용하는 Consumer가 없다.
  • Rollback Window 종료를 Change Record에 명시했다.
  • 이전 Secret 폐기와 권한 회수를 별도 변경으로 수행했다.
  • Feature Flag, Adapter, 임시 Read Fallback의 제거 Owner와 날짜가 있다.
  • 이전 컬럼·테이블 삭제는 Cutover와 분리된 별도 배포로 실행한다.
  • Migration 이후 새로운 Backup 또는 복구 기준점을 확인했다.
  • Runbook, Schema 문서, Dependency 기록과 운영 인계를 갱신했다.
  • 제거 작업 자체에도 새로운 Rollback·Forward Recovery 계획이 있다.

호환성 코드는 기술 부채가 될 수 있다. 그렇다고 새 Version이 정상이라는 이유만으로 같은 배포에서 제거하면 가장 중요한 복구 경로를 스스로 닫게 된다. 추가·이전·제거를 서로 다른 변경으로 분리해야 각 단계의 실패 원인과 복구 행동도 분리할 수 있다.

되돌릴 수 있는 배포는 배포 전에 만들어진다

Rollback 버튼은 마지막 실행 장치다. 그 버튼이 안전하려면 이전 코드가 새 Schema를 처리하고 이전 환경이 현재 Traffic과 Session을 받을 수 있으며 설정과 Secret의 이전 상태가 여전히 유효해야 한다. 데이터 변경에 역변환이 없다면 버튼을 누르기 전에 이미 Rollback 선택지는 사라진 것이다.

운영 중 가장 좋은 첫 행동은 때로 이전 Version 재배포가 아니라 노출 확대를 멈추는 것이다. 그다음 현재의 호환성 계약을 확인해 Rollback, Forward Recovery, Failover, Restore 중 맞는 행동을 고른다.

WordPress 서버 이전처럼 DNS·Cache·Cron·DB 동기화가 함께 바뀌는 작업에도 같은 Rollback Contract가 필요하다. 다만 WordPress의 구체적인 Preflight와 Cutover 절차는 별도 Migration Runbook에서 다룬다.