← 모든 글

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 이 실제로 사고 하나를 막았나” 한 줄 적기로.


🛒 이 글과 어울리는 추천 상품

위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.