LLM WikiAccess-protected knowledge portal
← 스터디 홈
7편 · 약 26분

Query engine 연동: Spark, Trino, Flink, ClickHouse 외부 테이블

쿼리 엔진은 테이블 포맷과 직접 통신하지 않는다

Lakehouse 아키텍처에서 Spark, Trino, Flink, ClickHouse는 저마다 다른 강점을 가진 쿼리 엔진이다. Spark는 대규모 배치·ML 파이프라인에, Trino는 대화형 SQL 분석에, Flink는 스트리밍 처리에, ClickHouse는 OLAP 집계에 적합하다. 이 네 엔진이 같은 Iceberg, Delta Lake, Hudi 테이블을 동시에 읽고 쓰는 환경이 점점 일반화되고 있다.

하지만 "지원한다"와 "안전하다"는 다르다. 각 엔진이 테이블 포맷에 연결하는 방식, 카탈로그 선택, 쓰기 동시성 보장이 다르기 때문에 운영자는 조합별로 어떤 제약과 주의사항이 있는지 정확히 파악해야 한다.

이 장에서는 각 엔진의 연동 방식을 실무 관점에서 정리하고, 다중 엔진 환경에서 특히 주의해야 할 카탈로그 선택과 쓰기 일관성 문제를 다룬다.

Spark
배치·ML
Trino
대화형 SQL
Flink
스트리밍
ClickHouse
OLAP
Catalog Layer
Hive Metastore / REST Catalog / AWS Glue / Nessie
Apache Iceberg
snapshot + manifest
Delta Lake
transaction log
Apache Hudi
timeline
Object Storage (S3 / GCS / ADLS)
Parquet / ORC data files
다중 엔진 Lakehouse 아키텍처

1. Spark: 테이블 포맷 연동의 기준점

Spark는 Iceberg, Delta Lake, Hudi 모두에서 가장 성숙한 연동을 제공한다. Delta Lake는 Databricks에서 시작했고, Iceberg와 Hudi 역시 Spark를 1순위 런타임으로 설계했다.

Iceberg + Spark

Iceberg는 두 가지 카탈로그 통합 경로를 제공한다.

첫 번째는 SparkSessionCatalogspark_catalog로 설정해 기존 Hive Metastore 기반 테이블을 Iceberg와 함께 쓰는 방식이다.

spark.sql.catalog.spark_catalog = org.apache.iceberg.spark.SparkSessionCatalog
spark.sql.catalog.spark_catalog.type = hive

두 번째는 REST Catalog를 직접 연결하는 방식으로, 2025년 기준 신규 구축에서는 이 경로가 권장된다.

spark.sql.catalog.my_cat = org.apache.iceberg.spark.SparkCatalog
spark.sql.catalog.my_cat.type = rest
spark.sql.catalog.my_cat.uri = http://catalog-server:8080

Iceberg는 field ID 기반으로 컬럼을 추적하므로, Spark가 Parquet 파일을 물리적 위치가 아닌 논리적 ID로 매핑한다. 이 덕분에 schema evolution과 partition evolution이 Spark 쓰기 중에도 안전하게 동작한다.

운영 주의점이 두 가지 있다.

  • Iceberg JAR 버전과 Spark 버전을 반드시 맞춰야 한다. 같은 클러스터에서 다른 버전 조합을 섞으면 silent failure가 발생할 수 있다.
  • Iceberg 테이블을 Parquet 경로로 직접 읽으면 field ID 기반 매핑을 잃는다. 반드시 Iceberg catalog를 통해 읽어야 schema evolution 안전장치가 작동한다.

Delta Lake + Spark

Delta Lake와 Spark의 연동은 가장 긴밀하다. Delta Lake 4.1.0(2026년 3월)부터 Maven artifact가 Spark 버전 suffix를 포함한다(delta-spark_4.1_2.13). Java 17이 필수이며 Spark 3.5 지원은 중단됐다.

Spark SQL 확장을 등록하면 DESCRIBE HISTORY, RESTORE TABLE, OPTIMIZE, VACUUM 같은 명령이 활성화된다.

