Engineering Note

Apache Fluss란: Kafka·Flink·Iceberg 사이의 스트리밍 레이크하우스

Apache Fluss를 Kafka·Flink·Iceberg와 역할별로 비교합니다. Log Table·Primary Key Table·통합 메타데이터로 실시간 스트림과 레이크하우스를 연결하는 방식을 정리합니다.

2026년 7월 28일 · Pletor Engineering apache-flusslakehousestreamingflinkarchitecture

Apache Fluss는 Kafka, Flink, Iceberg와 접점이 많아서 처음에는 어느 하나의 대체재처럼 보일 수 있습니다. 하지만 네 제품은 데이터 경로에서 맡는 위치가 다릅니다.

이 글은 먼저 그 역할을 나란히 놓고, 그 뒤 Fluss가 왜 실시간 계층과 레이크하우스 계층을 연결하려 하는지 설명합니다. 비교의 기준은 제품의 인기나 기능 수가 아니라 데이터를 전달하는가, 계산하는가, 저장하는가, 오래 보관하는가입니다.

여러 청록색 물줄기가 짙은 남색의 하나의 넓은 물 저장소로 흘러드는 편집 일러스트
Fluss는 실시간으로 흐르는 데이터와 오래 보관할 데이터를 하나의 논리적 테이블로 연결하려 합니다.

먼저 좌표를 잡자: Kafka·Flink·Iceberg·Fluss

시스템데이터 경로에서 맡는 역할중심 개념Fluss와의 관계
Kafka이벤트를 서비스 사이로 전달하고, 재생 가능한 로그를 보관토픽, 파티션, 컨슈머 그룹Log Table·offset과 닮았지만, Fluss는 메시지 브로커보다 분석용 테이블 저장소에 가깝습니다.
Flink스트림과 배치 데이터를 계산·변환·조인작업, 상태, 체크포인트Fluss는 Flink 작업이 읽고 쓰는 저장소입니다. Flink 자체를 대체하지 않습니다.
Iceberg데이터 레이크 위의 테이블 형식과 장기 이력 관리파일, 스냅샷, 카탈로그Fluss는 최근 데이터를 빠르게 다루고, Iceberg 같은 레이크하우스 계층으로 이력을 티어링합니다.
Fluss실시간 분석을 위한 스트리밍 테이블 저장소Log Table, Primary Key Table, bucket이벤트와 최신 상태를 짧은 지연 시간으로 다루며, 실시간 계층과 이력 계층을 하나의 테이블로 연결하려 합니다.

이 관계를 한 줄씩 표현하면 다음과 같습니다.

Kafka는 이벤트를 전달한다.
Flink는 이벤트를 계산한다.
Iceberg는 분석용 이력을 파일로 관리한다.
Fluss는 실시간 테이블을 제공하고, 그 테이블을 레이크하우스 이력과 연결한다.

따라서 Fluss의 핵심은 “Kafka 토픽을 더 싸게 저장하는 방법”이 아닙니다. 스트림과 테이블·레이크하우스를 하나의 데이터 모델로 다루는 저장소라는 점에서 이해하는 편이 정확합니다.

Fluss가 필요한 이유: Kafka와 Iceberg 사이의 복제 비용

실시간 이벤트는 흔히 Kafka에 쌓이고, 분석용 데이터는 Iceberg나 Paimon에 적재됩니다. 둘 사이에는 Flink 작업, 커넥터, 별도 저장소와 서로 다른 보존 정책이 놓입니다.

이 구성은 검증된 선택입니다. 다만 실시간 분석이나 AI 특성 계산이 늘어나면 같은 데이터를 여러 계층에 복제하고, 서로 다른 메타데이터와 최신성 목표를 관리하는 비용이 커집니다.

레이크하우스는 대규모 분석과 장기 보관에 강합니다. 하지만 Parquet 파일을 자주 작게 커밋하면 작은 파일이 늘고, 큰 파일을 만들려고 데이터를 모으면 최신성이 떨어집니다.

짧은 지연 시간
-> 잦은 작은 파일 커밋
-> 분석 읽기 효율 저하

효율적인 분석 파일
-> 더 오래 모아서 큰 파일 생성
-> 실시간성 저하

Fluss는 이 사이에 실시간 계층을 둡니다. Fluss 클러스터에서는 Arrow 기반 데이터를 짧은 지연 시간으로 읽고 쓰고, 데이터 레이크 계층에는 티어링 서비스가 이를 Parquet 또는 ORC 파일로 압축·정리합니다. 공식 Lakehouse 문서는 전자를 며칠 단위의 실시간 계층, 후자를 수개월 단위의 이력 계층으로 설명합니다.

