9.3 KiB
title: company-tech-blog / Spring for Apache Kafka — Beyond the Basics: Can Your Kafka Consumers Handle a Poison Pill? source_type: company-tech-blog url: https://www.confluent.io/blog/spring-kafka-can-your-kafka-consumers-handle-a-poison-pill/ archive_url: related_branches: [feature-kafka-consumer-inbox-contract] related_projects: [ca-skeleton] tags: [company-tech-blog, ca-skeleton, messaging, kafka, dead-letter-queue] created: 2026-07-28
company-tech-blog / Spring for Apache Kafka — Beyond the Basics: Can Your Kafka Consumers Handle a Poison Pill?
Layer:
raw/company-tech-blogs/— 외부 자료 원문 발췌·출처 기록. 등급 caveat (필독): Confluent 는 Kafka 상용 벤더이고, 저자(Tim van Baarsen)는 ING Bank 소속 엔지니어로 Confluent 블로그에 기고한 것이다. 이 글은 "타사 프로덕션 장애 사례 보고"라기보다 벤더 소속 블로그에 실린, 벤더 저자의 Spring Kafka 메커니즘 설명에 가깝다. CLAUDE.md §5 에 따라company-tech-blog는 사례/관점으로만 취급하며, 이 글만으로 "공식 best practice"라고 격상하지 않는다. Spring Kafka 공식 레퍼런스(reference docs)의 corroboration 없이는official-vendor-docstrength 를 부여하지 않는다.
Parent / 활용 branch
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-kafka-consumer-inbox-contract | ca-skeleton consumer 가 역직렬화 실패를 재시도 무의미(non-retryable)로 분류하고 즉시 DLT(회수 경로)로 보내야 하는 근거 — poison pill 이 consumer offset 을 전진시키지 못한 채 무한 재시도 루프에 빠뜨리는 실패 메커니즘, 그리고 역직렬화 실패가 poll() 반환 이전에 발생해 리스너 레벨 예외 처리로는 잡을 수 없다는 사실 |
출처
- 원본 URL: https://www.confluent.io/blog/spring-kafka-can-your-kafka-consumers-handle-a-poison-pill/
- 아카이브 URL: (미제공)
- 저자 / 조직: Tim van Baarsen, Senior Software Engineer — ING Bank (Netherlands). Confluent 블로그(벤더 사이트)에 기고
- 발행일: 2020-06-30 (Jun 30, 2020, 페이지 표기 기준)
- 마지막 확인일: 2026-07-28
왜 저장했는지
ca-skeleton kafka consumer inbox 계약(feature-kafka-consumer-inbox-contract)이 "poison pill(역직렬화 실패)은 재시도 무의미 → 즉시 DLT" 로 분류하려는 결정의 근거로, poison pill 이 consumer 를 어떤 메커니즘으로 멈추게 하는지(offset 미전진 + 무한 재시도)와 그 실패가 Spring 리스너 레벨 예외 처리보다 이른 시점(poll() 반환 전)에 발생한다는 사실을 원문으로 확보하기 위함.
핵심 인용
[§"What is a poison pill?"] "A poison pill (in the context of Kafka) is a record that has been produced to a Kafka topic and always fails when consumed, no matter how many times it is attempted." (line 23 in fetched text)
[§"How can you survive a poison pill scenario?" — ErrorHandlingDeserializer 설명] "When a deserializer fails to deserialize a message, Spring has no way to handle the problem, because it occurs before the poll() returns." (line 113 in fetched text)
[§"What can go wrong if I don't protect my application against poison pills?"] "The consumption of the topic partition is blocked because the consumer offset is not moving forward." (line 89 in fetched text)
[§"What can go wrong if I don't protect my application against poison pills?"] "The consumer will try again and again (very rapidly) to deserialize the record but will never succeed." (line 90 in fetched text)
[§"How can you survive a poison pill scenario?" — 요약] "the poison pill is handled and logged. The consumer offset moves forward so that the consumer can continue consuming the next record." (line 139 in fetched text)
Claims Extracted
| Claim ID | Claim | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| CONF-POISON-C1 | poison pill 은 Kafka 토픽에 생성된 뒤 몇 번을 시도해도 항상 소비에 실패하는 레코드로 정의된다 | "A poison pill (in the context of Kafka) is a record that has been produced to a Kafka topic and always fails when consumed, no matter how many times it is attempted." | company-case-study | poison pill 용어 정의 일반. 역직렬화 실패를 포함한 "항상 실패하는 레코드" 개념 범위 | 이 정의가 Kafka 또는 Spring 공식 문서에 등재된 표준 용어라는 것 (벤더 블로그 저자의 서술) |
| CONF-POISON-C2 | 역직렬화 실패는 poll() 이 반환되기 이전에 발생하므로 Spring 은 리스너 레벨에서 이 문제를 처리할 방법이 없다 |
"When a deserializer fails to deserialize a message, Spring has no way to handle the problem, because it occurs before the poll() returns." | company-case-study | ca-skeleton consumer 가 리스너(listener) 레벨 try/catch 나 애플리케이션 예외 핸들러만으로 역직렬화 실패를 잡을 수 없다는 아키텍처 제약의 근거 | 모든 Spring Kafka 버전에서 이 메커니즘이 동일하게 유지된다는 것 — 원문은 spring-kafka 2.5.0(2020) 기준 스택 트레이스를 인용하며, 이후 버전 변경 여부는 이 글만으로 확인 불가 |
| CONF-POISON-C3 | 처리되지 않은 poison pill 은 consumer offset 을 전진시키지 못해 해당 topic partition 의 consumption 을 정지시킨다 | "The consumption of the topic partition is blocked because the consumer offset is not moving forward." | company-case-study | poison pill 미처리 시 offset stuck 실패 메커니즘 일반 | auto-commit 과 manual ack 등 커밋 방식 차이에 따라 이 거동이 달라지는지 여부 — 원문은 커밋 방식별 차이를 별도로 분석하지 않음 |
| CONF-POISON-C4 | 처리되지 않은 poison pill 은 consumer 가 동일 레코드를 매우 빠르게 반복 재시도하며 결코 성공하지 못하는 상태를 만든다 | "The consumer will try again and again (very rapidly) to deserialize the record but will never succeed." | company-case-study | poison pill 미처리 시 무한 재시도 루프 실패 근거 | 재시도 사이 backoff/interval 이 존재하는지, 로그 볼륨 외의 구체적 리소스 소모 수치 — 원문은 "very rapidly" 로만 서술하고 수치를 제시하지 않음 |
| CONF-POISON-C5 | ErrorHandlingDeserializer 를 구성하면 poison pill 이 처리·로깅되고 consumer offset 이 전진해 다음 레코드 소비를 계속할 수 있다 | "the poison pill is handled and logged. The consumer offset moves forward so that the consumer can continue consuming the next record." | company-case-study | ca-skeleton 이 역직렬화 실패 레코드를 격리(DLT 등)하고 offset 을 커밋해야 한다는 결정의 방향성 근거 | ErrorHandlingDeserializer 가 ca-skeleton 이 채택할 구체적 DLT 라우팅 메커니즘(retry topic, replay 정책 등)의 유일한 구현 방법이라는 것 — 원문은 Spring Kafka 의 한 가지 구성 예시만 보여줌 |
Usage Boundaries
- 이 자료가 직접 증명하는 것:
CONF-POISON-C1: poison pill 의 정의(항상 실패하는 레코드)CONF-POISON-C2: 역직렬화 실패가poll()반환 이전에 발생해 Spring 리스너 레벨 예외 처리로 잡을 수 없다는 메커니즘CONF-POISON-C3,CONF-POISON-C4: 처리되지 않은 poison pill 이 offset 미전진 + 무한 재시도로 이어지는 실패 사슬CONF-POISON-C5: ErrorHandlingDeserializer 적용 시 offset 이 전진해 poison pill 을 우회할 수 있다는 방향성
- 이 자료가 증명하지 않는 것:
- Kafka 또는 Spring 공식 문서가 "역직렬화 실패는 항상 DLT 로 보내야 한다"고 명시한다는 것 — 이 글은 company-tech-blog(벤더 사례)이며 공식 best practice 문서가 아니다 (CLAUDE.md §5)
- ca-skeleton 이 채택할 구체적 DLT 토픽 명명, retry 정책, replay 감사 메커니즘 — 이 글은 Spring Kafka 의
ErrorHandlingDeserializer구성 예시 하나만 제시 - 최신 Spring Kafka 버전(2020년 이후)에서도 동일한
poll()이전 실패 메커니즘이 유지된다는 것 — 버전별 재검증 필요
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-skeleton 이 실제 사용할 Spring Kafka / spring-boot 버전에서
ErrorHandlingDeserializer및DefaultErrorHandler(또는 후속 API)의 현재 동작이 이 글의 서술과 동일한지 공식 Spring Kafka 레퍼런스로 재확인 - manual acknowledgement 모드에서 poison pill 발생 시 offset 커밋 시점이 이 글의 auto-commit 전제와 동일한지 확인 (branch 범위: manual ack 채택 예정)
- ca-skeleton 이 실제 사용할 Spring Kafka / spring-boot 버전에서
메모
- 인용 1 해석 후보 (미검증): "poison pill" 은 Kafka 생태계에서 널리 쓰이는 은유적 표현으로 보이나, 이 글 자체가 그 유래를 규명하지는 않음 — RFC/공식 용어집 등재 여부는 별도 확인 필요.
- 추가로 봐야 할 동일 출처 페이지: Spring Kafka 공식 레퍼런스의
ErrorHandlingDeserializer/DefaultErrorHandler/DeadLetterPublishingRecoverer섹션 (official-vendor-doc corroboration 후보).
관련
- 같은 주제 다른 official-doc / company-tech-blog: (아직 없음 — Spring Kafka 공식 레퍼런스 등록 시 여기 추가)
- 이 자료를 인용한 wiki 요약:
[[wiki/concepts/...]](생성 시)