Uber IngestionNext의 스트리밍 데이터 레이크 수집 설계

Kafka·Flink·Apache Hudi로 구성한 Uber IngestionNext의 스트리밍 수집, 정확히 한 번 처리, CoW·MoR 트랜잭션 설계를 정리한다.

2026-08-15 · 최초 발행 2026-04-26

배치 수집의 지연을 스트리밍 파이프라인으로 바꾸다

Uber는 페타바이트 규모 데이터 레이크의 수집 방식을 Spark 배치 중심에서 스트리밍 우선 구조로 전환하며 IngestionNext를 공개했다. Kafka, Flink, Apache Hudi를 조합해 수집 지연을 수 시간에서 수 분으로 줄이고 컴퓨팅 비용을 25% 절감했다. 이 플랫폼은 매월 1억 3700만 명의 탑승자 데이터를 처리한다.

IngestionNext는 2025년 말 공개된 스트리밍 우선 데이터 레이크 수집 플랫폼이다. 고정된 실행 주기에 맞춰 데이터를 모으던 기존 배치 수집은 수 시간의 지연을 만들었다. 스케줄 기반 수집에서는 잡이 1시간에서 수 시간 단위로 실행되고, 피크 구간에는 한꺼번에 모인 데이터를 처리하면서 클러스터 리소스가 급격히 튄다. 스키마나 파티션이 바뀔 때 재처리 비용도 커진다.

IngestionNext는 이벤트가 유입되는 흐름을 따라 데이터를 변환하고 데이터 레이크에 기록하도록 설계됐다. 서비스, 모바일, 디바이스에서 발생한 이벤트는 Kafka 토픽으로 모이고, Flink 잡이 이를 연속적으로 소비해 변환·정제한다. 결과는 Hudi 테이블에 트랜잭셔널 커밋으로 기록되며, 적재된 테이블은 분석 엔진, ML 피처 스토어, 실험 플랫폼이 함께 사용한다.

Kafka는 Uber 내부 수천 개 서비스에서 발생하는 이벤트를 지속적으로 수신하는 이벤트 버스다. Flink는 이 이벤트를 소비하면서 실시간 변환을 수행하는 연속 처리 계층이며, Hudi는 트랜잭션 보장과 함께 최종 데이터를 기록하는 레이크하우스 테이블 포맷이자 싱크 역할을 맡는다.

제어 평면이 수집 잡의 생애주기를 맡는 방식

이벤트 스트림연속 소비트랜잭션 쓰기CoW/MoR 생성/배포헬스 모니터링장애 복구Uber 서비스들(수천 개)Apache Kafka(이벤트 수신)Apache Flink(스트림 처리)Apache Hudi(데이터 레이크)Parquet 파일(오브젝트 스토리지)Control PlaneDataCentral(옵저버빌리티)

수천 개 Flink 잡을 각각 운영하는 대신, Control Plane이 잡 생성, 기본 설정 적용, 배포, 재시작 로직, 설정 변경 전파, 헬스 검증, 장애 발생 시 자동 롤백을 한곳에서 처리한다. 정지와 삭제를 포함한 잡 생애주기를 통합 관리해 수천 개 데이터셋을 일관되게 운영한다.

지역 장애에는 페일오버 전략을 적용한다. 설계의 초점은 데이터 손실 방지와 결정론적 복구에 있으며, 어느 지점에서 재개해야 하는지를 일관되게 판단할 수 있어야 한다. 마지막 커밋에 기록된 체크포인트 ID를 읽어 동일한 지점에서 처리를 재개하고, 상황에 따라 보조 리전에서 재시작하거나 스트리밍 잡을 실행할 수 없는 구간에는 일시적으로 배치 폴백 모드로 전환한다. 이후 해당 체크포인트부터 처리를 이어가므로 장애 구간을 흡수하면서 무손실 연속성을 보장한다.

필요한 데이터셋에만 정확히 한 번 처리를 적용한다

