← 블로그 목록

Developer Knowledge

개발자가 알아야 할 지식: 데드레터 큐, 보이지 않는 설계는 고칠 수도 없다

데드레터 큐를 로그, 지표, 알림과 연결해 운영 가능한 설계로 만드는 방법을 정리합니다.

Amazon Web Services
  • 개발자가 알아야 할 지식
  • Queues
  • Operations
  • Reliability

데드레터 큐는 코드가 커지고 사용자가 늘어날수록 조용히 중요해지는 실무 개념입니다. 처음에는 세부 구현처럼 보이지만, 실제로는 시스템이 실패를 어떻게 다룰지 정하는 기준이 됩니다.

왜 개발자가 알아야 하나

데드레터 큐는 작은 코드 조각보다 시스템의 약속에 더 가깝습니다.

이 기준이 없으면 구현은 동작해도 운영 순간에 비용, 장애, 데이터 불일치가 드러납니다.

개발자가 이 개념을 알면 설계 결정의 이유를 더 분명히 설명하고, 장애가 나기 전에 위험을 줄일 수 있습니다.

핵심 개념

첫 번째 핵심은 경계입니다. 데드레터 큐가 적용되는 범위와 적용되지 않는 범위를 구분해야 합니다. 경계가 흐리면 예외 처리가 곳곳에 흩어지고, 나중에는 같은 문제가 서로 다른 방식으로 해결됩니다.

두 번째 핵심은 계약입니다. 서버, 클라이언트, 데이터베이스, 운영 도구가 어떤 값을 믿고 어떤 실패를 허용하는지 문서와 코드에 함께 드러나야 합니다.

세 번째 핵심은 관측 가능성입니다. 제대로 설계했는지 알려면 성공 경로뿐 아니라 거절, 충돌, 지연, 재시도 같은 사건도 로그와 지표로 확인할 수 있어야 합니다.

설계할 때 먼저 정할 경계

데드레터 큐를 설계할 때 가장 먼저 정할 것은 “어디까지 같은 규칙으로 볼 것인가”입니다. 요청 하나, 사용자 한 명, 조직 하나, 리전 하나처럼 경계를 무엇으로 잡느냐에 따라 저장해야 할 상태와 실패의 영향 범위가 달라집니다. 정상 경로만 보고 구현하면 경계 밖의 값이 들어왔을 때 임시 예외가 늘어나므로, 입력·상태·권한·시간의 경계를 문서와 테스트에 함께 남겨야 합니다.

두 번째는 소유권입니다. 데드레터 큐와 관련된 판단을 호출자, 서버, 데이터 저장소, 비동기 작업자 가운데 누가 최종적으로 책임지는지 하나씩 적어보는 편이 좋습니다. 여러 구성 요소가 같은 결정을 독립적으로 내리면 재시도나 부분 실패 때 서로 다른 결과를 만들 수 있습니다. 반대로 책임이 한 곳에 모이면 다른 구성 요소는 결과를 추측하지 않고 명시적인 계약을 따를 수 있습니다.

세 번째는 시간축입니다. 보이지 않는 설계는 고칠 수도 없다라는 관점은 배포 순간뿐 아니라 지연, 재시도, 롤백, 오래된 클라이언트가 함께 존재하는 기간까지 봐야 의미가 있습니다. 지금은 맞는 값이라도 몇 분 뒤 상태가 바뀔 수 있고, 순서가 뒤집힌 이벤트가 늦게 도착할 수 있습니다. 따라서 만료 조건, 재처리 가능성, 호환 기간을 설계 초기에 결정해야 합니다.

실패 시나리오로 점검하기

  • 부분 성공: 데드레터 큐 처리 중 일부 단계만 성공했을 때 이미 반영된 상태를 되돌릴지, 보상 작업으로 이어갈지, 사람이 확인할 대기열로 보낼지 정해야 합니다. 단순히 예외를 던지는 것으로는 외부 시스템에 남은 효과가 사라지지 않습니다.
  • 중복 실행: 네트워크 타임아웃 뒤 같은 요청이 다시 들어와도 결과가 두 번 만들어지지 않는지 확인해야 합니다. 요청 식별자, 멱등 키, 상태 전이 조건처럼 중복을 알아볼 근거가 필요합니다.
  • 순서 역전: 오래된 이벤트나 응답이 최신 상태보다 늦게 도착할 때 무엇을 버리고 무엇을 적용할지 정해야 합니다. 버전, 타임스탬프, 단조 증가 번호를 비교하는 규칙이 없으면 정상적인 재시도가 데이터 회귀를 만들 수 있습니다.
  • 의존성 장애: 데이터베이스, 캐시, 메시지 브로커, 외부 API 중 하나가 느리거나 응답하지 않을 때 데드레터 큐가 무한 대기하지 않도록 타임아웃과 제한된 재시도, 대체 경로를 함께 설계해야 합니다.