spark.sql.extensions = io.delta.sql.DeltaSparkSessionExtension
spark.sql.catalog.spark_catalog = org.apache.spark.sql.delta.catalog.DeltaCatalog

한 세션에서 Delta와 Iceberg를 동시에 쓴다면 두 확장을 쉼표로 연결할 수 있다.

spark.sql.extensions = io.delta.sql.DeltaSparkSessionExtension,org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions

Delta Lake 4.0부터 다중 스레드 OPTIMIZE로 실행 시간이 최대 5배 빨라졌고, VACUUM에서 인벤토리 테이블을 지정해 대형 테이블의 전체 디렉터리 스캔을 우회할 수 있다.

Hudi + Spark

Hudi는 Spark와 연동할 때 두 가지 API 경로가 있다: RDD 기반 HoodieWriteClient와 DataFrame/SQL API다.

# DataFrame API - Spark SQL 설정이 적용됨
df.write.format("hudi")
  .option("hoodie.table.name", "my_table")
  .option("hoodie.datasource.write.operation", "upsert")
  .save("/path/to/table")

중요한 운영 함정은 RDD API를 쓰면 Spark SQL 설정이 무시된다는 점이다. DataFrame API에서만 효과가 있는 설정을 RDD 경로에서 기대하면 예상과 다른 동작이 발생한다.

Hudi 1.0(2025년 1월)부터 Non-Blocking Concurrency Control(NBCC)이 추가돼 서로 다른 레코드 집합을 쓰는 복수의 writer가 명시적 lock 없이 동작할 수 있다.


2. Trino: 대화형 SQL의 멀티 포맷 지원

Trino는 2025년 기준 450개 이상의 connector를 보유하며, Iceberg, Delta Lake, Hudi 각각에 전용 connector를 제공한다. Hive connector로 우회하는 방식보다 전용 connector가 성능과 기능 면에서 모두 낫다.

Iceberg connector

Trino의 Iceberg connector는 가장 성숙하다. REST Catalog 연결 예시:

connector.name=iceberg
iceberg.catalog.type=rest
iceberg.rest-catalog.uri=http://catalog-server:8181

Iceberg connector는 hidden partitioning, time travel query, row-level delete, schema evolution을 지원한다. 단, REST Catalog 경로에서 view 생성·관리는 지원하지 않는다.

S3 Tables처럼 Iceberg REST endpoint를 직접 노출하는 서비스와도 통합할 수 있어, 별도 connector 없이 Trino가 S3 Tables의 최적화를 그대로 활용할 수 있다.

Delta Lake connector

Delta Lake connector는 사용 가능하지만 Iceberg connector보다 기능과 성숙도가 낮다. Delta Lake 테이블이 주 자산이라면 Trino가 최선의 선택인지 먼저 검토한다. Databricks SQL 또는 Spark가 Delta에 더 깊은 통합을 제공한다.

Hudi connector

Trino Hudi connector는 읽기 위주로 사용하는 것이 안정적이다. 스트리밍 write는 Flink나 Spark를 통해 하고, Trino는 분석 조회에 활용하는 패턴이 일반적이다.

통계와 쿼리 최적화

Trino의 Cost-Based Optimizer는 테이블 통계에 의존한다. 파티션 pruning, broadcast join vs hash join 선택, dynamic filtering이 통계 품질에 따라 크게 달라진다. Iceberg의 경우 manifest에 포함된 컬럼 통계를 Trino가 직접 활용하므로 통계 수집 비용이 낮다.


3. Flink: 스트리밍 write의 Exactly-Once 보장

Flink는 세 포맷 중 스트리밍 write 관점에서 Iceberg와 가장 깊은 통합을 갖는다.

Iceberg + Flink: 체크포인트 기반 커밋

Flink의 Iceberg sink는 Flink 체크포인트 프로토콜에 참여한다. 체크포인트가 완료되는 시점에 해당 인터벌에서 쓴 data file을 새 Iceberg snapshot으로 커밋한다. 체크포인트가 실패하면 uncommitted 파일은 orphan으로 남고 offset이 마지막 성공 체크포인트로 롤백된다.

