큐는 쌓이는 순간부터 장애다: Cloudflare Queues 백로그 지표로 보는 재시도와 DLQ
메시지 큐를 붙였는데도 장애가 반복된다면, 우리는 무엇을 먼저 봐야 할까?
큐는 쌓이는 순간부터 장애다: Cloudflare Queues 백로그 지표로 보는 재시도와 DLQ
- 카테고리: infra_dev
- 예상 읽기 시간: 10분
- 오늘의 질문: 메시지 큐를 붙였는데도 장애가 반복된다면, 우리는 무엇을 먼저 봐야 할까?
- 핵심 출처:
- Cloudflare Queues Changelog - 2026-04-28 등, 확인일 2026-06-15
- Cloudflare Queues now available on Workers Free plan - 2026-02-04, 확인일 2026-06-15
- Batching, Retries and Delays · Cloudflare Queues docs - 문서, 확인일 2026-06-15
- Dead Letter Queues · Cloudflare Queues docs - 문서, 확인일 2026-06-15
- Configure Queues · Cloudflare Queues docs - 문서, 확인일 2026-06-15
1. 왜 지금 봐야 하나
작은 팀이 비동기 처리를 도입할 때 가장 흔한 착각은 “큐를 넣으면 서버가 안정된다”는 생각이다. 실제로 큐는 요청-응답 경로에서 무거운 일을 떼어내는 데 매우 유용하다. 하지만 큐는 일을 없애지 않는다. 단지 일을 나중으로 미루고, 실패를 다른 곳에 쌓아둔다.
Cloudflare Queues는 2026년 들어 이 지점을 더 잘 관찰할 수 있는 방향으로 바뀌었다. 2026년 2월에는 Workers Free plan에서도 Queues를 사용할 수 있게 되었고, 2026년 4월에는 backlog_count, backlog_bytes, oldest_message_timestamp_ms 같은 실시간 백로그 지표가 공개되었다. 즉, 이제 “큐를 써볼 수 있느냐”보다 “큐가 밀릴 때 무엇을 보고 멈출 것인가”가 더 중요한 질문이 되었다.
이 글은 Cloudflare Queues 자체 소개가 아니다. 메시지 큐를 운영할 때 반드시 마주치는 세 가지 문제, 즉 백로그, 재시도, DLQ를 작은 팀의 신뢰성·비용·보안 관점에서 정리한다.
2. 핵심 개념
큐 운영의 핵심은 “생산 속도와 소비 속도의 차이”를 관리하는 것이다.
- 생산자(producer): 사용자 요청, 웹훅, 이벤트, 배치 작업처럼 메시지를 큐에 넣는 쪽
- 소비자(consumer): Worker나 HTTP pull consumer처럼 메시지를 꺼내 처리하는 쪽
- 백로그(backlog): 아직 acknowledge되지 않은 메시지의 양
- 재시도(retry): 실패한 메시지를 다시 처리하는 동작
- DLQ(dead letter queue): 정해진 재시도 횟수를 넘은 메시지를 격리하는 큐
큐를 붙이면 사용자 요청은 빨라질 수 있다. 하지만 소비자가 느리거나, 외부 API가 장애이거나, 메시지 처리 코드에 버그가 있으면 백로그가 증가한다. 백로그는 단순한 숫자가 아니다. 지연 시간, 비용, 장애 전파 가능성을 동시에 보여주는 신호다.
Cloudflare Queues의 최근 백로그 지표는 이 신호를 세 가지로 나눠 보여준다.
backlog_count: 처리되지 않은 메시지 개수backlog_bytes: 처리되지 않은 메시지의 총 크기oldest_message_timestamp_ms: 가장 오래된 미처리 메시지의 시각
개수만 보면 위험을 놓칠 수 있다. 1만 개의 작은 이벤트와 1만 개의 이미지 처리 작업은 비용과 지연이 다르다. 반대로 총 바이트만 보면 오래된 VIP 결제 이벤트 하나가 묻힐 수 있다. 그래서 백로그 관측은 “몇 개냐”와 “얼마나 오래됐냐”를 같이 봐야 한다.
3. 최신 이슈와 연결
Cloudflare Queues는 2026년 2월 Free plan에 포함되었다. 무료 플랜에서도 최대 10,000개 큐, 하루 10,000 operations, Workers 또는 HTTP pull consumers로의 보장된 메시지 전달을 제공한다고 공지했다. 단, 무료 플랜의 최대 보존 기간은 24시간이고, 유료 티어의 14일과 다르다.
이 제한은 운영 설계에 직접 영향을 준다. “무료니까 우선 큐에 넣자”는 결정은 나쁘지 않지만, 24시간 안에 소비하지 못하는 메시지는 제품 기능상 의미가 있는지 먼저 물어야 한다. 예를 들어 이메일 발송 이벤트는 하루 늦어도 의미가 있을 수 있지만, 5분 안에 처리해야 하는 결제 승인 후속 작업은 다른 보장 방식이 필요할 수 있다.
2026년 4월의 실시간 백로그 지표 추가도 중요하다. 예전에는 큐가 밀리는지 확인하려면 소비자 로그, 외부 API 에러율, 수동 샘플링에 의존하기 쉬웠다. 이제는 큐 자체에서 미처리 메시지 수, 크기, 가장 오래된 메시지 시각을 볼 수 있다. 이는 알림 기준을 “에러가 났다”에서 “복구 가능 시간이 줄어든다”로 옮길 수 있다는 뜻이다.
4. 개발자 관점 해석
큐 장애의 무서운 점은 조용히 시작된다는 것이다. HTTP 서버 장애는 500 응답으로 바로 보인다. 하지만 큐 소비자가 조금씩 느려지는 장애는 처음에는 사용자에게 보이지 않는다. 대신 백로그가 쌓이고, 재시도가 증가하고, 외부 API 호출이 중복되고, 결국 비용과 데이터 정합성 문제가 한꺼번에 나타난다.
여기서 중요한 트레이드오프가 있다.
첫째, 배치 크기를 키우면 비용은 줄지만 실패 반경은 커질 수 있다. Cloudflare 문서에 따르면 max_batch_size 기본값은 10이고, max_batch_timeout 기본값은 5초다. 큰 배치는 Worker 호출 수와 외부 API write 횟수를 줄일 수 있다. 하지만 배치 중 한 메시지에서 예외가 나면, 명시적으로 ack하지 않은 메시지들이 다시 배달될 수 있다. 비멱등 작업이라면 중복 결제, 중복 이메일, 중복 포인트 지급 같은 문제가 생긴다.
둘째, 재시도는 신뢰성을 높이지만 장애를 증폭할 수도 있다. 외부 API가 5분 동안 장애인데 모든 메시지를 즉시 재시도하면, 복구 직후 더 큰 트래픽 폭탄을 만든다. retry()와 retry delay는 실패를 “다시 시도할 일”로 다루게 해주지만, 재시도 횟수와 지연 시간을 제품 요구사항에 맞게 제한해야 한다.
셋째, DLQ는 실패를 숨기는 곳이 아니라 실패를 격리하는 곳이다. Cloudflare 문서는 DLQ를 설정하지 않으면 재시도 한도에 도달한 메시지가 삭제될 수 있다고 설명한다. DLQ를 둔다는 것은 “처리 실패를 잃어버리지 않고, 나중에 원인 분석과 재처리를 하겠다”는 운영 약속이다.
보안 관점도 있다. 큐 메시지에는 사용자 ID, 주문 ID, 웹훅 payload, 내부 상태가 들어가기 쉽다. 메시지 보존 기간이 길수록 유출 시 피해도 커진다. 그래서 큐에는 secret 원문을 넣지 말고, 필요한 최소 식별자와 재조회 가능한 참조만 넣는 편이 안전하다.
5. 내 프로젝트에 적용할 체크포인트
작은 팀이라면 아래 순서로 점검하자.
-
백로그 알림을 에러율보다 먼저 만든다.
backlog_count가 일정 수준 이상인지oldest_message_timestamp_ms가 SLA를 넘는지backlog_bytes가 예상보다 빠르게 증가하는지
-
메시지 처리 함수를 멱등하게 만든다.
- 메시지 ID 또는 업무 키를 저장해 중복 처리를 막는가?
- 외부 API 호출 전후 상태가 분리되어 있는가?
- “이미 처리됨”을 성공으로 볼 수 있는가?
-
배치 설정을 비용 절감만으로 정하지 않는다.
- 큰 배치가 실패했을 때 재처리 범위는 어디까지인가?
- 메시지별
ack()또는retry()를 써야 하는가? - 외부 API rate limit에 맞춘 배치 크기인가?
-
DLQ를 반드시 소비 가능한 상태로 둔다.
- DLQ에 쌓인 메시지를 누가 언제 확인하는가?
- DLQ 메시지는 며칠 보존되는가?
- 재처리 스크립트가 안전하게 멱등성을 지키는가?
-
무료 플랜의 보존 기간을 제품 요구사항과 비교한다.
- 24시간 후 사라져도 되는 이벤트인가?
- 14일 보존이 필요한 감사·정산·주문 이벤트인가?
- 장기 보존이 필요하면 DB나 오브젝트 스토리지에 별도 원장을 남기는가?
6. 오늘 10분 액션
지금 운영 중인 비동기 작업 하나를 골라 아래 표를 채워보자.
| 질문 | 내 답 |
|---|---|
| 이 큐의 생산자는 무엇인가? | |
| 소비자는 몇 개이고 어디서 돈이 드는가? | |
| 10분 동안 소비자가 멈추면 몇 개가 쌓이는가? | |
| 가장 오래된 메시지가 몇 분을 넘으면 장애인가? | |
| 재시도는 몇 번까지 허용할 것인가? | |
| DLQ가 없다면 실패 메시지는 어디로 가는가? | |
| 메시지 처리는 멱등한가? 어떤 키로 보장하는가? |
그리고 알림 기준 하나만 정하자.
“가장 오래된 메시지가 5분을 넘으면 경고, 15분을 넘으면 장애로 본다.”
정확한 숫자는 서비스마다 다르다. 중요한 것은 큐의 성공 기준을 “메시지를 넣었다”가 아니라 “정해진 시간 안에 안전하게 처리했다”로 바꾸는 것이다.
7. 더 볼 자료
- Cloudflare Queues Changelog: 백로그 지표, Free plan, pull consumer 제한 등 최근 변경을 확인할 수 있다.
- Batching, Retries and Delays: 배치 크기, timeout, 명시적 ack/retry의 실패 반경을 이해할 때 유용하다.
- Dead Letter Queues: 재시도 한도 이후 메시지를 삭제하지 않고 격리하는 방법을 설명한다.
- Configure Queues:
max_batch_size,max_batch_timeout,max_retries,dead_letter_queue,max_concurrency설정을 한 번에 볼 수 있다.
중복 회피 메모
최근 infra_dev 글은 PostgreSQL 19 관측 지표, Docker docker cp 보안 경계, GKE standby buffer, OpenTelemetry Collector 운영, Cloud Run worker pool과 Pub/Sub/Kafka backpressure, OIDC 기반 배포 secret 축소를 다뤘다. 이번 글은 특정 클라우드 워커 분리나 일반 backpressure 설명을 반복하지 않고, Cloudflare Queues의 2026년 Free plan 확대와 실시간 백로그 지표를 바탕으로 큐 자체의 운영 기준, 메시지별 ack/retry, DLQ, 보존 기간의 신뢰성·비용·보안 트레이드오프에 집중했다.
핵심 출처
로그인하면 이 글을 북마크하고, 나만 보는 한 줄 메모를 남길 수 있어요.
댓글 0
최신순 ▾혹시 이 글을 읽는 동료 개발자가 있다면, GitHub으로 로그인하고 한 줄 흔적을 남겨줘요. (스팸 방지용 로그인이에요)