강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

gnstjrdlsla님의 프로필 이미지
gnstjrdlsla

작성한 질문수

실전에서 바로 써먹는 Kafka 입문

[실습] Spring Boot로 Kafka에서 재시도조차 실패한 메시지를 따로 보관하기 (DLT, Dead Letter Topic)

잘못된 이메일 주소로 인해 발송 실패 코드

작성

·

26

0

POSTMAN에
to: fail@naver.com 으로 변경하여 send할 시

총 5번 재시도 후 강사님 처럼 멈추지 않고 아래 에러가 무한 반복이 됩니다.

 

2026-01-04T20:45:42.814+09:00 ERROR 20160 --- [ner#0.dlt-0-C-1] k.r.DeadLetterPublishingRecovererFactory : Record: topic = email.send.dlt, partition = 0, offset = 2, main topic = email.send threw an error at topic email.send.dlt and won't be retried. Sending to DLT with name email.send.dlt.

org.springframework.kafka.listener.ListenerExecutionFailedException: Listener failed

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.decorateException(KafkaMessageListenerContainer.java:3011) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeOnMessage(KafkaMessageListenerContainer.java:2911) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeOnMessage(KafkaMessageListenerContainer.java:2877) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:2787) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeWithRecords(KafkaMessageListenerContainer.java:2629) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeRecordListener(KafkaMessageListenerContainer.java:2523) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:2161) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeIfHaveRecords(KafkaMessageListenerContainer.java:1538) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:1476) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:1345) ~[spring-kafka-4.0.1.jar:4.0.1]

at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) ~[na:na]

at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]

Caused by: org.springframework.kafka.listener.TimestampedException: Exception thrown at 2026-01-04T11:45:42.814281400Z

at org.springframework.kafka.listener.adapter.KafkaBackoffAwareMessageListenerAdapter.onMessage(KafkaBackoffAwareMessageListenerAdapter.java:100) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.adapter.KafkaBackoffAwareMessageListenerAdapter.onMessage(KafkaBackoffAwareMessageListenerAdapter.java:49) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeOnMessage(KafkaMessageListenerContainer.java:2898) ~[spring-kafka-4.0.1.jar:4.0.1]

... 10 common frames omitted

Caused by: org.springframework.kafka.listener.ListenerExecutionFailedException: invokeHandler Failed

at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.checkAckArg(MessagingMessageListenerAdapter.java:519) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:496) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invoke(MessagingMessageListenerAdapter.java:425) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:92) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:52) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.adapter.KafkaBackoffAwareMessageListenerAdapter.invokeDelegateOnMessage(KafkaBackoffAwareMessageListenerAdapter.java:106) ~[spring-kafka-4.0.1.jar:4.0.1]

at org.springframework.kafka.listener.adapter.KafkaBackoffAwareMessageListenerAdapter.onMessage(KafkaBackoffAwareMessageListenerAdapter.java:97) ~[spring-kafka-4.0.1.jar:4.0.1]

... 12 common frames omitted

Caused by: java.lang.IllegalStateException: No Acknowledgment available as an argument, the listener container must have a MANUAL AckMode to populate the Acknowledgment.

... 19 common frames omitted

답변 2

0

JSCODE 박재성님의 프로필 이미지
JSCODE 박재성
지식공유자

안녕하세요 ! 질문 잘해주셨어요 !

질문해 주신 내용에 대해 답변드려볼게요 ~

 

에러 로그를 보니 DLT 토픽으로 메시지를 보내는 과정에서 문제가 발생하고 있네요!

에러 메시지에 No Acknowledgment available as an argument, the listener container must have a MANUAL AckMode to populate the Acknowledgment.라고 나오는 걸 보면, DLT Consumer 코드에서 Acknowledgment를 파라미터로 사용하려고 했는데 Kafka 리스너 설정이 MANUAL AckMode로 되어있지 않아서 발생하는 문제예요 !

해당 실습과 관련 없는 코드로 인해 발생한 문제 같아요 ~

우선 EmailSendConsumer 클래스의 consume 메서드를 확인해 보시는 걸 추천드려요 ! 이 메서드는 String message 파라미터 하나만 받아야 해요 !

혹시 Acknowledgment 같은 다른 파라미터가 추가되어 있다면 제거해 주셔야 해요 !

다시 한번 수업자료와 코드 비교해 보시고 수업 자료대로 코드를 작성하셨는데도 같은 에러가 발생한다면 사용하신 코드들, application.yml과 함께 에러가 발생했을 때의 전체 로그들을 알려주시면 더 정확하게 도와드릴 수 있을 것 같아요 :)

 

추가로 또 궁금하신 점 있으시면 언제든 편하게 질문 남겨주세요~~

0

안녕하세요, 인프런 AI 인턴입니다. gnstjrdlsla님!

Kafka를 이용한 이메일 전송 시 ListenerExecutionFailedException이 무한 반복되는 문제를 겪고 계신 것 같습니다. 이 문제는 주로 잘못된 이메일 주소로 인해 메시지가 전송되지 않으면서 발생할 수 있습니다. 여러 가지 가능한 원인과 해결 방법을 아래에 정리해 드릴게요.

문제의 핵심 원인

  1. 잘못된 이메일 주소로 인한 재시도 실패:

    • 말씀해주신 대로, 잘못된 이메일 주소가 반복적으로 실패하게 되면 이 문제가 발생할 수 있습니다.
  2. DLT (Dead Letter Topic) 관련 설정 문제:

    • DeadLetterPublishingRecovererFactory 메시지를 확인해보면, DLT로 넘어가야 하는 메시지가 제대로 처리되지 않는 것 같습니다. 설정을 잘 확인해볼 필요가 있습니다.
  3. 수동 AckMode 문제:

    • 로그에서 java.lang.IllegalStateException: No Acknowledgment available as an argument 에러가 보이는데, 이는 수동 ACK 설정이 필요함을 나타냅니다.

해결 방안

  1. 재시도 및 DLT 설정 확인:

    • @RetryableTopic 어노테이션의 설정을 정확하게 검토해 주세요. 특히 재시도 횟수(attempts)와 DLT 관련 설정(dltTopicSuffix)이 의도한 대로 설정되어 있는지 확인해야 합니다.
  2. ACK Mode 설정:

    • 수동 확인 모드를 설정하면, Listener가 메시지를 수동으로 확인해야 처리되도록 설정 가능하며, 관련 설정을 AckMode.MANUAL로 변경하고, Acknowledgment 객체를 주입 받아 수동으로 ack 처리하는 방식으로 구현할 수 있습니다.
  3. 로그 분석 통한 원인 파악:

    • DLT로 메시지를 정상적으로 보내는지, 해당 메시지가 어떻게 처리되고 있는지 더욱 자세히 로그를 남기도록 설정하여 문제의 근본적인 원인을 확인할 수 있습니다.

유사한 질문 및 해결 방안 링크

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

gnstjrdlsla님의 프로필 이미지
gnstjrdlsla

작성한 질문수

질문하기