Kafka 테이블 엔진 — 스트림 수집의 표준 아키텍처와 at-least-once의 한계
ClickHouse Data Skipping Index 및 Kafka 테이블 엔진 공식 문서·기술 블로그 종합 (웹 리서치, 2026) — ClickHouse 공식 문서(best-practices/use-data-skipping-indices-where-appropriate, integrations/kafka/kafka-table-engine) + Altinity 블로그 ClickHouse 공식 문서 Using the Kafka table engine, Altinity Kafka Engine FAQ
이 모듈을 다 읽으면
- Kafka 엔진 + Materialized View 조합이 표준 스트림 수집 아키텍처인 이유를 설명할 수 있다
- Kafka 엔진이 exactly-once가 아니라 at-least-once만 보장하는 근본 원인을 판단할 수 있다
clickhouse-learn-05에서 다룬 Materialized View(INSERT 트리거)를 실제로 어디에 쓰는지 보여주는 대표 사례 — Kafka에서 직접 데이터를 읽어들이는 Kafka 엔진과, 그 데이터를 영구 테이블로 흘려보내는 표준 아키텍처, 그리고 그 한계를 정리한다.
표준 아키텍처 — Kafka 엔진은 그 자체로 데이터를 저장하지 않는다
Kafka 테이블 엔진은 Kafka 토픽을 구독해 메시지를 읽어오는 창구 역할만 하며, 그 자체로는 데이터를 디스크에 영구 저장하지 않는다(SELECT 한 번 하면 그 순간 소비된 메시지만 보이고 사라진다). 그래서 거의 항상 Materialized View(clickhouse-learn-05)와 짝을 이뤄 쓴다 — Kafka 엔진 테이블에 새 메시지가 들어올 때마다(내부적으로 poll), Materialized View가 그 데이터를 변환해 실제 영구 저장소인 MergeTree 테이블로 흘려보낸다. 즉 'Kafka 엔진(구독 창구) → Materialized View(INSERT 트리거) → MergeTree(영구 저장)'이 표준 3단 구성이다.
핵심 포인트
- Kafka 엔진 테이블 자체는 데이터를 영구 저장하지 않는 구독 창구일 뿐
- 표준 아키텍처: Kafka 엔진(구독) → Materialized View(변환·전달) → MergeTree(영구 저장) 3단 구성
왜 exactly-once가 아니라 at-least-once인가
Kafka 엔진이 메시지를 처리하는 과정은 실제로 두 개의 독립적인 커밋으로 이뤄진다: (1) 읽어온 데이터를 ClickHouse(MergeTree)에 flush(쓰기), (2) 그 메시지를 처리했다고 Kafka 쪽에 오프셋을 커밋. 이 두 커밋은 서로 다른 시스템(ClickHouse와 Kafka)에 걸쳐 있어 하나의 원자적 트랜잭션으로 묶이지 않는다 — kafka-learn-49에서 다룬 Kafka Streams의 EOS가 '입력 오프셋+상태+출력'을 전부 같은 Kafka 트랜잭션 안에 묶어서 원자성을 얻는 것과 대조적으로, 여기서는 애초에 오프셋 커밋 대상(Kafka)과 데이터 쓰기 대상(ClickHouse)이 별개 시스템이라 그런 원자적 트랜잭션 자체가 불가능하다. 그래서 ClickHouse에 데이터를 flush한 직후, 그 오프셋을 Kafka에 커밋하기 전에 장애가 나면, 재시작 후 같은 메시지를 다시 읽어 중복 삽입이 일어날 수 있다 — 이것이 Kafka 엔진이 '적어도 한 번은 들어간다(at-least-once)'만 보장하고 정확히 한 번은 보장 못 하는 근본 이유다. 정확히 한 번이 꼭 필요하다면 ClickHouse Kafka Connect(별도 배포 방식)가 대안으로 제시된다.
핵심 포인트
- ClickHouse에 데이터 flush(쓰기)와 Kafka에 오프셋 커밋, 이 두 커밋이 서로 다른 시스템에 걸쳐 있어 원자적으로 묶이지 않는다
- kafka-learn-49의 Kafka Streams EOS(같은 Kafka 트랜잭션 안에 다 묶음)와 대조적 — 여기선 대상 시스템 자체가 다르다
- flush 후 오프셋 커밋 전에 장애가 나면 재시작 시 중복 삽입 가능 — at-least-once만 보장, exactly-once가 꼭 필요하면 ClickHouse Kafka Connect가 대안