웹훅 완벽 가이드: 서명된 페이로드와 재시도
웹훅이 강력하면서도 취약한 이유
웹훅은 실시간 통합을 가능하게 합니다: 결제 알림, CI/CD 트리거, 채팅 메시지 등. 하지만 두 가지 큰 과제가 있습니다: 보안(요청이 예상된 발신자로부터 온 것인지 어떻게 알 수 있을까?)과 신뢰성(수신자가 다운되면 어떻게 할까?). 이 글에서는 서명된 페이로드와 재시도 전략으로 두 문제를 모두 해결하는 방법을 보여줍니다.
웹훅이란 무엇인가?
웹훅은 이벤트가 발생했을 때 제공자가 소비자에게 보내는 HTTP POST 요청입니다. 폴링과 달리 웹훅은 거의 실시간으로 데이터를 푸시하여 지연 시간과 서버 부하를 줄입니다. 제공자는 요청이 진본임을 보장해야 하고, 소비자는 이를 안정적으로 처리해야 합니다.
서명된 페이로드로 웹훅 보호하기
서명된 페이로드는 비밀 키를 사용하여 요청 본문의 암호화 서명(보통 HMAC-SHA256)을 생성합니다. 수신자는 서명을 다시 계산하고 헤더에 있는 것과 비교합니다. 일치하면 페이로드는 진본이며 변조되지 않았습니다.
서명 생성 및 검증 방법
일반적인 흐름은 다음과 같습니다:
- 제공자와 소비자가 비밀 키를 공유합니다(예: 대시보드를 통해).
- 제공자가
HMAC-SHA256(secret, payload)를 계산하여X-Signature와 같은 헤더에 담아 보냅니다. - 소비자가 원시 본문을 읽고 동일한 HMAC을 계산한 후 상수 시간 함수를 사용하여 비교합니다.
Node.js 예제:
const crypto = require('crypto');
function verifySignature(secret, payload, signature) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(payload);
const digest = hmac.digest('hex');
return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signature));
}
타이밍 공격을 방지하려면 항상 상수 시간 비교를 사용하세요. 검증 전에 본문을 파싱하지 말고 원시 본문 미들웨어를 사용하세요.
안정적인 전달을 위한 재시도 구현
서명이 있어도 네트워크 장애나 일시적인 중단으로 웹훅 전달이 실패할 수 있습니다. 견고한 재시도 메커니즘은 최종 전달을 보장합니다.
재시도 전략
- 지수 백오프: 각 재시도 사이에 더 오래 기다립니다(예: 1초, 2초, 4초, 8초).
- 최대 시도 횟수: 무한 루프를 방지하기 위해 재시도를 제한합니다(예: 5회).
- 데드 레터 큐: 최대 시도 후 이벤트를 수동 검사를 위해 저장합니다.
- 멱등성: 소비자가 중복을 무시할 수 있도록 고유 이벤트 ID를 포함합니다.
Python 재시도 로직 예제:
import time
import requests
def send_webhook(url, payload, max_retries=5):
for attempt in range(max_retries):
try:
response = requests.post(url, json=payload, timeout=5)
if response.status_code == 200:
return True
except requests.RequestException:
pass
time.sleep(2 ** attempt) # exponential backoff
return False
웹훅 소비자를 위한 모범 사례
- 빠르게 2xx로 응답하고, 필요하면 비동기로 처리하세요.
- 어떤 처리 전에 서명을 검증하세요.
- 멱등성 키를 사용하여 중복 전달을 처리하세요.
- 디버깅을 위해 모든 수신 웹훅을 로그로 남기세요.
- 실패를 모니터링하고 반복 오류에 대해 알림을 설정하세요.
비교: 폴링 vs 웹훅
| 측면 | 폴링 | 웹훅 |
|---|---|---|
| 지연 시간 | 높음(간격 기반) | 낮음(실시간) |
| 서버 부하 | 지속적인 요청 | 이벤트 발생 시에만 |
| 복잡성 | 단순함 | 재시도/보안 필요 |
| 사용 사례 | 소규모, 드문 업데이트 | 실시간 통합 |
FAQ
서명된 웹훅 페이로드란 무엇인가요?
서명된 페이로드는 수신자가 요청이 신뢰할 수 있는 출처에서 왔고 변조되지 않았음을 확인할 수 있게 해주는 암호화 서명(예: HMAC)을 포함합니다.
실패한 웹훅을 몇 번 재시도해야 하나요?
보편적인 숫자는 없지만 지수 백오프를 사용한 3~5회 시도가 일반적입니다. 그 후에는 수동 검토를 위해 이벤트를 로그로 남기세요.
웹훅 서명에 HMAC 대신 JWT를 사용할 수 있나요?
네, 일부 제공자는 JWT를 사용합니다. 원리는 동일합니다: 페이로드를 신뢰하기 전에 토큰의 서명과 클레임을 검증하세요.
웹훅 페이로드나 로그를 검사해야 하나요? JSON Formatter를 사용하여 JSON 페이로드를 빠르게 예쁘게 출력하고 검증해 보세요.