Ⅰ. Apache Hudi 기술이란?
전통적인 데이터 레이크(HDFS, S3 등 객체 스토리지)는 Parquet, ORC와 같은 컬럼형 파일을 단순히 쌓아두는 구조로 설계되었습니다.
이러한 구조는 대규모 배치 분석에는 강하지만, 다음과 같은 명확한 한계를 가지고 있습니다.
ⅰ. Update / Delete 의 어려움 → 한 건의 행을 수정하려면 파일 전체를 다시 써야 함 (Immutable File System)
ⅱ. 실시간성 부재 → 변경 데이터(CDC)를 반영하려면 매번 전체 테이블을 재작성해야 함
ⅲ. 트랜잭션 부재 → 동시에 쓰기/읽기가 일어나면 데이터 정합성을 보장할 수 없음
ⅳ. 작은 파일 문제(Small File Problem) → 스트리밍 적재 시 수많은 작은 파일이 생성되어 쿼리 성능 저하
ⅴ. 증분 처리 불가 → "어제 이후 변경된 데이터만" 가져오려면 별도의 타임스탬프 컬럼과 복잡한 쿼리가 필요
Apache Hudi(Hadoop Upserts Deletes and Incrementals)는 Uber에서 2016년 개발하여 2019년 Apache 최상위 프로젝트로 승격된 오픈 데이터 레이크하우스 플랫폼입니다.
S3, HDFS, GCS 등 기존 객체 스토리지 위에서 ACID 트랜잭션, Upsert/Delete, 증분 쿼리, 시간 여행(Time Travel), 스키마 진화를 지원하여, 데이터 레이크를 데이터 웨어하우스처럼 다룰 수 있게 해주는 기술입니다.
Ⅱ. Apache Hudi 기술 특징
| 구분 | 설명 |
| ACID 트랜잭션 | MVCC(Multi-Version Concurrency Control) 기반으로 동시 쓰기/읽기 환경에서도 데이터 일관성을 보장합니다. |
| Upsert / Delete | Primary Key 기준으로 행 단위 업데이트와 삭제가 가능합니다. CDC(Change Data Capture) 적재에 최적화되어 있습니다. |
| 증분 쿼리(Incremental Query) | "특정 커밋 이후 변경된 데이터만" 가져올 수 있어, ETL 파이프라인의 비용과 지연시간을 획기적으로 줄입니다. |
| Time Travel | 과거 시점의 테이블 상태를 그대로 조회 가능. 감사(Audit), 디버깅, 머신러닝 재현성 확보에 활용됩니다. |
| 스키마 진화 | 컬럼 추가/이름 변경/타입 변경을 기존 데이터 재작성 없이 지원합니다. |
| 자동 파일 관리 | Compaction, Clustering, Cleaning을 통해 작은 파일 문제를 자동으로 해결하여 쿼리 성능을 유지합니다. |
| 다중 엔진 호환 | Spark, Flink, Presto, Trino, Hive, Athena, Redshift Spectrum 등 거의 모든 분석 엔진과 연동됩니다. |
Ⅲ. Apache Hudi 기술 동작방식
Hudi는 객체 스토리지 위에 "테이블"이라는 논리적 단위를 만들고, 그 안에 데이터 파일과 메타데이터(Timeline)를 함께 관리합니다.
ⅰ. 핵심 구성 요소
| 구성 요소 | 역할 |
| Timeline | 테이블에 일어난 모든 작업(Commit, Clean, Compaction, Rollback 등)을 시간 순으로 기록한 메타데이터 로그. .hoodie/ 디렉터리에 저장됩니다. |
| File Group / File Slice | 데이터를 저장하는 물리 단위. 하나의 파티션은 여러 File Group으로 나뉘고, 각 File Group은 시간 순으로 여러 File Slice를 가집니다. |
| Index | 레코드 키 → File Group 매핑을 빠르게 찾기 위한 인덱스. Bloom, Simple, HBase, Bucket, Record-Level Index를 지원합니다. |
| Base File | 컬럼형 형식(Parquet/ORC)으로 저장된 본 데이터 파일. |
| Log File | 행 단위 변경분(Delta)을 Avro 형식으로 빠르게 추가 기록하는 파일. MoR 테이블에서만 사용됩니다. |
| Table Service | Compaction, Clustering, Cleaning, Archival 등 백그라운드 자동 최적화 작업. |
ⅱ. 데이터 흐름

