인프런 커뮤니티 질문&답변
잘못된 이메일 주소로 인해 발송 실패 코드
작성
·
81
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
위
답변 3
0
안녕하세요, 저도 같은 코드로 실습하면서 동일한 현상이 발생하였습니다!
consume() 메서드에는 별도의 Acknowledgment를 파라미터를 요구하지는 않습니다.
조금 알아보니 spring boot가 4.0.2 버전으로 올라오면서 @RetryableTopic의 dltStrategy 설정 기본 값이 기존에 FAIL_ON_ERROR 에서 ALWAYS_RETRY_ON_ERROR 로 변경 된 것으로 보입니다!
값이 ALWAYS_RETRY_ON_ERROR 일 경우, 생성된 dlt 토픽의 메시지를 consume() 메서드를 통해 처리하는 동작인 것 같습니다. 그렇기에 무한 루프를 통해 예외가 무한정으로 쌓이는 것이구요..!저는 아래와 같이 dltStrategy 값을 별도로 설정하니 해결되었습니다!dltStrategy = DltStrategy.FAIL_ON_ERROR
질문을 새로 올리기보다는 해당 글에 답글로 추가 문의 드리면 좋을 것 같아서 답글 남깁니다!
0
안녕하세요 ! 질문 잘해주셨어요 !
질문해 주신 내용에 대해 답변드려볼게요 ~
에러 로그를 보니 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이 무한 반복되는 문제를 겪고 계신 것 같습니다. 이 문제는 주로 잘못된 이메일 주소로 인해 메시지가 전송되지 않으면서 발생할 수 있습니다. 여러 가지 가능한 원인과 해결 방법을 아래에 정리해 드릴게요.
문제의 핵심 원인
잘못된 이메일 주소로 인한 재시도 실패:
- 말씀해주신 대로, 잘못된 이메일 주소가 반복적으로 실패하게 되면 이 문제가 발생할 수 있습니다.
- 말씀해주신 대로, 잘못된 이메일 주소가 반복적으로 실패하게 되면 이 문제가 발생할 수 있습니다.
DLT (Dead Letter Topic) 관련 설정 문제:
DeadLetterPublishingRecovererFactory메시지를 확인해보면, DLT로 넘어가야 하는 메시지가 제대로 처리되지 않는 것 같습니다. 설정을 잘 확인해볼 필요가 있습니다.
수동 AckMode 문제:
- 로그에서
java.lang.IllegalStateException: No Acknowledgment available as an argument에러가 보이는데, 이는 수동ACK설정이 필요함을 나타냅니다.
- 로그에서
해결 방안
재시도 및 DLT 설정 확인:
@RetryableTopic어노테이션의 설정을 정확하게 검토해 주세요. 특히 재시도 횟수(attempts)와 DLT 관련 설정(dltTopicSuffix)이 의도한 대로 설정되어 있는지 확인해야 합니다.
ACK Mode 설정:
- 수동 확인 모드를 설정하면, Listener가 메시지를 수동으로 확인해야 처리되도록 설정 가능하며, 관련 설정을
AckMode.MANUAL로 변경하고,Acknowledgment객체를 주입 받아 수동으로 ack 처리하는 방식으로 구현할 수 있습니다.
- 수동 확인 모드를 설정하면, Listener가 메시지를 수동으로 확인해야 처리되도록 설정 가능하며, 관련 설정을
로그 분석 통한 원인 파악:
- DLT로 메시지를 정상적으로 보내는지, 해당 메시지가 어떻게 처리되고 있는지 더욱 자세히 로그를 남기도록 설정하여 문제의 근본적인 원인을 확인할 수 있습니다.
- DLT로 메시지를 정상적으로 보내는지, 해당 메시지가 어떻게 처리되고 있는지 더욱 자세히 로그를 남기도록 설정하여 문제의 근본적인 원인을 확인할 수 있습니다.
유사한 질문 및 해결 방안 링크
- Kafka 설정 관련 문제 해결: 지속적인 DLT 메시지 재시도 문제 해결
- Dead Letter Queue 활용 방안: Kafka DLQ 설정 및 운영
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





안녕하세요! 강훈님 !
원인 파악과 해결책 공유해 주셔서 정말 감사합니다~~
말씀해 주신 대로 dltStrategy = DltStrategy.FAIL_ON_ERROR로 설정하시면 무한 루프 문제가 해결되는 게 맞아요 !
DLT 처리가 실패했을 때 ALWAYS_RETRY_ON_ERROR 설정이면 해당 레코드를 다시 DLT로 보내서 재시도하게 되는데, DLT 리스너에서 계속 실패하면 무한 반복이 발생하게 되거든요 ~
FAIL_ON_ERROR로 설정하면 DLT 처리 실패 시 재전송 없이 종료되어서 루프가 끊기게 돼요 !
다만 한 가지 보충 드리자면, "Spring Boot 4.0.2에서 기본값이 변경되었다"는 부분은 조금 달라요~
Spring Kafka 공식 문서와 Javadoc을 확인해 보니 @RetryableTopic이 처음 도입된 2.7 버전부터 dltStrategy의 기본값은 ALWAYS_RETRY_ON_ERROR였어요 !
Spring Boot 4.0에서 Spring Kafka의 retry 기능이 기존 Spring Retry에서 Spring Framework 코어로 이전되면서 내부 에러 핸들링 동작 방식이 달라졌어요! 이 과정에서 3.x에서는 DLT 처리 실패 시 조용히 넘어갔던 부분이 4.0에서는 더 엄격하게 재시도하도록 변경된 것으로 보여요 ! 그래서 기본값은 같지만 실제 동작이 달라져서 3.x에서는 문제없던 코드가 4.0에서 무한 루프가 발생하게 된 것 같네요 :)
제가 처음 원인 파악을 할 때는 버전을 미처 고려하지 못했는데, 해결책을 직접 찾아서 공유해 주신 덕분에 같은 문제를 겪으실 다른 수강생분들께도 큰 도움이 될 것 같아요 ! 감사합니다 😊