Backfill, 어디까지 자동으로 믿을 수 있나
데이터 파이프라인 재처리 전략 — 자동화의 범위를 어디에 그을지
자동 backfill 을 믿었다가
올해 초 로그 적재 파이프라인이 3시간 죽었다. 복구 후 Airflow 의 catchup=True 가 조용히 밀린 구간을 전부 재실행했다. 문제는 그 3시간 안에 upstream 스키마가 바뀌어 있었다는 것. 자동 backfill 은 성공 코드를 돌려줬고, 테이블엔 조용히 null 컬럼이 쌓였다. 알아챈 건 이틀 뒤 대시보드 이상치 알림이었다.
이 경험이 내 backfill 기준선을 바꿨다.
재처리 전략을 구간별로 나누기
막상 정리해보면 backfill 상황은 크게 세 가지로 쪼개진다.
1) 단순 공백 — 파이프라인이 멈췄던 구간
upstream 이 변하지 않았고, 로직도 그대로라면 catchup 자동 실행이 맞다. 단, 전제 조건을 코드로 확인해야 한다. 우리 팀은 DAG 진입 시점에 간단한 schema fingerprint 를 비교하는 assertion 을 넣었다.
def assert_schema_unchanged(conn, table, expected_hash):
current = get_schema_hash(conn, table)
if current != expected_hash:
raise ValueError(f"Schema changed: {table} ({current})")
이 한 줄이 없었으면 이번 사고도 자동으로 묻혔을 것이다.
2) 로직 변경 backfill — 과거 데이터를 새 기준으로 재산출
이건 자동화해선 안 된다. 범위·우선순위·비용이 매번 다르다. 예를 들어 집계 지표 산식이 바뀌면 어디까지 소급할지는 비즈니스 판단이다. 기술적으로 가능하다고 자동 실행하면 과거 리포트 수치가 조용히 바뀐다. 이해관계자가 나중에 발견하면 신뢰 문제가 된다.
우리는 이 케이스는 무조건 PR + 별도 수동 트리거로 분리했다. manual_backfill_YYYYMMDD 식 DAG ID 를 찍어두면 추적도 쉽다.
3) 데이터 유실 backfill — upstream 에서 과거 데이터를 다시 밀어주는 경우
제일 까다롭다. 보통은 원천 시스템이 재전송한 데이터가 멱등하다고 가정하는데, 막상 해보면 타임스탬프나 이벤트 순서가 미묘하게 다른 경우가 있다. 자동 upsert 는 OK 지만, 반드시 row count + checksum 비교를 재처리 후 자동으로 찍어야 한다. 사람이 보는 것과 별개로 로그에 남겨야 나중에 근거가 된다.
자동화의 경계를 정하는 기준
정리하면 내가 쓰는 기준은 하나다.
재처리 결과가 틀렸을 때, 그 사실을 파이프라인 스스로 감지할 수 있는가?
감지 가능하면 자동화해도 된다. 감지 불가능하면 사람이 트리거해야 한다.
구체적으로:
- schema / row count / null rate 이상 → assertion 으로 커버 가능 → 자동 OK
- 비즈니스 지표의 “맞음/틀림” → 코드로 판단 불가 → 수동 트리거
- 재처리 범위가 30일 이상 → 비용·영향도 검토 필수 → 수동 트리거
catchup=True 를 기본값으로 쓰는 팀이 많은데, 나는 2026년 기준으론 catchup=False 를 기본으로 놓고 명시적으로 허용하는 쪽이 더 안전하다고 본다. 파이프라인이 복잡해질수록 자동 재실행의 사이드이펙트가 비선형으로 커진다.
또 하나 — backfill 전용 pool 을 따로 두는 것. 재처리가 운영 DAG 와 worker 를 공유하면 정상 배치가 밀린다. 우리는 Airflow pool 을 backfill_pool: 4 로 제한해서 운영과 격리했다. 단순한 설정이지만 재처리 중 on-call 이 울리는 빈도가 확 줄었다.
다음 한 가지
재처리 결과에 대한 assertion 을 DAG 안에 넣기로 했으니, 다음 글을 쓸 때 “그 assertion 이 실제로 사고 하나를 막았나” 한 줄 적기로.
🛒 이 글과 어울리는 추천 상품
위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.