정확히 한 번 처리(exactly-once)는 스트리밍 수집에서 구현 난도가 높은 요구사항이다. Uber는 대부분의 파이프라인에 최소 한 번(at-least-once) 시맨틱을 적용하고, 기본키 기반 중복 제거가 필요한 핵심 데이터셋에만 정확히 한 번 처리를 구현했다.

핵심 메커니즘은 Flink 체크포인트 ID를 Hudi 커밋 메타데이터에 삽입하는 방식이다. 데이터 레이크에 반영된 Flink 체크포인트를 추적할 수 있으므로, 재시작이나 롤백이 발생해도 복구 위치를 결정론적으로 찾을 수 있다. 롤백이나 페일오버가 발생해도 어떤 체크포인트가 어떤 커밋에 대응하는지 추측할 필요가 없고, 장애 시 데이터 중복과 손실을 제거하는 설계다. 트랜잭션 커밋과 롤백은 원자성을 보장하고, 타임 트래블로 일관된 과거 상태를 조회할 수 있다.

Flink 체크포인트와 Hudi 커밋을 동기화하는 일도 중요하다. 두 상태를 조율해야 재시작 과정의 중복 쓰기를 막을 수 있다.

읽기와 쓰기 특성에 따라 CoW와 MoR을 고른다

트레이드오프트레이드오프Hudi 스토리지 타입Copy-on-Write(CoW)Merge-on-Read(MoR)업데이트 전체 파일 재작성(Parquet)읽기 최적화(단순 쿼리)적합: 읽기 중심 워크로드변경 빈도 낮음업데이트를 델타 로그에 추가(Avro)비동기 컴팩션(Parquet 생성)적합: 쓰기 중심 워크로드변경 빈도 높음높은 쓰기 지연낮은 읽기 지연낮은 쓰기 지연병합 필요한 읽기

Copy-on-Write(CoW)는 기본 스토리지 타입으로, 데이터를 Parquet 컬럼 포맷에 저장한다. 업데이트가 들어오면 파일 전체를 새 버전으로 다시 쓴다. 별도 컴팩션 서비스 없이 운영 모델이 단순하므로, 읽기가 많고 변경이 드문 워크로드에 맞는다. 대신 쓰기 지연은 상대적으로 높다.

Merge-on-Read(MoR)는 Parquet 컬럼 파일과 Avro 행 기반 파일을 함께 사용한다. 업데이트는 Avro 델타 로그에 추가되고, 비동기 컴팩션이 새 Parquet 버전을 만든다. 쓰기 성능은 빠르지만 읽을 때 컬럼 파일과 델타 파일을 병합해야 하므로 복잡성이 커진다. 변경이 잦거나 쓰기 중심인 워크로드에 적합하다.

Hudi의 쿼리 뷰는 이 선택지를 보완한다. Read-Optimized View는 최신 컴팩션 데이터를 제공하고, Real-Time View는 델타를 병합한 최신 MoR 데이터를 제공한다. Incremental View는 커밋 사이의 변경 스트림을 ETL 워크플로우에 전달한다. 증분 리더는 다운스트림의 배치 소비자와 스트리밍 소비자를 모두 지원하며, 업데이트와 삭제를 다뤄야 하는 CDC에도 lakehouse 패턴으로 대응할 수 있다.

오브젝트 스토리지에서 ACID 상태를 유지하는 방법

Hudi는 전통적인 데이터베이스의 트랜잭션 패턴을 데이터 레이크에 적용한다.

원자성(Atomicity)은 트랜잭션 전체 완료 또는 전체 롤백을 보장한다. 부분 업데이트가 읽기 측에 노출되지 않으며, 장애 뒤에도 일관된 상태로 복구된다.

일관성(Consistency)은 커밋 시점에 일관된 스냅샷을 만든다. 동시 쓰기가 서로 간섭하지 않고 데이터 무결성을 유지하도록 한다.

격리성(Isolation)은 스냅샷 격리 모델에 기반한다. 읽기와 쓰기가 서로를 블로킹하지 않고, 읽기 측은 일관된 시점의 뷰를 관찰한다.

