컬리 기술 블로그가 Kafka Connect와 JDBC 커넥터로 DB 데이터를 Kafka로 옮기는 방법과, 그 과정에서 발생하는 데이터 유실 문제를 다룬다. Kafka Connect 구성요소와 JDBC Source Connector의 세 가지 증분 조회 모드를 설명하고, 폴링 기반 CDC가 놓치는 유실 시나리오와 완화책을 정리한다.
핵심 포인트- Kafka Connect는 Worker/Connector/Task/Transformer(SMT)/Converter로 구성된다.
- JDBC Source Connector는 incrementing, timestamp, timestamp+incrementing 세 모드로 증분 조회한다.
- 로그 기반 CDC(Debezium)와 쿼리 기반 CDC(JDBC)의 트레이드오프를 비교한다.
- 폴링 방식은 삭제·중간 변경·순서 뒤바뀜 세 유형의 데이터 유실이 생긴다.
- timestamp.delay.interval.ms로 커밋 지연 트랜잭션을 기다려 유실을 줄인다.
상세 정리- 구성: Worker는 Kafka Connect 프로세스가 도는 서버/인스턴스, Connector는 task를 관리하며 실제 파이프라인을 담당, Task는 실제 추출·삽입을 수행하는 스레드 단위다.
- SMT(Transformer)는 메시지 내용을 변형하고, Converter는 JSON/Avro 등 데이터 포맷을 변환한다.
- Incrementing 모드: auto-increment PK를 추적해 새 행만 가져온다. 기존 행의 컬럼 수정은 놓친다.
- Timestamp 모드: timestamp 컬럼으로 더 최근 레코드를 식별한다.
- Timestamp+Incrementing 모드: 둘을 결합해 중복 처리까지 대응한다.
- CDC 비교: 로그 기반(Debezium)은 트랜잭션 로그를 직접 읽어 지연이 낮고 변경을 빠짐없이 추적하지만 설정이 복잡하고 DB별 구현이 필요하다.
- 쿼리 기반(JDBC)은 주기적 SQL 폴링이라 구현이 단순하고 권한이 적게 들며 DB 종류를 안 가리고 비용이 낮다. 로그 접근이 막힌 환경에 적합하다.
- 유실 시나리오 1: 폴링 사이에 삭제된 행은 다음 조회 때 사라져 감지 못한다. incrementing/timestamp 모두 삭제는 못 잡는다.
- 유실 시나리오 2: 한 폴링 간격 안에서 insert 후 delete되면 순변화 0으로 보여 조회 시점 상태만 남는다.
- 유실 시나리오 3: 긴 트랜잭션이 커밋을 지연시켜, 과거 timestamp를 가진 레코드가 폴링 창이 닫힌 뒤 커밋되며 이벤트 순서에 구멍이 생긴다.
- 완화책: timestamp.delay.interval.ms로 인입 전 인위적 지연을 둬 미커밋 트랜잭션이 끝날 시간을 준다. 대신 end-to-end 지연이 늘어 트랜잭션 타임아웃 특성에 맞춰 튜닝해야 한다.
- 적합 사용처: update/delete 없이 insert만 하고 현재 상태만 중요한 로그성 테이블에 JDBC 커넥터가 가장 잘 맞는다.
왜 읽나Kafka Connect JDBC로 DB→Kafka 파이프라인을 구성하려는 백엔드·데이터 엔지니어가 폴링 CDC의 유실 함정과 회피책을 미리 파악하는 데 유용.