Kafka Source
Flink Operator
처리·변환
Iceberg Sink
파일 버퍼링
Object Storage
data files
Checkpoint Coordinator
barrier 전파
체크포인트 완료 시
Iceberg snapshot 커밋
Reader 가시성
쿼리 가능
체크포인트 실패 → uncommitted 파일 orphan 처리 → offset 마지막 성공 체크포인트로 롤백
Flink Iceberg Sink의 Exactly-Once 흐름

운영 권장 설정:

execution.checkpointing.interval = 5min
execution.checkpointing.mode = EXACTLY_ONCE
execution.checkpointing.timeout = 10min
state.backend = rocksdb
state.backend.incremental = true

체크포인트 간격이 짧을수록 생성되는 파일 수가 늘고, 길수록 장애 복구 시 재처리 범위가 커진다. 5분이 대부분의 프로덕션 워크로드에서 균형점이다.

Dynamic Iceberg Sink

Iceberg의 Dynamic Sink(2025년 기준)는 라우팅 로직에 따라 여러 테이블에 동적으로 쓸 수 있고, Flink job 재시작 없이 schema와 partition evolution을 처리한다. 멀티 테넌트 데이터 수집 파이프라인에서 유용하다.

Hudi + Flink

Hudi도 Flink streaming write를 지원하며 MoR(Merge-on-Read) 테이블과 잘 맞는다. CDC 워크로드에서 equality delete를 쓰는 Iceberg와 함께 선택지가 된다. 다만 Hudi Flink 연동은 Iceberg 대비 커뮤니티 성숙도가 다소 낮다.

Flink write 운영 주의사항

중앙 집중형 upsert(같은 키를 많은 producer가 업데이트)는 sink에서 backpressure를 유발할 수 있다. 또한 Flink job이 savepoint 후 재시작할 때 uncommitted 파일을 자동으로 정리하지 않으므로 orphan file cleanup 절차를 운영 runbook에 포함해야 한다.


4. ClickHouse: 분석 엔진으로서의 Lakehouse 연동

ClickHouse는 Iceberg, Delta Lake 테이블을 외부 테이블로 읽는 것과 직접 쓰는 것을 점차 지원하고 있다.

Iceberg 연동 진화

ClickHouse의 Iceberg write 지원은 2025년에 급격히 발전했다.

버전추가 기능
25.7 (2025년 7월)기존 Iceberg 테이블에 INSERT INTO
25.8 (2025년 8월)CREATE TABLE, ALTER DELETE, equality delete 처리
25.9 (2025년 9월)ALTER UPDATE, 분산 쓰기 (read/write 동등성 달성)

이전까지는 read-only였지만 25.9부터 실질적인 write 엔진으로 사용할 수 있다. Iceberg v2 spec의 schema evolution, time travel, statistics 기반 pruning도 지원한다.

DataLakeCatalog 엔진

ClickHouse의 DataLakeCatalog 엔진은 AWS Glue Catalog, Databricks Unity Catalog에 연결해 Iceberg와 Delta Lake 테이블을 자동 감지하고 쿼리한다. 별도 connector 설정 없이 cross-catalog 쿼리도 가능하다.

파일 캐싱

ClickHouse Cloud 환경에서는 distributed cache가 여러 compute node 간에 Parquet 파일을 공유하며, 외부 Iceberg/Delta 테이블까지 캐싱을 확장한다. S3에서 반복적으로 읽어야 할 경우 tail latency가 수백 ms에서 microsecond 수준으로 줄어든다. 이 기능은 ClickHouse Cloud 전용이며 self-hosted 환경에서는 사용할 수 없다.

ClickHouse의 적합한 역할

