웹훅 완벽 가이드: 서명된 페이로드와 재시도 로직

Backend2026-10-28TryQuickToolBox

API를 구축했고 이제 이벤트가 발생할 때 다른 서비스에 알림을 보내야 합니다. 폴링은 비효율적이므로 웹훅을 사용하게 됩니다. 하지만 곧 웹훅이 실패할 수 있고, 위조될 수 있으며, 중복 처리를 유발할 수 있다는 것을 알게 됩니다. 이 글에서는 서명된 페이로드로 웹훅을 보호하고 견고한 재시도 로직을 구현하는 방법을 설명합니다.

웹훅이란?

웹훅은 사용자가 정의한 HTTP 콜백입니다. 시스템에서 이벤트가 발생하면(예: 결제 성공) 구독자가 제공한 URL로 HTTP POST 요청을 보냅니다. 페이로드는 일반적으로 JSON 또는 폼 형식의 이벤트 데이터를 포함합니다.

웹훅은 지속적인 폴링 없이 서비스 간 실시간 통신을 가능하게 합니다. 결제 게이트웨이, CI/CD 도구, SaaS 플랫폼에서 널리 사용됩니다.

웹훅 보안이 필요한 이유

보안이 없으면 웹훅 URL을 아는 사람이 가짜 요청을 보내 데이터 손상이나 사기를 초래할 수 있습니다. 또한 공격자가 이전 요청을 재생할 수도 있습니다. 공유 비밀로 페이로드에 서명하면 진위성과 무결성을 보장할 수 있습니다.

HMAC으로 페이로드 서명하기

HMAC(Hash-based Message Authentication Code)은 웹훅에 서명하는 일반적인 방법입니다. 송신자와 수신자는 비밀 키를 공유합니다. 송신자는 비밀 키를 사용하여 페이로드의 HMAC을 계산하고 헤더(예: X-Signature)에 포함합니다. 수신자는 HMAC을 다시 계산하여 비교합니다.

단계별: 서명된 웹훅 보내기

  1. 페이로드(JSON)를 생성합니다.
  2. 비밀 키를 사용하여 페이로드의 HMAC-SHA256을 계산합니다.
  3. 16진수 다이제스트를 헤더에 포함합니다. 예: X-Signature: sha256=...
  4. POST 요청을 보냅니다.
// Node.js 예제 (crypto 사용)
const crypto = require('crypto');
const secret = 'your_shared_secret';
const payload = JSON.stringify({ event: 'payment.success', amount: 100 });
const signature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
// X-Signature: sha256=signature 헤더와 함께 POST 전송

서명 검증하기

수신자 측에서는 서명 헤더를 추출하고, 원시 요청 본문의 HMAC을 계산한 후, 타이밍 공격을 방지하기 위해 상수 시간 비교를 사용하여 비교합니다.

// Express.js 예제
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const computed = crypto.createHmac('sha256', secret).update(req.rawBody).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(computed))) {
    return res.status(401).send('Invalid signature');
  }
  // 페이로드 처리
  res.status(200).send('OK');
});

참고: 파싱된 JSON이 아닌 원시 본문을 사용해야 합니다. 파싱 과정에서 페이로드가 변경될 수 있기 때문입니다.

재전송 공격 방지

서명된 페이로드에 타임스탬프를 포함하고 몇 분 이상 지난 요청은 거부합니다. 또한 고유한 이벤트 ID를 포함하고 처리된 ID를 저장하여 중복을 피합니다.

안정적인 전달을 위한 재시도 로직

웹훅 엔드포인트는 다운되거나 느릴 수 있습니다. 지수 백오프와 지터를 사용한 재시도를 구현하세요. 최대 재시도 횟수(예: 5회)와 각 요청에 대한 타임아웃을 설정합니다.

재시도 전략

재시도 일정 예시: 1차 재시도 5초 후, 2차 30초 후, 3차 2분 후, 4차 10분 후, 5차 1시간 후.

실패 처리

모든 재시도가 실패하면 실패를 기록하고 구독자에게 알립니다(예: 이메일 또는 대시보드를 통해). 수동으로 웹훅을 다시 보낼 수 있는 방법을 제공하세요.

비교: 서명된 페이로드 vs 기본 인증

방법 보안 복잡성 재전송 방지
HMAC 서명된 페이로드 높음 중간 예 (타임스탬프 포함)
기본 인증 낮음 낮음 아니오
헤더의 API 키 중간 낮음 아니오

모범 사례

자주 묻는 질문

웹훅 서명을 어떻게 검증하나요?

비밀 키를 사용하여 원시 요청 본문의 HMAC을 계산하고, 상수 시간 비교를 사용하여 서명 헤더와 비교합니다.

웹훅이 실패하면 어떻게 해야 하나요?

지수 백오프와 지터를 사용한 재시도를 구현하세요. 모든 재시도가 실패하면 실패를 기록하고 수동 재전송 옵션을 제공하세요.

서명 없이 웹훅을 사용할 수 있나요?

권장하지 않습니다. 서명이 없으면 발신자를 검증할 수 없어 시스템이 스푸핑 및 재전송 공격에 취약해집니다.

웹훅 페이로드를 테스트할 때 JSON 응답을 검사해야 할 수 있습니다. JSON Formatter를 사용하여 JSON 데이터를 빠르게 예쁘게 출력하고 검증하세요.