Kafka Connect Source EOS(KIP-618) — 오프셋 커밋을 트랜잭션 안에 가둔다
Kafka Connect Source EOS(KIP-618) 및 KIP-392 폴로워 페치 공식 문서 종합 (웹 리서치, 2026) — KIP-618: Exactly-Once Support for Source Connectors + KIP-392: Allow consumers to fetch from closest replica KIP-618: Exactly-Once Support for Source Connectors
이 모듈을 다 읽으면
- Connect Source EOS가 레코드 쓰기와 오프셋 커밋을 하나의 트랜잭션으로 묶는 이유를 설명할 수 있다
- source 커넥터가 이 지원을 받으려면 어떤 전제조건을 만족해야 하는지 설명할 수 있다
kafka-learn-50에서 다룬 source 커넥터의 offset.storage.topic 개념을 전제로, Kafka Connect 3.3.0(KIP-618)부터 지원되는 source 커넥터의 exactly-once 처리가 이 오프셋 커밋을 어떻게 레코드 쓰기와 하나로 묶어 보장하는지를 정리한다.
문제 상황 — 레코드는 썼는데 오프셋 기록에 실패하면?
source 커넥터가 외부 시스템에서 읽은 레코드를 Kafka에 쓰고 나서, 그 레코드에 대응하는 소스 오프셋을 offset.storage.topic에 별도로 기록하는 구조라면, 레코드 쓰기는 성공했는데 오프셋 기록이 실패하는(혹은 그 반대의) 어중간한 상태가 생길 수 있다 — 재시작 시 어느 지점부터 다시 읽어야 할지 애매해져 중복이나 누락이 발생할 위험이 있다.
핵심 포인트
- 레코드를 Kafka에 쓰는 것과 소스 오프셋을 기록하는 것이 별개 작업이면, 하나만 성공하는 어중간한 상태가 생겨 재시작 시 중복/누락 위험
해법 — 배치 하나를 트랜잭션 하나로 묶는다
KIP-618은 source 태스크가 poll() 메서드에서 반환하는 레코드 배치 하나를 Kafka 트랜잭션 하나로 감싼다 — 그 배치의 레코드들이 전부 Kafka에 쓰인 뒤, 같은 트랜잭션 안에서 해당 배치의 오프셋 정보를 offset.storage.topic에 기록하고, 그제서야 트랜잭션을 커밋한다. 그 결과 '이 배치의 소스 오프셋이 커밋됐다'는 것은 곧 '이 배치의 레코드도 반드시 Kafka에 쓰였다'는 것과 논리적으로 동치가 된다 — 기본적으로 Connect 프레임워크는 poll()이 반환하는 배치마다 새 트랜잭션을 만들고 커밋하며, 이 트랜잭션 경계는 transaction.boundary 커넥터 설정으로 조정할 수 있다.
핵심 포인트
- 배치의 레코드를 전부 Kafka에 쓴 뒤 같은 트랜잭션 안에서 오프셋을 offset.storage.topic에 기록하고 커밋 — 오프셋 커밋됨=레코드도 반드시 쓰였음이 논리적으로 동치
- 기본적으로 poll() 반환 배치마다 새 트랜잭션 생성·커밋, transaction.boundary 설정으로 트랜잭션 경계 조정 가능
전제조건 — 커넥터가 의미 있는 소스 오프셋을 제공해야 한다
이 지원을 받으려면 source 커넥터 자체가 자신이 내보내는 각 레코드에 대해 의미 있는 소스 오프셋을 제공할 수 있어야 하고, 그 오프셋에 해당하는 지점부터 외부 시스템 읽기를 재개했을 때 레코드를 빠뜨리거나 중복시키지 않아야 한다는 조건을 만족해야 한다 — 즉 프레임워크가 트랜잭션으로 감싸주는 것만으로 저절로 되는 게 아니라, 커넥터 구현 자체가 이 재개 가능성을 보장하도록 설계돼 있어야 한다는 전제가 깔려 있다.
핵심 포인트
- 커넥터가 각 레코드에 의미 있는 소스 오프셋을 제공하고, 그 지점부터 재개 시 누락·중복 없이 읽을 수 있어야 함 — 프레임워크의 트랜잭션 보장만으로 자동으로 충족되는 게 아니라 커넥터 구현 자체의 전제조건