Queues, Webhooks and Rate Limits: Retries, Backlogs and Backoff You Can Watch Happen
큐, 웹훅, 레이트 리밋 — 재시도·백로그·백오프를 직접 관찰하는 시뮬레이터
메시지 큐, 웹훅, API 레이트 리밋에서 발생하는 지연·재시도·백오프를 브라우저 시뮬레이터로 관찰하는 글입니다. Kafka와 RabbitMQ의 차이, 웹훅 서명 검증과 중복 처리, 429 응답 대응을 실패 시나리오 중심으로 설명합니다.
- 주제
AI 요약
“At-least-once delivery”, “consumer lag”, “dead letter queue”, “exponential backoff” 같은 용어는 익숙하지만, 실제 장애에서 어떤 모습으로 나타나는지 직접 본 경험은 별개입니다. 이 글은 비동기 전달 과정의 세 구간을 다루는 무료 브라우저 시뮬레이터 세 가지를 소개합니다. 모두 회원가입 없이 사용할 수 있으며, 글 작성자가 세 도구 제작에 참여했다는 점도 밝혔습니다.
메시지 큐에서 지연과 백로그 보기
Message Queue Simulator는 Kafka 스타일의 토픽과 파티션, RabbitMQ 스타일의 exchange와 queue를 함께 모델링합니다. 정상 동작, consumer lag, backpressure, dead letter 처리, 순서 보장, consumer rebalance까지 여섯 가지 시나리오를 실행합니다.
먼저 정상 상태에서 producer가 메시지를 넣고 consumer가 꺼내면서 큐 깊이가 안정적으로 유지되는 모습을 확인합니다. 이후 생산 속도가 소비 속도를 앞서면 lag가 커집니다. 온콜에서 실제로 경보를 울리는 지표는 단순히 높은 lag가 아니라 계속 증가하는 lag입니다. lag가 높지만 안정적이면 당장 장애로 이어지지 않을 수 있지만, 증가하는 lag는 처리량 부족이나 소비자 문제를 뜻합니다.
Backpressure 시나리오에서는 소비자가 비우는 속도보다 빠르게 메시지를 밀어 넣어 백로그를 쌓습니다. 과부하가 계속되면 무한정 버퍼링할 수 없으므로 producer를 의도적으로 늦추는 편이 장애가 날 때까지 쌓아 두는 것보다 낫다는 점을 보여줍니다.
처리할 수 없는 poison message는 dead letter queue(DLQ)로 보내 스트림을 막지 않게 합니다. 시뮬레이터는 메시지를 DLQ로 바로 보내지만, 실제 시스템은 보통 몇 차례 재시도한 뒤 이동시킵니다. 결국 사람이 확인해야 할 메시지를 별도 경로에 남기고 정상 메시지 처리를 계속하는 방식입니다.
순서 보장 시나리오는 Kafka에 관한 흔한 오해를 다룹니다. 순서는 토픽 전체가 아니라 파티션 안에서만 보장됩니다. 여러 파티션을 사용하는 토픽에서 전체 순서를 기대할 수 없는 이유를 화면에서 확인하게 합니다. Rebalancing 시나리오에서는 consumer가 들어오거나 나갈 때 파티션 소유권이 재분배되는 과정을 보여줍니다. 과거 Kafka의 리밸런싱은 전체 처리를 멈추는 방식으로 알려졌지만, 최신 Kafka는 incremental rebalance를 사용해 중단을 줄입니다. 그래도 consumer group 배포가 lag 그래프에 흔적을 남기는 이유는 확인할 수 있습니다.
웹훅의 응답 코드와 서명 검증
큐가 직접 관리하는 서비스 사이를 연결한다면, 웹훅은 외부 서버로 이벤트를 전달합니다. Webhook Delivery Simulator에서는 수신 엔드포인트가 200, 400, 429, 500을 반환하거나 타임아웃과 간헐적 실패를 일으키도록 설정합니다. 그 결과에 따라 발신자가 어떻게 재시도하는지 관찰합니다.
이 시뮬레이터의 예시 정책에서는 500과 타임아웃을 backoff와 함께 재시도하고, 400은 재시도하지 않습니다. 잘못된 요청을 다시 보내도 해결되지 않기 때문입니다. 429는 요청 속도를 낮추는 신호로 처리합니다. 다만 실제 제공업체마다 정책이 다릅니다. Stripe와 Svix는 모든 non-2xx 응답을 재시도하는 예로 언급됩니다. 따라서 수신 서버의 상태 코드는 단순한 로그가 아니라 발신자에게 전달하는 동작 지침입니다.
보안 실습에서는 공유 비밀키로 HMAC 서명을 붙입니다. 서명한 뒤 본문을 수정하면 검증에 실패하고, 오래된 이벤트를 재전송하면 timestamp 검사가 이를 잡아냅니다. 웹훅 엔드포인트가 서명을 검증하지 않으면 누구나 요청을 보내도 믿는 공개 API처럼 동작하게 됩니다.
운영 환경의 웹훅 소비자는 서명을 검증하고 이벤트를 영속적으로 기록한 뒤 2xx를 반환해야 합니다. 비용이 큰 작업은 비동기로 넘깁니다. 4xx는 수신 측 버그로 보고, 발신자의 재시도 때문에 중복 이벤트가 들어온다는 전제도 필요합니다.
429와 백오프 비교
Rate Limit Simulator는 제한된 API를 호출하는 클라이언트 입장에서 동작합니다. 백오프 없이 계속 요청하는 방식, 고정 지연, exponential backoff를 선택하고 성공 요청과 throttled 요청의 수를 비교합니다.
먼저 백오프 없이 실행하면 제한에 걸린 요청이 실패하면서 요청 예산을 소모합니다. 같은 트래픽으로 고정 지연과 지수 백오프를 비교하면 throttled 요청 수가 달라집니다. API가 Retry-After 헤더를 보내는 경우에는 서버가 재요청 시점을 직접 알려주는 셈이므로, 클라이언트가 임의로 만든 지연보다 우선해야 합니다. 다만 실제 API에서 이 헤더는 선택 사항입니다.
세 영역은 서로 다른 문제처럼 보이지만 같은 원리를 공유합니다. 큐는 lag와 backpressure로, 웹훅은 상태 코드와 서명으로, API 클라이언트는 429와 backoff로 상대방과 전달 속도와 신뢰를 조정합니다. producer가 lag를 무시하거나, 수신자가 이벤트를 영속적으로 저장하기 전에 성공을 알리거나, 클라이언트가 기다리지 않고 재시도하면 장애가 커집니다. 글에서는 세 시뮬레이터를 차례로 실행하면 정의만 읽을 때보다 전달 시스템의 실패 양상을 구체적으로 이해할 수 있다고 설명하며, 추가 참고 자료로 Kafka 설계 문서와 Stripe 웹훅 문서를 권합니다.
원문: dev.to / 번역·요약: Trawling