1) Writer가 새로운 레코드를 보냄(Insert/Update/Delete)
2) Index를 통해 해당 레코드 키가 속한 File Group을 식별
3) 테이블 타입(CoW/MoR)에 따라 Base File을 다시 쓰거나 Log File에 추가
4) Timeline에 새로운 Commit 인스턴트(instant)를 기록
5) Reader는 Timeline을 보고 가장 최신 일관된 스냅샷을 조회
Ⅳ. Apache Hudi 기술 구성 및 흐름도
Hudi의 가장 중요한 설계 결정은 테이블 타입(Table Type)입니다. 동일한 데이터라도 어떤 타입을 선택하느냐에 따라 쓰기/읽기 트레이드오프가 완전히 달라집니다.
| 구분 | Copy on Write (CoW) | Merge on Read (MoR) |
| 저장 방식 | 변경 발생 시 Parquet 파일을 전체 재작성 | 변경분은 Avro Log File에 추가, Base File은 그대로 유지 |
| 쓰기 비용 | 높음 (파일 전체 재작성) | 낮음 (append-only) |
| 읽기 비용 | 낮음 (Parquet 직접 스캔) | 높음 (Base + Log Merge 필요) |
| 적재 지연 | 분 단위 | 초 단위 (실시간) |
| 적합 워크로드 | 읽기 빈도 > 쓰기 빈도 (BI, 대시보드) | 쓰기 빈도 > 읽기 빈도 (CDC, IoT 스트리밍) |
[ 단계별 처리 흐름 (MoR 기준) ]
| 단계 | 처리 내용 | 세부 설명 |
| 1) Ingest | Kafka/CDC 소스에서 변경 이벤트 수신 | DeltaStreamer 또는 Spark/Flink Structured Streaming Job이 마이크로 배치로 데이터를 끌어옵니다. |
| 2) Tag | Index 조회로 레코드 위치 식별 | 레코드 키가 기존 어떤 File Group에 있는지 인덱스로 찾아 Insert/Update를 분리합니다. |
| 3) Write | Log File에 변경분 append | Base Parquet은 건드리지 않고, 행 기반 Avro Log에 변경분을 빠르게 기록합니다. |
| 4) Commit | Timeline에 deltacommit 기록 | Atomic하게 인스턴트(instant)를 추가하여, 이 시점부터 Reader가 새 데이터를 볼 수 있습니다. |
| 5) Compaction | Log + Base를 Parquet으로 병합 | 백그라운드에서 주기적으로 수행. 읽기 성능이 떨어지기 전에 자동 최적화합니다. |
| 6) Clean | 오래된 파일 정리 | 설정된 보존 정책(commits/hours)을 넘긴 구버전 파일을 삭제하여 스토리지 비용을 관리합니다. |
| 7) Read | Snapshot / Incremental / Read-Optimized | 쿼리 종류에 따라 (1)최신 병합 결과, (2)특정 커밋 이후 변경분, (3)Base Parquet만 빠르게 조회 중 선택합니다. |
Ⅴ. Apache Hudi 기술 설치 방법
Hudi는 자체 데몬을 띄우는 방식이 아니라, Spark / Flink 등 컴퓨트 엔진에 라이브러리(JAR)로 탑재되는 형태입니다. 별도의 Hudi 서버를 설치할 필요는 없습니다.
ⅰ. Spark 환경에서 Hudi 사용 (가장 일반적)
# Spark 3.5 + Hudi 0.15 기준 (Scala 2.12)
spark-shell \
--packages org.apache.hudi:hudi-spark3.5-bundle_2.12:0.15.0 \
--conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer' \
--conf 'spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog' \
--conf 'spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension'
ⅱ. Flink 환경에서 Hudi 사용
# Flink 1.18 lib 디렉터리에 번들 JAR 배치
wget https://repo1.maven.org/maven2/org/apache/hudi/hudi-flink1.18-bundle/0.15.0/hudi-flink1.18-bundle-0.15.0.jar \
-O $FLINK_HOME/lib/hudi-flink1.18-bundle-0.15.0.jar
ⅲ. Python(PySpark) 환경
pip install pyspark==3.5.0
# 실행 시 패키지를 함께 지정
pyspark --packages org.apache.hudi:hudi-spark3.5-bundle_2.12:0.15.0
ⅳ. 클라우드 매니지드 옵션
- AWS EMR / Glue : Hudi가 기본 탑재되어 있어 별도 설치 불필요
- Databricks : 자체 OSS Spark 런타임에서 Hudi 사용 가능
- GCP Dataproc : 초기화 액션으로 Hudi 패키지 자동 설치 가능
Ⅵ. Apache Hudi 기술 사용 방법
ⅰ. PySpark로 Hudi 테이블 생성 & Upsert
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("hudi-demo").getOrCreate()
hudi_options = {
'hoodie.table.name': 'orders',
'hoodie.datasource.write.recordkey.field': 'order_id',
'hoodie.datasource.write.partitionpath.field': 'order_date',
'hoodie.datasource.write.precombine.field': 'updated_at',
'hoodie.datasource.write.operation': 'upsert',
'hoodie.datasource.write.table.type': 'MERGE_ON_READ',
'hoodie.upsert.shuffle.parallelism': 4,
'hoodie.insert.shuffle.parallelism': 4,
}
# 최초 적재
df.write.format("hudi") \
.options(**hudi_options) \
.mode("overwrite") \
.save("s3://my-lake/orders/")
# 변경분 Upsert
delta_df.write.format("hudi") \
.options(**hudi_options) \
.mode("append") \
.save("s3://my-lake/orders/")
ⅱ. Spark SQL로 사용 (DDL/DML)
CREATE TABLE orders (
order_id STRING,
customer STRING,
amount DECIMAL(18,2),
updated_at TIMESTAMP,
order_date STRING
) USING hudi
TBLPROPERTIES (
type = 'mor',
primaryKey = 'order_id',
preCombineField = 'updated_at'
)
PARTITIONED BY (order_date);
MERGE INTO orders t
USING staging_orders s
ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
ⅲ. 증분 쿼리 / 시간 여행
# 특정 커밋 이후 변경된 데이터만 조회 (Incremental)
spark.read.format("hudi") \
.option("hoodie.datasource.query.type", "incremental") \
.option("hoodie.datasource.read.begin.instanttime", "20260420090000") \
.load("s3://my-lake/orders/").show()
# 특정 시점의 스냅샷 조회 (Time Travel)
SELECT * FROM orders TIMESTAMP AS OF '2026-04-20 09:00:00';
ⅳ. 운영 시 고려사항
| 항목 | 권장 사항 |
| Record Key 설계 | 카디널리티가 높고 불변인 컬럼을 선택해야 합니다. 비즈니스 키와 결합하지 마세요. |
| 파티션 키 설계 | 날짜 기반(연/월/일)이 일반적이나, 너무 잘게 나누면 작은 파일이 폭증합니다. |
| Index 선택 | 대용량 + 랜덤 키 → Bucket Index, 범위 검색 → Bloom, 0.14+ → Record-Level Index 권장 |
| Compaction 전략 | MoR은 inline 또는 async 중 선택. 실시간성이 중요하면 async + 별도 컴팩션 잡으로 분리하세요. |
| Cleaning 정책 | Time Travel 요구 기간만큼만 보존하여 스토리지 비용을 관리합니다 (기본 10 commits 보존). |
| Hive Sync | Glue/Hive Metastore와 자동 동기화하여 Athena, Trino, Presto에서 즉시 쿼리 가능하도록 설정합니다. |
| 모니터링 | Hudi Metrics를 Prometheus/Grafana로 노출하고, Timeline 누적 크기와 Compaction 지연을 핵심 지표로 둡니다. |
Ⅶ. Apache Hudi 자주 쓰는 명령어 / 사례
Hudi는 운영 편의를 위해 hudi-cli라는 인터랙티브 셸과 Spark 기반 유틸리티 잡(HoodieDeltaStreamer)을 제공합니다.
ⅰ. hudi-cli 자주 쓰는 명령
| 명령어 | 용도 |
| connect --path s3://my-lake/orders/ | Hudi 테이블에 접속 |
| commits show | Timeline의 모든 커밋 이력 조회 |
| stats filesizes | 파일 크기 분포 확인 (작은 파일 문제 진단) |
| compactions show all | 예약/완료된 Compaction 작업 확인 |
| compaction schedule | 새로운 Compaction 작업 예약 |
| compaction run --compactionInstant {ts} | 예약된 Compaction 실행 |
| cleans run | 오래된 파일 정리(Clean) 수동 실행 |
| commit rollback --commit {ts} | 잘못된 커밋을 안전하게 롤백 |
| savepoint create --commit {ts} | 중요 시점을 보존하여 Cleaner가 지우지 못하게 보호 |
ⅱ. HoodieDeltaStreamer 활용 사례 (Kafka → S3 CDC 적재)
spark-submit \
--class org.apache.hudi.utilities.streamer.HoodieStreamer \
--packages org.apache.hudi:hudi-utilities-bundle_2.12:0.15.0 \
--master yarn --deploy-mode cluster \
/path/to/hudi-utilities-bundle.jar \
--table-type MERGE_ON_READ \
--source-class org.apache.hudi.utilities.sources.DebeziumSource \
--target-base-path s3://my-lake/orders/ \
--target-table orders \
--op UPSERT \
--continuous \
--min-sync-interval-seconds 30
ⅲ. 실제 활용 사례
- Uber : 수백 PB의 데이터 레이크를 Hudi로 운영, 30분 → 분 단위로 데이터 신선도 향상
- Walmart : 매장 재고/주문 CDC를 실시간으로 분석 레이크에 반영
- Robinhood : 거래 데이터를 분 단위로 적재하여 리스크 분석에 활용
- ByteDance : 추천 모델용 Feature Store 백엔드로 사용
Ⅷ. Apache Hudi 기술 활용방안
ⅰ. 대안 기술 비교 (Lakehouse Format Trinity)
| 구분 | Apache Hudi | Apache Iceberg | Delta Lake |
| 최초 개발 | Uber (2016) | Netflix (2018) | Databricks (2019) |
| 핵심 강점 | Upsert/CDC 실시간 적재, Record-Level Index | 대규모 스키마/파티션 진화, 멀티엔진 중립성 | Spark/Databricks 생태계 통합, 단순함 |
| 테이블 타입 | CoW / MoR 선택 가능 | CoW (MoR은 v3에서 도입 중) | CoW (Deletion Vector로 보완) |
| 실시간 적재 | 최우선 설계 목표 (초~분) | 분~시간 단위 | 분 단위 |
| 증분 쿼리 | 기본 지원 (Incremental Pull) | CDF로 부분 지원 | CDF 지원 |
| 주된 사용처 | CDC, IoT, 스트리밍 적재 | 대형 분석 테이블, 멀티엔진 환경 | Databricks 중심 데이터 플랫폼 |
ⅱ. Hudi가 적합한 시나리오
1) 운영 DB → 분석 레이크로의 실시간 CDC 미러링 (Debezium + Kafka + Hudi MoR)
2) GDPR/CCPA 대응 — 특정 사용자 데이터의 행 단위 삭제(Right to be Forgotten)
3) IoT/이벤트 데이터의 Late Arriving Data 처리 (지연 도착 이벤트 정합성 보정)
4) 머신러닝용 Feature Store의 백엔드 (시간 여행으로 학습/서빙 시점 일치)
5) Slowly Changing Dimension(SCD Type 2) 패턴 구현
ⅲ. 언제 Hudi를 쓰면 안 되는가
| 상황 | 이유 / 더 나은 대안 |
| 단순 Append-only 로그 적재 | Upsert 인덱스 오버헤드만 발생. 그냥 Parquet + Glue Crawler로 충분합니다. |
| 초저지연(밀리초) OLTP | Hudi는 분석용 Lakehouse입니다. PostgreSQL, MySQL 등 OLTP DB가 적합합니다. |
| 초고속 OLAP 대시보드 | 읽기 응답 50ms 이하가 필요하다면 ClickHouse, Apache Doris, StarRocks가 더 나은 선택입니다. |
| 파일 수가 적고 변경이 거의 없는 정적 데이터셋 | 메타데이터/Timeline 관리 비용만 늘어납니다. 단순 Parquet 테이블이 적합합니다. |
| 멀티엔진 표준화가 최우선이고 실시간성은 부차적 | Apache Iceberg가 더 넓은 엔진 호환성과 단순한 메타데이터 모델을 제공합니다. |
| Databricks를 전면적으로 사용 | Delta Lake가 Databricks 런타임 최적화 측면에서 가장 자연스럽습니다. |
[ 핵심 요약 ]
Apache Hudi는 "데이터 레이크에서도 트랜잭션과 실시간 업데이트가 필요하다"는 문제를 정면으로 해결한 기술입니다.
특히 Upsert/Delete가 빈번한 CDC 워크로드에서 Iceberg, Delta Lake보다 명확한 우위를 가지며, CoW와 MoR이라는 두 개의 테이블 타입을 통해 읽기/쓰기 성능 트레이드오프를 워크로드에 맞게 조절할 수 있는 유연성이 가장 큰 강점입니다.
다만, 단순 분석용 정적 테이블이나 초저지연 OLAP 환경에서는 오히려 오버스펙이 될 수 있으므로, "이 데이터는 정말 행 단위로 변경되는가?"라는 질문에 Yes일 때 도입하는 것이 가장 합리적인 선택입니다.
'빅데이터(Big Data)' 카테고리의 다른 글
| 데이터 레이크의 표준 페더레이션 SQL 쿼리 엔진, Trino 분석 (0) | 2026.05.12 |
|---|---|
| 모던 데이터 스택의 공용어, Apache Arrow에 대해 분석 (0) | 2026.05.11 |
| 진정한 실시간 스트림 처리의 표준, Apache Flink에 대해 알아보겠습니다. (1) | 2026.05.06 |
| 실시간 이벤트 스트리밍의 심장, Apache Kafka에 대해 알아보겠습니다. (0) | 2026.05.02 |
| 빅데이터 분석의 새로운 표준, 'DuckDB'에 대해 알아보겠습니다. (0) | 2026.05.01 |