Flink와 애플리케이션이 Fluss 실시간 계층에 읽기·쓰기를 하고, 티어링 서비스가 데이터를 레이크하우스의 장기 계층으로 옮기며 Flink가 두 계층을 함께 읽는 구조도
Fluss는 실시간 계층과 이력 계층을 별도의 적재 경로가 아니라 하나의 논리적 테이블 아래에서 관리하려 합니다.

이 구조를 Fluss는 Streaming Lakehouse라고 부릅니다. 중요한 요소는 두 가지입니다.

  • 통합 메타데이터: 실시간 데이터와 레이크하우스 데이터에 같은 테이블 메타데이터를 사용합니다.
  • 통합 읽기(Union Read): 쿼리 엔진이 실시간 계층과 레이크하우스 계층의 데이터를 합쳐 읽습니다. 0.9 계열 문서는 Flink를 지원 엔진으로 명시합니다. 미출시 Next 문서는 Apache Flink와 Apache Spark를 함께 명시하며, Trino와 StarRocks는 레이크하우스 계층만 각자의 기본 커넥터로 읽습니다.

여기서 “하나의 테이블”은 논리 모델을 뜻합니다. 최근 데이터는 Fluss의 실시간 계층에, 시간이 지난 데이터는 레이크하우스 계층에 놓입니다. 티어링 중에는 안전을 위해 두 계층에 데이터가 잠시 함께 존재할 수도 있습니다. 따라서 Fluss는 데이터를 레이크에 한 번 더 복사하는 단순 적재 싱크와 다릅니다. 실시간 계층과 이력 계층을 한 테이블의 서로 다른 보존·읽기 특성으로 다루려는 저장소입니다.

중심 개념: 토픽보다 테이블

Fluss의 최상위 데이터 단위는 데이터베이스와 테이블입니다. 테이블은 크게 두 종류로 나뉩니다.

테이블 종류쓰기 모델읽기 모델잘 맞는 데이터
Log Table추가만 가능offset을 따라 순차적으로 읽기이벤트, 로그, 감사 이력
Primary Key Table기본 키에 따른 추가·갱신·삭제키 조회, 스냅샷 뒤 변경 이력 읽기최신 상태, 특성, 참조 데이터

Log Table은 PRIMARY KEY 없이 만들며, 기록된 레코드는 바뀌지 않습니다. 이벤트 스트림에 자연스럽습니다. 반대로 Primary Key Table은 기본 키를 선언합니다. 같은 키로 새 값을 쓰면 최신 값이 남고, 키로 한 행을 조회하거나 변경 이력을 소비할 수 있습니다.

추가 전용 Log Table과 키 기준으로 최신 상태를 유지하는 Primary Key Table을 bucket과 partition 개념으로 비교한 구조도
Fluss는 순차 이벤트와 최신 상태를 별도 제품으로 나누지 않고, 서로 다른 두 테이블 모델로 표현합니다.

여기서 Kafka 사용자에게 익숙한 개념도 있습니다.

  • bucket은 테이블 안의 병렬 처리 단위입니다. Kafka의 파티션과 비슷하게 생각할 수 있지만, Fluss에서는 테이블의 병렬성·데이터 이동·백업의 기본 단위이기도 합니다.
  • offset은 Log Table bucket 안에서 레코드의 위치를 나타내며, 읽기 진행 위치를 추적하는 데 씁니다.
  • **partition(파티션)**은 날짜나 리전 같은 열 값으로 테이블 데이터를 나누는 논리적 구획입니다. 하나의 파티션 안에는 다시 여러 bucket이 있습니다.

Primary Key Table의 각 bucket에는 변경 이력을 위한 로그와 현재 키 상태를 위한 저장 구조가 함께 있습니다. 공식 문서는 이 키 상태 저장 구조를 내장 RocksDB 기반 KvTablet으로 설명합니다. 이 때문에 Fluss는 이벤트를 순서대로 읽는 일뿐 아니라 최신 키 상태 조회도 주요 기능으로 둡니다.

Fluss는 Flink Catalog를 통해 테이블을 만들고 읽을 수 있습니다. 아래 예제는 Log Table과 Primary Key Table의 차이를 보여 주는 최소 구성입니다.

CREATE CATALOG fluss_catalog WITH (
  'type' = 'fluss',
  'bootstrap.servers' = 'coordinator-server:9123'
);

USE CATALOG fluss_catalog;

-- PRIMARY KEY가 없으면 추가 전용 Log Table이다.
CREATE TABLE payment_events (
  payment_id STRING,
  customer_id STRING,
  amount DECIMAL(18, 2),
  paid_at TIMESTAMP(3)
) WITH (
  'bucket.num' = '8'
);

-- PRIMARY KEY가 있으면 최신 상태를 유지하는 Primary Key Table이다.
CREATE TABLE customer_features (
  customer_id STRING,
  plan STRING,
  score DOUBLE,
  PRIMARY KEY (customer_id) NOT ENFORCED
) WITH (
  'bucket.num' = '4'
);

