왜 웹훅 재시도 로직(Webhook Retry Logic)이 계속 당신을 실망시키는지 — 그리고 에이전트가 주소를 가질 때 이를 대체할 것은
요약
웹훅(Webhook) 방식의 재시도 로직이 가진 멱등성, 순서 보장, 데드 레터 큐, 배압 관리 등의 기술적 한계와 복잡성을 분석합니다. 수동적인 엔드포인트 방식 대신 에이전트 중심의 새로운 통신 패러다임의 필요성을 시사합니다.
핵심 포인트
- 웹훅 재시도는 멱등성 관리를 위한 추가적인 데이터베이스 및 로직 비용을 발생시킴
- 재시도 과정에서 이벤트의 순서(Ordering)가 보장되지 않아 미묘한 버그 유발 가능
- 데드 레터 큐(DLQ) 관리를 위한 별도의 모니터링 및 수동 작업이 필수적임
- 수신자가 처리 속도를 조절할 수 없는 배압(Backpressure) 문제 존재
- 고정 주소가 없는 에이전트 환경에서는 기존 웹훅 방식이 한계를 가짐
모두가 하는 가정은 웹훅(webhook)이 유일한 옵션이라는 것입니다. 즉, 이벤트를 푸시하고 수신자가 이를 포착하기를 바라는 것이죠. 하지만 그 가정은 아무도 유지보수하고 싶어 하지 않는 수 주 분량의 코드 속에 조용히 박혀버리게 됩니다.
웹훅 전달 보장(Webhook Delivery Guarantees)의 실제 모습
전형적인 웹훅 송신자는 서류상으로는 안심이 되는 재시도 정책(retry policy)을 발표합니다:
— 시도 1: 즉시
— 시도 2: 10초 후
— 시도 3: 1분 후
— 시도 4: 10분 후
— ...N번의 재시도까지 지수 백오프 (exponential backoff)
— 모두 실패할 경우 데드 레터 큐 (Dead letter queue)
이것은 실제로는 최소 한 번 전달(at-least-once delivery) 방식입니다. 모든 재시도는 경주와 같습니다. 수신자의 엔드포인트(endpoint)에 일시적으로 접근할 수 없거나, 배포(deployment)가 진행 중이거나, DNS 레코드가 전파되지 않았을 수 있습니다. 송신자는 일시적인 오류와 영구적인 실패를 구분할 수 없으므로, 계속해서 재시도를 반복합니다.
숨겨진 복잡성
그러한 재시도 계약은 수신자에게 네 가지 문제를 떠넘깁니다:
멱등성 (Idempotency). 모든 이벤트에는 고유한 멱등성 키(idempotency key)가 포함됩니다. 수신자는 자신이 확인한 모든 키를 추적하고 중복된 것은 조용히 폐기해야 합니다. 이는 데이터베이스 테이블, 만료 정책, 그리고 동일한 결제나 웹훅을 실수로 두 번 처리할 수 없는 코드 경로를 의미합니다.
순서(Ordering)는 거짓말입니다. 웹훅 재시도는 순서를 보장하지 않습니다. 만약 이벤트 B가 즉시 사용 가능했다면, 이벤트 A의 두 번째 시도가 이벤트 B의 첫 번째 시도보다 나중에 도착할 수 있습니다. 이벤트가 순차적으로 도착한다고 가정했던 수신자들은 몇 달 뒤에 나타나는 미묘한 버그를 겪게 됩니다.
데드 레터 큐(Dead letter queues)는 모니터링이 필요합니다. 모든 재시도를 소진한 이벤트는 데드 레터 큐에 쌓입니다. 누군가는 그 큐를 확인하고, 이벤트를 다시 재생(replay)하며, 진정으로 성공할 수 없는 것들을 처리해야 합니다. 이것은 '던져두면 끝나는(fire-and-forget)' 시스템이 아니라 별도의 작업이 필요한 일입니다.
배압 (Backpressure)은 보이지 않습니다. 수신자가 느리게 처리하고 있다면, 송신자의 재시도는 계속해서 쌓이게 됩니다. 수신자는 "잠시만요, 따라잡고 있어요"라고 말할 방법이 없습니다. 각 재시도는 이미 과부하가 걸린 시스템에 압박을 더합니다.
이 중 그 어떤 것도 초기 통합 단계에서는 보이지 않습니다. 이는 운영 환경(production)에서, 즉 웹훅 폭풍(webhook storm)이 몰아치고 멱등성 테이블(idempotency table)이 정리 작업(cleanup job)이 실행되는 속도보다 더 빠르게 차오르는 새벽 시간에 표면화됩니다.
근본적인 가정 (The Root Assumption)
이 모든 문제들은 동일한 근본 원인으로 거슬러 올라갑니다. 바로 웹훅 수신자(webhook receiver)가 수동적인 엔드포인트(passive endpoint)라는 점입니다. 수신자는 특정 URL에 자리 잡고 송신자가 자신에게 도달할 수 있기를 바랄 뿐입니다. 송신자가 타이밍, 재시도(retries), 순서(ordering)를 제어하며, 수신자는 오직 도착하는 것에 대해서만 응답합니다.
서버가 고정 IP를 가지고 방화벽이 예외적이었던 세상에서는 이것이 타당했습니다. 하지만 노트북에서 실행되는 에이전트, CI 러너(CI runners), 로드 밸런서(load balancers)가 없는 컨테이너, 그리고 엣지 디바이스(edge devices)는 영구적인 주소를 가지고 있지 않습니다. 이들은 정의상 도달할 수 없는(unreachable) 존재입니다. 송신자의 재시도 로직(retry logic)은 해결책이 아니라, 이러한 상황의 결과물일 뿐입니다.
피어(Peer)가 주소 지정 가능해질 때 변하는 것
모델을 뒤집어 봅시다. 송신자가 존재하기를 바라는 엔드포인트로 데이터를 푸시(push)하는 대신, 수신자가 네트워크상에서 직접 도달 가능한 상태가 됩니다. 수신자는 재시작, 네트워크 변경, 클라우드 마이그레이션(cloud migrations) 중에도 유지되는 영구적인 주소를 가집니다. 송신자는 지수 백오프(exponential backoff)가 필요하지 않습니다. 대신 알려진 주소로 메시지를 보내기만 하면 됩니다.
지속적인 터널 오버레이(persistent tunnel overlay)는 모든 에이전트를 일급 피어(first-class peer)로 변모시킵니다. 데몬(daemon)이 아웃바운드 연결(outbound connection)을 시작하고(어떠한 NAT 뒤에서도 작동함), 안정적인 주소를 등록하며, 암호화된 터널을 유지합니다. 메시지는 에이전트의 핸들러(handler)로 타입화된 페이로드(typed payloads)로서 도착합니다. HTTP 엔드포인트도, 웹훅 설정도, 협상해야 할 재시도 정책(retry policy)도 필요 없습니다.
from pilotprotocol import PilotNode
node = PilotNode()
...
멱등성 키(idempotency keys)도 필요 없습니다. 데드 레터 큐(dead letter queue)도 필요 없습니다. 애플리케이션이 아닌 전송 계층(transport)이 전달을 처리합니다. 수신자가 오프라인 상태라면 메시지는 네트워크에 보관되었다가 수신자가 다시 연결될 때 전달됩니다. 송신자는 한 번만 보내고 다음 작업으로 넘어갑니다.
이는 추상적인 이야기가 아닙니다. 이를 가능하게 하는 데몬을 실행하는 명령은 단 하나입니다:
curl -fsSL https://pilotprotocol.network/install.sh | sh
pilotctl daemon start # 에이전트가 영구 주소를 할당받습니다
유지되는 것 vs 변화하는 것
웹훅 (Webhook) 모델은 한 가지 측면에서 탁월합니다. 바로 송신자가 이벤트를 '발사 후 망각 (fire-and-forget)' 방식으로 보낼 수 있게 해준다는 점입니다. 재시도 정책 (Retry policies)은 이 '발사 후 망각' 방식을 신뢰할 수 있게 만들려고 시도하지만, 이는 원인이 아닌 증상 — 즉, 도달할 수 없는 엔드포인트 (endpoints) — 을 처리하는 것에 불과합니다.
직접 주소 지정 (Direct addressability)을 사용하면 다음과 같습니다:
- 유지되는 것: 이벤트 기반 아키텍처 (event-driven architecture). 이벤트는 여전히 동작을 트리거합니다. 차이점은 전송 (transport) 계층이 기본적으로 신뢰할 수 있다는 것입니다.
- 유지되는 것: 비동기 통신 (asynchronous communication). 송신자는 차단 (block)되지 않습니다. 이벤트를 발송하고 계속 진행합니다.
- 사라지는 것: 멱등성 (idempotency) 처리. 중복 탐지 코드가 필요 없습니다. 키 만료 (key-expiration) 작업도 필요 없습니다.
- 사라지는 것: 지수 백오프 (exponential backoff) 설정.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기