Kafka Streams의 정확히 한 번(EOS) 처리 — processing.guarantee=exactly_once_v2
Kafka Streams Exactly-Once Semantics(EOS v2) 공식 문서 종합 (웹 리서치, 2026) — Apache Kafka 공식 문서(streams/upgrade-guide, streams/developer-guide/config-streams) Apache Kafka 공식 문서 Streams Upgrade Guide 및 Configuring a Streams Application
이 모듈을 다 읽으면
- processing.guarantee=exactly_once_v2 하나의 설정이 실제로 무엇을 원자적으로 묶는지 설명할 수 있다
- Kafka Streams가 재시작·리밸런스 이후에도 EOS를 유지하는 원리를 kafka-learn-35/37 내용과 연결해 설명할 수 있다
kafka-learn-35에서 다룬 멱등적 프로듀서+트랜잭션, kafka-learn-37에서 다룬 state store+changelog 토픽을 전제로, Kafka Streams가 이 둘을 자동으로 엮어 애플리케이션 코드 변경 없이 end-to-end exactly-once를 제공하는 processing.guarantee 설정을 정리한다.
설정 하나로 묶이는 세 가지 — 입력 오프셋, 상태, 출력
StreamsConfig에 processing.guarantee=exactly_once_v2(Kafka Streams 2.6+, 3.0 이상 애플리케이션에서 사용 가능한 EOS v2)를 설정하면, Kafka Streams는 (1) 입력 토픽에서 읽은 레코드의 컨슈머 오프셋 커밋, (2) 그 레코드 처리로 인한 state store 갱신(내부적으로 changelog 토픽에 반영되는 것 포함), (3) 처리 결과로 만들어진 출력 레코드 쓰기, 이 세 가지를 하나의 Kafka 트랜잭션 안에 묶는다. kafka-learn-35에서 다룬 '멱등적 프로듀서 + 트랜잭션 + read_committed'가 애플리케이션 개발자가 직접 조합해야 했던 것과 달리, Kafka Streams는 이 조합을 프레임워크 차원에서 자동으로 적용해준다는 게 차이다 — 개발자는 설정 한 줄만 켜면 된다.
핵심 포인트
- processing.guarantee=exactly_once_v2 하나로 '입력 오프셋 커밋 + state store 갱신 + 출력 쓰기'가 하나의 트랜잭션으로 묶인다
- kafka-learn-35의 멱등적 프로듀서+트랜잭션 조합을 Streams 프레임워크가 자동으로 적용해준다는 차이
재시작·리밸런스 이후에도 EOS가 유지되는 이유
kafka-learn-37에서 다룬 것처럼 Kafka Streams의 상태(state store)는 로컬(RocksDB 등)에 있는 동시에 changelog 토픽에도 백업된다. 태스크가 다른 인스턴스로 리밸런스되거나 재시작되면, 새로 그 태스크를 맡은 인스턴스는 changelog 토픽으로부터 마지막으로 커밋된 지점까지 state store를 복원한 뒤, 컨슈머 오프셋 토픽에 기록된 마지막 커밋 오프셋부터 입력을 다시 읽어 처리를 재개한다. 이때 '커밋된 지점'이라는 개념 자체가 트랜잭션 커밋과 함께 원자적으로 정해지므로(오프셋/상태/출력이 다 같은 트랜잭션 안에 있으므로), 장애 도중에 일부만 반영되고 나머지는 안 반영되는 어중간한 상태가 생기지 않는다 — 이게 재시작을 거쳐도 exactly-once가 유지되는 근거다.
핵심 포인트
- 리밸런스/재시작 시 changelog에서 state store를 복원하고, 컨슈머 오프셋 토픽의 마지막 커밋 지점부터 재개한다
- 오프셋·상태·출력이 같은 트랜잭션으로 묶여 있어 '일부만 반영된' 어중간한 상태가 발생하지 않는다 — 이게 재시작 후에도 EOS가 유지되는 근거
실무 전제조건 — 리파티션 토픽과 클러스터 크기
Kafka Streams 토폴로지에서 파티션 경계를 넘는 연산(예: groupBy로 키를 바꾸는 집계)은 내부적으로 리파티션(repartition) 토픽을 거친다 — 이 토픽들도 changelog 토픽처럼 애플리케이션이 자동으로 만들고 관리하며, 복제 팩터를 설정할 수 있다. 또한 트랜잭션 기반 EOS는 실무적으로 최소 3개 브로커 클러스터를 권장 설정으로 삼는다(복제/트랜잭션 코디네이터의 가용성을 위해) — 단일 브로커나 소규모 개발 클러스터에서 EOS를 테스트할 때 이 점을 감안해야 한다.
핵심 포인트
- 파티션 경계를 넘는 연산(예: groupBy 키 변경)은 내부적으로 리파티션 토픽을 자동 생성·경유한다
- 트랜잭션 기반 EOS는 실무적으로 최소 3개 브로커 클러스터가 권장 설정