payment_events에는 같은 고객의 여러 결제 이벤트가 모두 남습니다. 반면 customer_features는 같은 customer_id에 새 값을 쓰면 최신 상태가 갱신됩니다. Primary Key Table의 변경 이력이 필요하면 $changelog 가상 테이블을 읽을 수 있고, 변경 전·후 행을 함께 보려면 $binlog 가상 테이블을 사용할 수 있습니다.

SELECT * FROM customer_features$changelog;

이 모델은 이벤트 이력을 다시 읽어 상태를 구성하는 스트리밍 작업과 최신 상태를 조회하는 작업을 더 가깝게 놓습니다. 그렇다고 업무 DB를 대체한다는 뜻은 아닙니다. 트랜잭션 경계, 조회 패턴, 장애 복구, 권한 모델이 다른 업무 시스템이라면 별도의 DB가 계속 필요할 수 있습니다.

통합 읽기는 어떻게 보이나

payment_events에 레이크하우스 티어링을 활성화했다고 가정해 보겠습니다. Flink에서 테이블 이름만 조회하면 실시간 계층과 이력 계층을 함께 읽습니다. 반대로 $lake 접미사를 붙이면 레이크하우스 계층만 읽습니다. 통합 읽기 문서의 기본 동작도 이와 같습니다.

-- 기본값: Fluss의 최근 데이터와 레이크하우스 이력을 함께 읽는다.
SELECT * FROM payment_events;

-- 이력 계층만 읽는다.
SELECT * FROM payment_events$lake;

이 두 쿼리의 차이가 Fluss의 핵심입니다. Log Table이나 Primary Key Table을 만드는 것만으로는 Streaming Lakehouse가 되지 않습니다. 티어링을 활성화하면 실시간 계층과 레이크하우스 계층이 같은 테이블 메타데이터를 공유합니다. 그 뒤 Flink의 통합 읽기가 두 계층을 하나의 결과로 보여 줍니다. 미출시 Next 문서는 Spark도 통합 읽기를 지원한다고 설명하므로, 실제 도입에서는 대상 릴리스의 지원 범위를 다시 확인해야 합니다. 이 조합으로 하나의 논리적 테이블에서 최신성과 긴 이력을 함께 다룰 수 있습니다.

같은 데이터 경로에서 언제 무엇을 쓰나

네 시스템은 함께 쓸 수 있습니다. 다음처럼 같은 결제 이벤트를 기준으로 보면 역할 경계가 더 분명해집니다.

필요가장 자연스러운 중심 시스템Fluss가 더해지는 지점
결제 완료 이벤트를 여러 서비스에 전달하고 재처리Kafka기존 이벤트 계약을 바꾸지 않아도 됩니다. Fluss의 도입 이유가 되지는 않습니다.
이벤트를 정제하고 조인해 파생 데이터를 계산FlinkFluss는 입력·출력·상태 조회에 쓰는 저장소가 될 수 있습니다. 계산은 Flink가 담당합니다.
수개월치 이력을 대규모 분석 엔진으로 조회Iceberg·PaimonFluss의 티어링 대상이 될 수 있습니다. 장기 파일 분석을 Fluss가 대신하는 것은 아닙니다.
최근 이벤트와 최신 키 상태를 짧은 지연 시간으로 함께 다룸FlussLog Table과 Primary Key Table을 선택하고, 필요하면 Flink가 실시간·이력 계층을 통합해 읽습니다.

예를 들어 결제 이벤트를 Kafka로 각 서비스에 전달하고, Flink가 이를 정제해 payment_events Log Table과 고객별 customer_features Primary Key Table에 쓸 수 있습니다. Fluss의 최근 데이터는 즉시 분석과 조회 조인(lookup join)에 쓰고, 시간이 지난 데이터는 Iceberg나 Paimon으로 티어링합니다. 이때 Flink는 두 계층을 함께 읽을 수 있습니다.

Kafka payment-completed
  -> Flink가 이벤트를 정제·조인
  -> Fluss payment_events: 순차 이벤트를 보관하는 Log Table
  -> Fluss customer_features: 최신 고객 상태를 보관하는 Primary Key Table
  -> Iceberg 또는 Paimon: 압축된 장기 이력
  -> Flink 통합 읽기: 최근 데이터와 이력을 함께 분석

따라서 “Fluss가 Kafka를 대체한다”는 결론은 너무 빠릅니다. Kafka는 기존 서비스의 이벤트 계약, Connect·Streams 생태계, 컨슈머 그룹 운영, 재생 경로를 이미 갖고 있습니다. Fluss는 특히 실시간 분석, 키 기반 조회, 스트리밍 레이크하우스가 중심인 새로운 데이터 경로에서 검토할 대상입니다.