ClickHouse는 Lakehouse 테이블의 주 write 엔진이라기보다 분석 가속 레이어로 쓰는 것이 현실적이다.

  • Spark나 Flink가 쓴 Iceberg/Delta 테이블을 ClickHouse가 읽어 빠른 집계 쿼리를 제공한다.
  • 대시보드, 실시간 분석, 시계열 집계에 적합하다.
  • write path는 Flink나 Spark에 맡기고 ClickHouse는 read-heavy OLAP 역할을 담당하는 패턴이 안정적이다.

5. 카탈로그 선택: 멀티 엔진 환경의 핵심

여러 엔진이 같은 테이블을 읽고 쓰려면 카탈로그가 공통 메타데이터 저장소 역할을 해야 한다. 카탈로그 선택이 잘못되면 엔진마다 서로 다른 테이블 상태를 보게 된다.

카탈로그강점약점권장 상황
Hive Metastore가장 넓은 엔진 지원, 성숙도 높음인프라 관리 부담, 현대적 기능 부재기존 Hadoop 환경
REST Catalog벤더 중립, 폭넓은 엔진 호환별도 서버 운영 필요신규 구축 권장
AWS Glue관리형, AWS 생태계 통합AWS 락인, 비용AWS 기반
Project NessieGit-like 브랜치, 다중 테이블 atomic 커밋HMS보다 낮은 채택률브랜치 기반 개발
Unity CatalogDelta에 깊은 통합, 거버넌스 강점Delta 전용, 타 포맷 제한Databricks 환경
Apache PolarisREST 표준, 동적 credential 발급상대적으로 신규멀티 엔진 Iceberg 환경

2025년 이후 신규 Iceberg 환경에서는 REST Catalog가 표준으로 자리 잡고 있다. Spark, Flink, Trino, DuckDB, Snowflake가 모두 REST Catalog를 지원하므로 엔진 교체나 추가에 유연하다.

Unity Catalog는 Delta Lake 테이블에 특화되어 있고, 다른 포맷 테이블을 직접 관리하지 않는다. Delta UniForm을 통해 Iceberg 메타데이터를 read-only로 노출할 수 있지만, Iceberg 네이티브 기능의 일부만 사용 가능하다.


6. 다중 엔진 쓰기: 일관성 보장과 실제 제약

같은 테이블에 여러 엔진이 동시에 쓸 때 일관성 보장이 어떻게 되는지 이해해야 한다.

Iceberg

Iceberg의 일관성 모델은 메타데이터 원자성에 기반한다. 새 메타데이터 파일이 테이블 상태를 원자적으로 가리키고, 두 writer가 같은 base에서 새 버전을 만들려 하면 충돌을 감지하고 retry한다. lock이 필요 없으며 멀티 엔진 환경에서 가장 유연한 설계를 갖는다.

Delta Lake

Delta Lake는 write-ahead log에 트랜잭션을 순차적으로 기록한다. 단일 writer나 제한적 동시 쓰기에 잘 맞지만, Iceberg보다 복잡한 동시 쓰기 시나리오에서는 더 많은 제약이 있다.

Hudi

Hudi는 한 시점에 writer가 1개로 제한된다는 중요한 제약이 있다. NBCC(Non-Blocking Concurrency Control)가 1.0에서 도입됐지만, 이는 서로 다른 레코드 집합에 대한 writer를 위한 것이다. 같은 테이블에 Spark와 Flink가 동시에 write하는 패턴은 신중하게 설계해야 한다.

실무 설계 원칙

멀티 엔진 환경에서 write 경로를 설계할 때는 다음 원칙이 도움이 된다.

  1. write 엔진을 가능하면 하나로 제한한다. Flink가 스트리밍으로 쓰고 Spark가 배치로 보정하는 패턴은 동시 write가 아니라 시간적 분리다.
  2. read 엔진은 여러 개를 허용한다. Trino, ClickHouse, Spark가 동시에 읽는 것은 snapshot isolation 덕에 안전하다.
  3. compaction과 cleanup은 writer와 별도 주기로 분리한다. writer와 같은 클러스터에서 compaction을 돌리면 자원 경합이 발생한다.

7. Apache XTable: 포맷 간 상호 운용

