웹훅 완벽 가이드: 서명된 페이로드와 재시도 전략
방금 결제 게이트웨이나 CI/CD 서비스를 통합했고, 이제 실시간 이벤트를 받아야 합니다. 엔드포인트를 설정했지만 곧 두 가지 중요한 질문에 직면합니다: 요청이 실제로 해당 서비스에서 온 것인지 어떻게 확인할 수 있을까? 그리고 이벤트가 발생했을 때 서버가 다운되어 있으면 어떻게 될까? 이 글은 서명된 페이로드와 재시도 전략—신뢰할 수 있는 웹훅의 중추—을 설명하여 두 질문에 답합니다.
웹훅이란?
웹훅은 사용자 정의 HTTP 콜백입니다. 소스 시스템(예: 새로운 커밋, 결제 성공)에서 이벤트가 발생하면, 사용자가 제공한 URL로 HTTP POST 요청을 보냅니다. 폴링과 달리 웹훅은 거의 실시간으로 데이터를 푸시하여 지연 시간과 서버 부하를 줄입니다. 그러나 이 푸시 모델은 진위 확인과 전달 실패 처리라는 과제를 안고 있습니다.
서명된 페이로드가 중요한 이유
누구나 엔드포인트로 HTTP 요청을 보낼 수 있습니다. 검증 없이는 공격자가 이벤트를 위조하여 권한 없는 작업을 초래할 수 있습니다. 서명된 페이로드는 공유 비밀을 사용하여 요청 본문에 대해 계산된 암호화 서명을 포함함으로써 이를 해결합니다. 수신자는 서명을 다시 계산하고 비교하여 페이로드가 변조되지 않았고 예상 발신자로부터 왔음을 확인합니다.
HMAC 서명 작동 방식
대부분의 서비스는 HMAC-SHA256을 사용합니다. 발신자는 비밀 키로 페이로드를 해시하여 서명을 생성하고 이를 헤더(예: X-Signature)에 포함합니다. 수신자도 동일하게 수행하고 타이밍 공격을 방지하기 위해 상수 시간 함수를 사용하여 비교합니다.
단계별: 서명된 페이로드 검증
- 서명 추출 헤더(예:
X-Signature)에서 서명을 추출합니다. - 원시 요청 본문 가져오기 문자열이나 버퍼로 가져옵니다. 먼저 파싱하지 마세요. 형식 변경이 서명을 깨뜨립니다.
- 예상 서명 계산 비밀 키와 함께 HMAC-SHA256을 사용합니다.
- 서명 비교 상수 시간 비교 함수를 사용합니다.
- 요청 거부 일치하지 않으면 HTTP 401로 거부합니다.
다음은 Express를 사용한 Node.js 예제입니다:
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-signature'];
const secret = process.env.WEBHOOK_SECRET;
const payload = req.body; // raw buffer
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
// Process the event
const event = JSON.parse(payload);
// ... handle event
res.status(200).send('OK');
});
참고: 항상 원시 본문을 사용하여 검증하세요. JSON을 파싱하는 미들웨어는 페이로드를 변경하여 서명 불일치를 일으킵니다.
재시도 전략 설계
서명된 페이로드가 있더라도 네트워크 문제나 서버 다운타임으로 인해 전달 실패가 발생할 수 있습니다. 강력한 재시도 전략은 이벤트가 손실되지 않도록 보장합니다. 주요 고려 사항:
1. 빠르게 확인 응답
서명을 검증하고 이벤트를 처리 대기열에 넣은 즉시 2xx 상태로 응답하세요. 이렇게 하면 발신자가 시간 초과되어 불필요하게 재시도하는 것을 방지할 수 있습니다.
2. 멱등성
재시도는 동일한 이벤트를 여러 번 전달할 수 있습니다. 멱등성 키(종종 페이로드나 헤더에 포함됨)를 사용하여 중복을 제거하세요. 처리된 이벤트 ID를 저장하고 중복을 무시하세요.
3. 지터를 추가한 지수 백오프
엔드포인트가 오류(비 2xx)를 반환하면 발신자는 지연 시간을 늘려가며 재시도해야 합니다. 지수 백오프(예: 1초, 2초, 4초, 8초)는 장애 중 부하를 줄입니다. 무작위 지터를 추가하면 썬더링 허드 문제를 방지할 수 있습니다.
일반적인 재시도 일정:
| 시도 | 지연 |
|---|---|
| 1 | 즉시 |
| 2 | 1분 |
| 3 | 5분 |
| 4 | 30분 |
| 5 | 2시간 |
4. 데드 레터 큐
최대 재시도 후 이벤트를 수동 검사를 위해 데드 레터 큐로 이동하세요. 이렇게 하면 무한 재시도와 데이터 손실을 방지할 수 있습니다.
5. 모니터링 및 알림
전달 성공률, 지연 시간, 실패 이유를 추적하세요. 실패 급증에 대한 알림을 설정하여 문제를 조기에 감지하세요.
일반적인 함정과 모범 사례
- 항상 서명을 검증하세요—들어오는 데이터를 맹목적으로 신뢰하지 마세요.
- HTTPS를 사용하세요 전송 중 페이로드를 보호합니다.
- 비밀을 주기적으로 교체하세요 교체 중에는 여러 활성 비밀을 지원하세요.
- 웹훅 이벤트를 기록하세요 (민감한 데이터는 삭제) 디버깅을 위해.
- 샘플 페이로드로 테스트하세요 웹훅 전달을 시뮬레이션하는 도구를 사용하여.
FAQ
웹훅에서 서명된 페이로드란 무엇인가요?
서명된 페이로드는 수신자가 요청의 진위와 무결성을 확인할 수 있도록 하는 암호화 서명(보통 HMAC)을 포함합니다.
웹훅은 몇 번 재시도해야 하나요?
고정된 숫자는 없습니다. 일반적인 관행은 지수 백오프를 사용하여 3~10회 재시도입니다. 그 후 이벤트는 종종 데드 레터 큐로 전송됩니다.
서명 없이 웹훅을 사용할 수 있나요?
가능하지만 강력히 권장하지 않습니다. 서명이 없으면 엔드포인트가 위조 요청과 데이터 유출에 취약해집니다.
웹훅 페이로드를 테스트할 준비가 되셨나요? JSON Formatter를 사용하여 JSON 페이로드를 빠르게 검사하고 검증하세요.