클러스터와 저장소 계층은 어떻게 나뉘나

Fluss 클러스터에는 크게 CoordinatorServer와 TabletServer가 있습니다. CoordinatorServer는 TabletServer·메타데이터·재균형과 장애 복구를 조정하고, TabletServer는 실제 데이터를 관리하고 저장합니다.

선택적으로 원격 저장소와 레이크하우스 저장소를 붙일 수 있습니다.

계층역할현재 문서에서의 예
TabletServer의 로컬 저장소짧은 지연 시간의 실시간 데이터Arrow 파일
원격 저장소Primary Key Table 스냅샷과 Log Table의 티어링 세그먼트HDFS, S3 계열
레이크하우스 저장소압축된 장기 이력과 분석Paimon, Iceberg, Lance

현재 배포 문서는 CoordinatorServer 간 조정과 메타데이터 관리에 ZooKeeper를 사용한다고 설명하면서, 이를 단순화하기 위해 향후 제거할 계획도 밝힙니다. 지금 도입을 검토한다면 기능 목록뿐 아니라 이런 배포 의존성과 버전 변화도 함께 확인해야 합니다.

Fluss를 코드 수준의 추상화로만 보지 말고, 지연 시간·로컬 디스크·원격 저장소 전송·티어링 지연·클러스터 재균형을 함께 관찰해야 합니다. Konduo는 Kafka와 데이터베이스 같은 운영 대상을 플러그인으로 연결해 상태, 메트릭 근거, 진단, 알림 대응을 한 흐름에서 확인하도록 설계된 통합 관리 운영 플랫폼입니다. Fluss를 도입하더라도 주변 Kafka·저장소·메트릭 계층을 함께 보지 않으면 실시간성의 병목을 놓치기 쉽습니다.

현재 성숙도: 아직 인큐베이팅 단계다

“Fluss가 Apache Incubator를 졸업했다”라고 말하기에는 아직 이릅니다.

이 글을 쓰는 2026-07-28 기준으로 Apache Incubator의 Fluss 상태 페이지는 Fluss를 여전히 인큐베이팅 프로젝트로 표시합니다. 다만 2026년 4월 인큐베이터 보고서에는 Fluss가 “ready to graduate”라고 기록돼 있습니다. 즉 졸업 준비가 됐다는 평가는 받았지만, 공식 졸업 절차가 끝난 상태는 아닙니다.

이 구분은 단순한 명칭 문제가 아닙니다. 인큐베이팅 프로젝트의 API, 배포 구조, 운영 권장 사항은 빠르게 바뀔 수 있습니다. 현재 단계에서는 실험·검증 대상으로 보는 편이 정확합니다. 인큐베이터 상태 페이지에는 2026-05-04의 0.9.1 릴리스도 기록돼 있습니다.

도입 전에 확인할 질문

Fluss는 흥미로운 문제를 다루지만, 모든 Kafka 또는 레이크하우스 환경에 바로 넣을 기본 구성 요소는 아닙니다.

  • 실시간 데이터와 이력 데이터를 정말 같은 테이블로 읽어야 하는가?
  • 이벤트를 순차 소비하는 것 외에 최신 키 상태 조회나 조회 조인(lookup join)이 중요한가?
  • Flink 중심의 계산 경로가 이미 있거나 새로 도입할 수 있는가?
  • 현재 인큐베이팅 단계의 API·배포 변경을 검증 환경에서 감당할 수 있는가?
  • 기존 Kafka 토픽, Schema Registry, Connect, Streams, 운영 도구와의 경계는 무엇인가?
  • 로컬 디스크·원격 저장소·레이크하우스 계층의 보존 기간과 비용을 각각 측정했는가?

Fluss가 가장 설득력 있는 곳은 Kafka를 무조건 없애고 싶은 곳이 아니라, 실시간 분석 데이터와 레이크하우스 이력을 계속 복제하는 비용이 이미 커진 곳입니다.

결론

Apache Fluss는 Kafka의 이름을 바꾼 제품도, Iceberg의 대체재도 아닙니다.

Log Table로는 이벤트 흐름을 다루고,
Primary Key Table로는 최신 상태를 다루며,
티어링과 통합 읽기로는 실시간 계층과 이력 계층을 연결한다.

이 조합이 Fluss의 핵심입니다. 2026-07-28 현재 Fluss는 아직 Apache Incubator를 졸업하지 않았습니다. 그렇지만 졸업 준비가 됐다는 인큐베이터의 평가는, 단순한 실험 프로젝트를 넘어 활발히 검증할 가치가 있는 단계에 왔다는 신호로 볼 수 있습니다.

함께 읽기 좋은 글