이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • 운영 데이터 재처리 runbook에는 어떤 승인, 범위, 실행, 검증, 종료 절차가 들어가야 하는가?
  • 재처리 중 운영 부하와 데이터 오염을 막기 위해 누가 어떤 지표를 보는가?
  • 수동 replay와 backfill 작업 이력을 어떻게 남겨야 나중에 감사와 회고가 가능한가?
  • 개인 프로젝트에서도 runbook 형태로 남겨야 하는 최소 항목은 무엇인가?

개요

runbook은 장애 때 사람이 그대로 따라 실행할 수 있는 절차다.

재처리는 데이터와 운영 부하를 동시에 바꾸는 작업이므로 구두 지시로 실행하면 위험하다.

누가 승인했고, 어떤 범위를, 어떤 속도로, 어떤 검증 기준으로 처리했는지 남겨야 한다.

runbook은 문서가 아니라 운영 안전장치다.

Runbook 기본 구조

1. 목적과 incident id
2. source와 target
3. 재처리 range
4. dry run 방법
5. batch size와 rate limit
6. stop condition
7. 실행 command
8. 검증 query
9. rollback 또는 보상 절차
10. 결과 기록 위치

이 항목이 없으면 작업자가 매번 판단해야 한다.

장애 중에는 판단 여유가 줄어들기 때문에 runbook은 평소에 준비되어 있어야 한다.

승인과 소유자

재처리에는 owner가 필요하다.

데이터 owner, 서비스 owner, 실행자, 승인자를 구분한다.

정산 데이터라면 재무 또는 정산 담당 확인이 필요할 수 있다.

알림 재발송이라면 고객 영향 승인도 필요하다.

owner 없이 재처리를 시작하면 결과가 틀렸을 때 책임과 판단 기준이 흐려진다.

범위 정의

범위는 구체적이어야 한다.

source: orders
target: order_daily_summary
range: created_at >= 2026-04-01 and created_at < 2026-07-01
exclude: status = 'TEST'
reason: Q2 summary transform bug

“최근 데이터 다시 처리” 같은 표현은 부족하다.

SQL where 조건이나 event offset range로 바꿀 수 있어야 한다.

범위가 클수록 dry run과 샘플 검증을 먼저 한다.

Dry Run

dry run은 실제 write 전에 영향 범위를 계산한다.

SELECT count(*), sum(amount)
FROM orders
WHERE created_at >= :from AND created_at < :to;

dry run 결과는 runbook에 기록한다.

예상 처리 건수와 예상 금액 합계가 있어야 완료 후 비교할 수 있다.

dry run 없이 실행하면 완료 후 맞는지 틀린지 판단하기 어렵다.

실행 Command

재처리 command는 인자를 명시해야 한다.

java -jar app.jar reprocess-order-summary \
  --run-id=order-summary-2026-q2 \
  --from=2026-04-01 \
  --to=2026-07-01 \
  --batch-size=1000 \
  --sleep-ms=300

command는 run id를 받아야 한다.

run id가 있어야 log, metric, checkpoint, 결과를 하나로 묶을 수 있다.

Stop Condition

runbook에는 멈출 기준이 있어야 한다.

  • API p95 latency 임계치 초과
  • DB CPU 임계치 초과
  • replica lag 증가
  • error rate 증가
  • duplicate side effect 발견
  • validation gap 증가

중단은 실패가 아니다.

checkpoint가 있으면 멈췄다가 안전하게 이어갈 수 있다.

검증 Query

완료 검증은 source와 target의 의미 있는 숫자를 비교한다.

SELECT count(*), sum(amount)
FROM orders
WHERE created_at >= :from AND created_at < :to;
SELECT count(*), sum(paid_amount)
FROM order_daily_summary
WHERE order_date >= :from_date AND order_date < :to_date;

count, sum, latest timestamp, sample row를 함께 본다.

검증 query도 runbook에 그대로 있어야 한다.

작업 기록

재처리 결과는 별도 table이나 incident 문서에 남긴다.

CREATE TABLE reprocess_audit_logs (
    run_id varchar(80) PRIMARY KEY,
    operator varchar(80) NOT NULL,
    approved_by varchar(80) NOT NULL,
    range_text text NOT NULL,
    started_at timestamp NOT NULL,
    finished_at timestamp,
    status varchar(20) NOT NULL,
    result_summary text
);

작업 기록은 재처리 자체의 감사 로그다.

나중에 같은 지표가 또 흔들릴 때 어떤 보정이 있었는지 확인할 수 있다.

커뮤니케이션

재처리는 데이터 사용자에게 영향을 준다.

대시보드 수치가 바뀌거나 알림이 재발송될 수 있다.

runbook에는 알림 대상이 있어야 한다.

예를 들어 데이터 팀, CS, 서비스 owner, on-call 채널을 구분한다.

완료 후에는 검증 결과와 남은 리스크를 공유한다.

개인 프로젝트 기준

개인 프로젝트에서도 runbook을 짧게 남긴다.

  • 목적
  • range
  • 실행 command
  • batch size와 sleep
  • checkpoint 위치
  • 검증 SQL
  • 실패 시 재시작 방법

이 일곱 가지가 있으면 단순 스크립트가 아니라 운영 가능한 재처리로 보인다.

위험 신호!

  • 재처리 범위가 구두로만 정해진다.
  • dry run 없이 바로 write를 실행한다.
  • stop condition이 없다.
  • 완료 검증 query가 없다.
  • 누가 언제 어떤 command를 실행했는지 기록이 없다.

확인 질문

확인 질문

  • 이 재처리는 누가 승인했고 어떤 run id로 추적되는가?
    • owner, operator, approval이 기록되어야 한다.
  • 실행 전 예상 count와 sum은 얼마였고 완료 후 값은 무엇인가?
    • dry run과 validation query 결과를 비교해야 한다.
  • 중간에 멈추면 어떤 checkpoint부터 재시작하는가?
    • runbook에 재시작 command와 checkpoint 기준이 있어야 한다.

참고 문서