지속성(Durability)은 커밋된 데이터가 장애 뒤에도 유지되는 성질이다. 클라우드 오브젝트 스토리지의 내구성과 커밋 메타데이터 앵커링이 함께 이를 뒷받침한다.

이 구조는 데이터 변환 도중 장애가 발생했을 때의 롤백, 특정 커밋 시점으로의 타임 트래블 쿼리, 기본키 기반 업서트와 중복 제거, 원자적 변환에 의한 데이터 품질 보장, 안전한 스키마 진화를 가능하게 한다.

데이터 유입량에 맞춰 자원을 쓰는 수집 구조

항목 배치 수집 IngestionNext (스트리밍)
데이터 지연 3~12시간 5~60분
리소스 모델 고정 스케줄 + 고정 할당 데이터 볼륨에 따른 동적 확장
유휴 기간 예약 리소스 낭비 최소 리소스 사용
장애 복구 전체 배치 재실행 체크포인트에서 재개
최대 부하 처리 피크 대비 과다 프로비저닝 자동 스케일아웃

스트리밍 잡은 실제 데이터 유입량을 따라 확장·축소된다. 배치 창에서 한꺼번에 발생하던 리소스 스파이크와 주기적 컨테이너 기동, 재시작의 오버헤드는 장기 실행 잡으로 줄어든다. 저트래픽 시간대의 리소스 낭비를 줄이고, 피크 시간에는 자동 스케일아웃으로 SLA를 유지한다. 데이터 신선도가 수 시간에서 수 분으로 바뀌면서 분석 워크플로우의 의사결정 속도도 개선됐다.

운영 중에는 Flink가 많은 소파일(small file)을 만들 수 있다. 배칭과 컴팩션으로 이를 최적화했고, 파티션 스큐(skew)는 재파티셔닝 전략으로 핫스팟을 피했다.

25%의 컴퓨팅 비용 절감은 알고리즘 최적화보다 아키텍처 변화의 결과다. 데이터 볼륨과 무관하게 실행되던 고정 배치 잡을 제거해 유휴 실행 오버헤드와 피크 대비 과다 예약 리소스를 줄였다. 실제 이벤트 처리 속도에 맞춰 스트리밍 잡이 확장·축소되고, 사용량 기반 과금(pay-for-what-you-use) 모델이 예약 배치 슬롯을 대체한다.

단일 Control Plane은 수천 개 잡의 생애주기와 헬스 상태를 통합 관리한다. 자동화와 표준화된 패턴으로 수동 개입 및 잡당 비용을 낮추는 구조다.

Uber의 데이터 레이크는 100+ 페타바이트 규모이며, 초당 수십만 건의 이벤트를 수천 개 테이블에 처리한다. 지역 장애에는 페일오버를 적용해 SLA를 유지하고, 폴백 전략으로 연쇄 장애를 방지한다.

운영에서 계속 관리해야 할 경계 조건

최소 한 번 처리와 정확히 한 번 처리의 선택은 데이터셋별로 달라진다. Uber는 기본키 중복 제거로 충분한 경우와 그렇지 않은 경우를 구분한다. 정확히 한 번 처리는 비용과 복잡성이 더 높으므로 실제로 필요한 지점에만 적용한다.

MoR 테이블은 시간이 지날수록 델타 로그가 누적돼 읽기 성능이 저하될 수 있다. 비동기 컴팩션의 스케줄과 트리거 조건은 따라서 운영의 핵심 설정이 된다.

Kafka 토픽 스키마가 바뀌면 Hudi 테이블 스키마도 안전하게 진화해야 한다. 이를 위해 스키마 변경을 다루는 자동화된 파이프라인이 필요하다. 또한 Hudi 메타데이터에 기록된 체크포인트 ID는 재시작 위치를 결정론적으로 알려 주며, 수천 개 잡을 수동 개입 없이 복구하는 기반이 된다. 체크포인트 간격과 보존 정책은 복구 지점과 스토리지 비용을 좌우하고, 파티션과 버킷팅은 스트리밍 쓰기 패턴을 기준으로 잡아야 한다.

Sources

데이터 레이크Apache HudiApache FlinkApache Kafka스트리밍 수집