단일 포맷을 선택하기 어렵거나 점진적 마이그레이션이 필요한 상황에서 Apache XTable(구 OneTable)이 선택지가 된다.

XTable은 데이터 파일을 복사하지 않고 메타데이터만 번역해서, 하나의 물리 데이터셋을 Delta, Hudi, Iceberg로 동시에 인식하게 한다. 이미 Hudi로 운영 중인 테이블을 Trino나 ClickHouse가 Iceberg로 읽어야 하는 상황에서 유용하다. 2025년 기준 v0.3.0이며 Iceberg를 중심으로 Delta와 Hudi와의 양방향 변환을 지원한다. "포맷 선택은 영구적"이라는 과거의 제약이 완화되고 있다.


정리

  1. Spark는 세 포맷 모두에서 가장 성숙한 연동을 제공한다. 특히 Hudi에서 RDD API와 DataFrame API의 설정 적용 범위 차이를 주의해야 한다.
  2. Trino는 Iceberg connector가 가장 성숙하며 대화형 분석에 적합하다. Delta와 Hudi connector는 기능 범위를 먼저 확인해야 한다.
  3. Flink의 Iceberg sink는 체크포인트 프로토콜에 참여해 exactly-once를 보장한다. 체크포인트 간격이 파일 수와 장애 복구 범위의 균형에 영향을 준다.
  4. ClickHouse는 25.9부터 Iceberg write를 지원하지만, 현재 가장 안정적인 역할은 read-heavy OLAP 분석 레이어다.
  5. 카탈로그는 멀티 엔진 환경의 핵심이다. 신규 구축이라면 REST Catalog가 가장 넓은 엔진 호환성을 제공한다.
  6. 동시 쓰기 설계에서는 Iceberg가 가장 유연한 일관성 모델을 갖는다. write 엔진을 가능하면 하나로 제한하고, 여러 엔진을 read에 활용하는 패턴이 안전하다.

References

  • Apache Iceberg Docs, "Spark Configuration", https://iceberg.apache.org/docs/latest/spark-configuration/
  • Apache Iceberg Docs, "Flink Connector", https://iceberg.apache.org/docs/latest/flink/
  • Delta Lake Blog, "Delta Lake 4.1.0 Released", https://delta.io/blog/2026-03-01-delta-lake-4-1-0-released/
  • Trino Docs, "Iceberg Connector", https://trino.io/docs/current/connector/iceberg.html
  • Apache Polaris Docs, "Getting Started with Trino", https://polaris.apache.org/guides/trino/
  • ClickHouse Blog, "ClickHouse is data lake ready", https://clickhouse.com/blog/clickhouse-is-data-lake-ready
  • ClickHouse Blog, "ClickHouse 2025 Roundup", https://clickhouse.com/blog/clickhouse-2025-roundup
  • Apache Hudi Docs, "Flink Quick Start Guide", https://hudi.apache.org/docs/flink-quick-start-guide/
  • Jack Vanlightly, "Understanding Apache Hudi's Consistency Model", https://jack-vanlightly.com/analyses/2024/4/24/understanding-apache-hudi-consistency-model-part-1
  • Onehouse Blog, "Open Data Foundations with Apache XTable", https://www.onehouse.ai/blog/open-data-foundations-with-apache-xtable-hudi-delta-and-iceberg-interoperability
  • RisingWave Blog, "Apache Iceberg vs Delta Lake vs Hudi (2026)", https://risingwave.com/blog/apache-iceberg-vs-delta-lake-vs-hudi-2026/
  • AWS Blog, "Query Amazon S3 Tables from open source Trino using Apache Iceberg REST endpoint", https://aws.amazon.com/blogs/storage/query-amazon-s3-tables-from-open-source-trino-using-apache-iceberg-rest-endpoint/
  • LakeOps Blog, "Best Catalog for Apache Iceberg", https://lakeops.dev/blog/best-catalog-for-apache-iceberg
  • RisingWave Blog, "Iceberg Catalog Comparison", https://risingwave.com/blog/iceberg-catalog-comparison-guide/