멱등 싱크 없는 파이프라인은 왜 중복 적재를 피할 수 없나?

결론부터: 멱등 싱크가 없으면 재시도·부분 실패·백필 세 가지 경로 중 하나로 중복이 반드시 들어온다. 레이크하우스 포맷은 저장 이후 자동으로 중복을 걸러주지 않으므로, 추적·차단 로직을 파이프라인 쪽에 명시적으로 둬야 한다. 이 글은 그 로직을 어디에, 어떤 비용으로 배치하는지를 뜯는다.

  • 중복은 대부분 단일 배치 내 중복, 재시도 중복, 기본키 부재 세 유형으로 수렴한다.
  • Delta Lake·Iceberg는 MERGE를 명시하지 않으면 저장소 차원에서 중복을 막지 않는다.
  • 스트리밍에서는 상태 TTL을 얼마나 잡느냐가 추적 정확도와 비용을 동시에 결정한다.
  • 처리량 비교는 sync 시작·종료 시각 기준으로 재는 방식이 실무 표준에 가깝다.
  • 상류 차단이 하류 제거보다 재처리 비용 관점에서 일관되게 유리하다.

이 글은 배치 적재, 스트리밍 상태 관리, 레이크하우스 저장 계층 세 층위에서 중복이 발생·잔존하는 지점을 다룬다. 오케스트레이션 도구별 리트라이 정책이나 특정 벤더 커넥터의 내부 구현까지는 들어가지 않는다.

중복은 파이프라인의 어느 지점에서 새는가?

가장 흔한 세 지점은 단일 배치 내 중복, 재시도로 인한 중복, 기본키·고유 식별자 부재다. 단일 배치 내 중복은 소스 쿼리 자체가 같은 레코드를 두 번 뽑아올 때 생기고, 재시도 중복은 적재 작업이 커밋 여부를 확인하지 못한 채 재실행될 때 생긴다. 기본키가 없으면 이 둘을 사후에 구분할 방법 자체가 사라진다(Onehouse). 멱등 싱크가 있다면 같은 레코드를 몇 번 밀어 넣어도 최종 상태는 한 번 넣은 것과 같아지지만, 그런 싱크가 없으면 이 세 지점 각각에 별도 방어선을 세워야 한다.

레이크하우스는 왜 저장 후 중복을 자동으로 걸러주지 않나?

Delta Lake와 Iceberg 모두 기본값은 append이고, 중복 제거는 MERGE 구문을 명시적으로 호출해야 일어난다. 저장 이후 시점에 기본키를 강제하거나 쿼리 시점에 자동으로 중복을 접어주는 동작은 기본 제공되지 않는다(Onehouse). 즉 "레이크하우스에 넣었으니 정합성은 확보됐다"는 가정은 성립하지 않고, MERGE 조건절과 그 조건절이 참조할 키 설계가 파이프라인 쪽 책임으로 남는다.

스트리밍에서 상태 기반 중복 제거는 어떻게 설계하나?

핵심은 상태 보관 기간, 즉 TTL이다. Flink 기반 적재 최적화 가이드는 중복 제거용 상태를 sql.state-ttl로 명시하도록 안내하는데, 이 값이 곧 "몇 초·몇 시간 전 레코드까지 중복으로 인식할 것인가"의 경계가 된다. TTL을 짧게 잡으면 상태 저장 비용은 줄지만 그 창을 벗어난 지연 도착 레코드는 중복으로 걸러지지 않는다. 같은 문서는 중복을 가능한 한 빨리 걸러 downstream datastore로 보내지 않는 편이 낫다고 명시한다 — 하류에서 걸러내는 것보다 상류 차단이 신선도와 재처리 비용 모두에서 유리하다는 뜻이다.

처리량과 중복 제거 효과는 실제로 어떻게 측정됐나?

Fivetran은 2025-01-16 공개 문서에서 처리량을 1TB / (sync 종료 - sync 시작)으로 정의한다(Fivetran). 이 정의는 재처리 비용을 비교할 때 "동기 1회당 실제 완료 시간"을 기준선으로 잡게 해준다 — 다만 하드웨어·부하·버전 조건이 스니펫만으로는 확인되지 않으므로, 실제 비교에는 원문 표를 함께 봐야 한다.

사례 쪽에서는 MinIO가 소개한 WeChat 인프라 전환이 구체적이다. Hadoop과 별도 웨어하우스로 나뉘어 있던 구조에서 lakehouse로 옮긴 뒤 일상적인 데이터 엔지니어링 작업 수가 절반으로 줄었고, 중복 데이터셋 제거로 저장 비용이 65% 이상 감소했다고 보고됐다(MinIO). Hudi의 copy-on-write·merge-on-read가 레코드 단위 update/delete를 가능하게 한 덕분이라는 설명이다. 이 수치는 해당 인프라 규모와 전환 조건에 묶인 사례 결과이며, 일반 벤치마크로 확대 해석할 근거는 아니다.

상류 차단과 하류 제거, 무엇을 얻고 무엇을 잃나?

상류에서 중복을 막으면 하류 저장소는 항상 깨끗한 상태를 유지하지만, 그 대가로 상태 저장·TTL 관리라는 운영 부담이 스트리밍 레이어에 고정으로 붙는다. 반대로 하류에서 MERGE로 사후 제거하면 상류 로직은 단순해지지만, MERGE 자체가 배치 단위로 도는 무거운 연산이라 재처리 비용이 데이터 양에 비례해 커진다. 스트림 데이터를 임시 저장해 완충하는 버퍼 레이어 설계는 이 둘의 중간 지점으로, 중복 추적과 재처리 완충을 동시에 노리는 방식이다. 결국 선택은 "상태 관리 비용을 스트리밍 레이어에 둘 것인가, MERGE 비용을 배치 레이어에 둘 것인가"의 문제로 좁혀진다.

이 설계는 언제 쓰고 언제 피해야 하나?

소스 시스템에 안정적인 기본키가 있고 재시도 빈도가 낮다면, 상류 차단에 드는 상태 관리 비용이 이득 대비 과하다 — 이 경우 하류 MERGE 배치만으로 충분하다. 반대로 소스가 지연 도착·중복 전송이 잦은 이벤트 스트림이라면, TTL 기반 상태 제거를 상류에 두지 않을 경우 하류 MERGE 비용이 데이터 양과 함께 계속 불어난다. 2026년 기준으로 배치·스트리밍 혼합 파이프라인이 일반화되면서, 이 판단을 소스별로 나눠 적용하는 쪽이 파이프라인 전체를 한 정책으로 묶는 쪽보다 재처리 비용 관리에 유리하다.

핵심 정리

  • 멱등 싱크가 없으면 단일 배치 중복·재시도 중복·기본키 부재 세 지점에서 중복이 발생한다.
  • Delta Lake·Iceberg는 MERGE를 명시해야 중복이 제거되며, 저장 후 자동 정합성은 보장되지 않는다.
  • 스트리밍 중복 제거는 sql.state-ttl 값이 추적 정확도와 상태 저장 비용을 동시에 결정한다.
  • 처리량 비교는 sync 시작·종료 시각 기준(1TB / 소요시간)으로 재는 것이 실무 기준선이 된다.
  • 상류 차단은 상태 관리 비용을, 하류 MERGE는 배치 재처리 비용을 각각 대가로 요구한다 — 소스 특성에 따라 나눠 선택하는 편이 낫다.

더 알아보기

데이터 파이프라인 아키텍처: 배치·스트리밍·신선도의 설계 축 — 이 주제의 종합 가이드