관측 가능성과 운영 기준

좋은 구현은 성공 건수만 세지 않습니다. 데드레터 큐에서 거절, 충돌, 재시도, 만료, 보상 처리 같은 상태를 서로 다른 이벤트로 기록해야 합니다. 로그에는 요청 식별자와 결정 이유를 남기고, 지표에는 처리량뿐 아니라 지연 분포와 실패 유형을 남겨야 운영자가 “느리다”를 원인별로 나눌 수 있습니다.

알림은 사용자가 영향을 받기 전 신호와 이미 영향을 받은 신호를 구분해야 합니다. 큐 적체나 재시도 증가처럼 선행하는 지표는 조기 대응에 쓰고, 최종 실패율이나 데이터 불일치처럼 결과를 보여주는 지표는 심각도를 판단하는 데 씁니다. 하나의 임계값만 두면 작은 흔들림에 과민하거나 실제 장애를 늦게 발견하기 쉽습니다.

운영 기준에는 복구 확인도 포함되어야 합니다. 장애 원인을 제거한 뒤 밀린 작업이 줄고 있는지, 실패율이 정상 범위로 돌아왔는지, 임시 우회가 새로운 병목을 만들지 않았는지 확인해야 합니다. 데드레터 큐의 완료 조건은 배포 성공이 아니라 시스템과 사용자 경험이 안정 상태로 돌아온 증거까지입니다.

작은 예시 또는 체크리스트

데드레터 큐를 새 기능에 적용한다고 해봅시다. 처음에는 정상 경로만 보이지만 실제 운영에서는 지연, 중복 요청, 권한 차이, 배포 순서처럼 작은 예외가 함께 움직입니다. 이때 데드레터 큐의 기준을 미리 정해두면 문제를 코드 곳곳의 임시 처리로 흩뜨리지 않고 한 곳에서 설명할 수 있습니다.

  • 데드레터 큐가 적용되는 경계와 예외가 문서와 코드에 드러나는가?
  • 실패하거나 지연될 때 호출자가 어떤 응답을 받는지 정해져 있는가?
  • 중복 실행, 재시도, 롤백 상황에서도 데이터가 일관되게 남는가?
  • 운영자가 성공뿐 아니라 거절, 충돌, 지연을 지표로 확인할 수 있는가?
  • 새 팀원이 이 설계를 왜 쓰는지 한 문단으로 이해할 수 있는가?

실무에서 자주 생기는 오해

  • “데드레터 큐는 나중에 트래픽이 커지면 보면 된다”는 오해가 있습니다. 많은 운영 문제는 작은 규모에서 만든 계약이 그대로 커지면서 생깁니다.

  • “라이브러리가 알아서 해준다”는 생각도 부족합니다. 도구는 메커니즘을 제공하지만 어떤 실패를 허용할지는 서비스가 정해야 합니다.

  • “문제가 생기면 로그를 보면 된다”도 늦습니다. 필요한 필드를 남기지 않은 로그는 장애 순간에 방향을 주지 못합니다.

도입 순서

  • 먼저 현재 흐름을 한 장으로 그리고 데드레터 큐와 관련된 상태 변화, 외부 효과, 책임 주체를 표시합니다.
  • 가장 자주 발생하거나 피해가 큰 실패 시나리오 하나를 골라 재현 가능한 테스트로 고정합니다.
  • 정상·거절·재시도·최종 실패를 구분하는 로그와 지표를 추가하고 대시보드에서 실제 값을 확인합니다.
  • 작은 트래픽이나 내부 사용자에게 먼저 적용해 가정과 임계값이 현실과 맞는지 관찰합니다.
  • 롤백과 복구 절차를 연습한 뒤 범위를 넓히고, 운영 결과를 설계 문서와 체크리스트에 다시 반영합니다.

오늘 바로 적용해보기

현재 서비스에서 데드레터 큐와 연결된 코드 경로 하나를 골라 정상 경로와 실패 경로를 함께 그려보세요.

코드 리뷰 체크리스트에 경계, 재시도, 관측 가능성 중 빠진 항목이 있는지 확인하세요.

운영 대시보드에 이 개념이 제대로 동작하는지 보여주는 최소 지표 하나를 추가하세요.

더 알아보기

오늘의 takeaway

데드레터 큐는 구현 디테일처럼 보이지만, 시간이 지나면 서비스가 실패를 다루는 방식 그 자체가 됩니다.