Kafka Dead Letter Queue 설계 가이드 - 재처리와 장애 격리를 어떻게 할까
Kafka 기반 시스템에서 메시지 처리 실패를 어떻게 다뤄야 하는지 설명합니다. DLQ가 필요한 이유, 어떤 메시지를 DLQ로 보낼지, 재처리 전략과 운영 체크포인트까지 실무 중심으로 정리합니다.
왜 DLQ가 필요한가
Kafka consumer는 언젠가 실패합니다.
대표 원인:
- JSON schema mismatch
- 외부 API 장애
- DB timeout
- business validation 실패
이때 실패 메시지를 어떻게 처리할지 결정하지 않으면 consumer 전체가 멈추거나, 같은 메시지를 무한 재시도하게 됩니다.
DLQ의 목적
Dead Letter Queue의 목적은 단순 폐기가 아닙니다.
- 장애 메시지 격리
- 정상 메시지 흐름 유지
- 재처리 기회 확보
- 원인 분석 가능성 확보
즉, DLQ는 운영 관측성과 복구 전략의 일부입니다.
모든 실패를 DLQ로 보내면 안 되는 이유
실패 유형을 나눠야 합니다.
재시도 가치가 있는 실패
- 일시적 DB 장애
- 일시적 네트워크 타임아웃
- 외부 서비스 rate limit
DLQ로 보내야 하는 실패
- schema 자체가 잘못됨
- 필수 값 누락
- business invariant 위반
- 더 이상 성공 가능성이 낮은 메시지
이 구분 없이 전부 DLQ로 보내면 운영 비용만 커집니다.
추천 처리 흐름
Consume
-> Validate
-> Retry 가능한가?
-> Yes: bounded retry
-> No: publish to DLQ
-> Log / alert / metrics
bounded retry가 중요합니다. 무한 재시도는 장애를 숨기고 시스템을 막습니다.
DLQ 메시지에 무엇을 같이 저장할까
최소한 아래는 같이 남겨야 합니다.
- 원본 payload
- 원본 topic / partition / offset
- error type
- stack trace 요약
- 발생 시각
- consumer group 정보
그래야 나중에 재처리와 원인 분석이 가능합니다.
재처리는 어떻게 할까
DLQ에 쌓였다고 바로 자동 재처리하면 안 되는 경우도 많습니다.
권장 방식:
- 원인 분류
- 수정 가능한 문제 해결
- 선택적 replay
예를 들어 schema 버그였다면 consumer 수정 후 replay하고, business validation 실패였다면 단순 replay는 의미가 없을 수 있습니다.
마무리
Kafka DLQ의 핵심은 “실패를 치워두는 것”이 아니라 정상 흐름을 보호하면서 실패를 분석 가능한 상태로 격리하는 것입니다.
재시도, DLQ, 재처리 전략을 명확히 나누면 운영 안정성이 크게 좋아집니다.