업데이트됨 1개월 전
폴링은 장거리 자동차 여행 중 5분마다 "다 왔어요?"라고 묻는 것과 같습니다. 웹훅은 친구가 도착했을 때 문자를 보내주는 것과 같습니다.
핵심은 이겁니다. 애플리케이션이 서비스에 "뭔가 바뀐 게 있나요?"라고 반복해서 묻는 대신, 서비스가 무언가 변경되는 즉시 알려줍니다. URL을 등록해두면 이벤트가 발생할 때 서비스가 데이터를 직접 전송합니다.
이처럼 사소해 보이는 역할의 전환—누가 기다리느냐의 문제—이 모든 것을 바꿉니다.
웹훅 패턴
세 단계로 이루어집니다:
등록. 서비스에 URL을 제공합니다: https://yourdomain.com/webhooks/payment-received. 서비스는 이를 저장합니다.
이벤트 발생. 무언가가 일어납니다—결제가 완료되거나, 사용자가 가입하거나, 파일 처리가 끝납니다.
전달. 서비스가 즉시 여러분의 URL로 JSON 페이로드를 POST합니다. 처리 후 HTTP 200으로 응답합니다.
이게 전부입니다. 폴링 루프도 없고, 낭비되는 요청도 없으며, 불필요한 지연도 없습니다.
왜 중요한가
폴링은 응답성과 효율성 사이에서 선택을 강요합니다. 매초 폴링하면? 대부분 아무것도 반환하지 않는 요청으로 API를 혹사시킵니다. 매분 폴링하면? 최대 59초까지 시간에 민감한 이벤트를 놓칠 수 있습니다.
웹훅은 이 트레이드오프를 없앱니다. 이벤트는 발생하는 즉시 도착합니다. 실제로 처리할 내용이 있을 때만 요청을 받습니다. 변경 사항을 감시하는 부담은 서비스가 집니다—여러분이 아니라.
단, 다음이 필요합니다: 들어오는 요청을 수락하는 엔드포인트를 호스팅하고, 전달 실패를 처리하며, 악용으로부터 엔드포인트를 보호해야 합니다.
웹훅의 구조
일반적인 웹훅 페이로드:
이벤트 유형은 무슨 일이 일어났는지 알려줍니다. ID는 중복을 감지할 수 있게 합니다. 타임스탬프는 언제 발생했는지 알려줍니다. 데이터에는 해당 이벤트와 관련된 모든 정보가 담겨 있습니다.
서비스는 같은 URL로 여러 유형의 이벤트를 전송합니다—payment.completed, payment.failed, payment.refunded—따라서 핸들러는 이벤트 유형에 따라 라우팅합니다.
보안: 서명되지 않은 웹훅의 위험
위험은 이렇습니다: 웹훅 URL은 그냥 URL에 불과합니다. 이를 발견한 누구든 가짜 이벤트를 전송할 수 있습니다. 검증 없이는 공격자가 가짜 payment.completed 이벤트를 POST해 실제로 결제되지 않은 주문을 처리하도록 시스템을 속일 수 있습니다.
서비스는 서명으로 이 문제를 해결합니다. 여러분과 서비스만 아는 비밀 키를 사용해 각 웹훅 페이로드에 서명합니다. 애플리케이션은 페이로드를 신뢰하기 전에 서명을 검증합니다:
서명되지 않은 웹훅은 절대 처리하지 마세요. 또한: HTTPS를 사용하고(일반 HTTP로 웹훅을 수락하지 마세요), 재전송 공격을 방지하기 위해 타임스탬프를 확인하고, 처리 전에 페이로드 구조를 검증하며, 속도 제한을 구현하세요.
속도의 함정
웹훅 핸들러에는 시간 제한이 있습니다—보통 몇 초입니다. 엔드포인트가 빠르게 응답하지 않으면 서비스는 전달이 실패했다고 판단하고 재시도합니다.
흔한 실수: 웹훅 핸들러에서 실제 작업을 처리하는 것입니다. 결제 처리, 이메일 발송, 데이터베이스 업데이트—이 모든 것은 시간이 걸립니다. 동기적으로 처리하면 타임아웃이 발생합니다.
올바른 패턴: 즉시 수신 확인을 하고, 처리는 나중에 합니다.
엔드포인트는 빠른 중계자 역할을 합니다: 검증, 큐 추가, 수신 확인. 실제 처리는 비동기적으로 이루어집니다.
중복 문제
서비스는 실패한 웹훅을 재시도합니다. 네트워크가 불안정할 수 있습니다. 동일한 웹훅이 두 번 이상 도착하는 경우가 있습니다.
핸들러가 받은 모든 웹훅을 처리하면, 같은 주문을 두 번 처리하거나, 중복 이메일을 발송하거나, 데이터를 손상시킬 수 있습니다.
해결책은 멱등성(idempotency)입니다: 같은 이벤트로 여러 번 호출되어도 안전한 핸들러를 만드는 것입니다.
이벤트 ID가 핵심입니다. 이미 처리했는지 확인합니다. 있으면 건너뜁니다. 없으면 처리하고 기록합니다.
서비스 없이 테스트하기
웹훅은 테스트하기 까다롭습니다. 트리거하려면 외부 서비스가 필요하고, 그 서비스는 여러분의 엔드포인트에 도달할 수 있어야 합니다.
개발 중에는 로컬호스트가 인터넷에서 접근할 수 없습니다. ngrok 같은 도구로 이 문제를 해결합니다:
이렇게 하면 공개 URL(예: https://abc123.ngrok.io)이 생성되어 로컬 서버로 터널링됩니다. 이 URL에 서비스의 웹훅 설정을 지정하면 웹훅이 개발 머신으로 전달됩니다.
자동화된 테스트를 위해서는 웹훅을 목(mock)으로 처리합니다:
대부분의 서비스는 대시보드에서 웹훅 시뮬레이터도 제공합니다—등록된 URL로 테스트 이벤트를 보내는 버튼입니다.
웹훅이 사용되는 곳
결제 처리 서비스 (Stripe, PayPal)는 결제가 완료, 실패, 환불될 때 알려줍니다. 주문 상태를 업데이트하고 즉시 구매를 처리합니다.
코드 저장소 (GitHub, GitLab)는 푸시, 풀 리퀘스트, 이슈에 대해 알려줍니다. CI/CD 파이프라인이 이 웹훅에 의해 트리거됩니다.
커뮤니케이션 서비스 (Twilio, SendGrid)는 메시지 전달, 수신 SMS, 이메일 열람 및 클릭에 대해 알려줍니다.
파일 처리 서비스는 업로드 처리가 완료되거나, 썸네일이 생성되거나, 동영상 트랜스코딩이 끝날 때 알려줍니다.
모니터링 시스템은 서버 다운, 오류율 급증, 임계값 초과 시 알림을 전송합니다.
다른 사람을 위한 웹훅 구축
서비스에서 웹훅을 제공한다면:
모든 것에 서명하세요. 수신자가 진위를 확인할 수 있도록 HMAC 서명을 사용하세요.
백오프로 재시도하세요. 전달이 실패하면 점점 늘어나는 간격으로 재시도하세요—1분, 5분, 30분. 수신자가 일시적인 문제에서 복구할 시간을 주세요.
가시성을 제공하세요. 대시보드에서 전달 시도, 응답, 실패를 표시하세요. 사용자가 테스트 웹훅을 트리거할 수 있게 하세요.
지속적인 실패를 방치하지 마세요. URL이 반복적으로 실패하면 비활성화하고, 죽은 엔드포인트를 계속 호출하는 대신 사용자에게 알리세요.
철저하게 문서화하세요. 페이로드 스키마, 이벤트 유형, 재시도 정책, 서명 검증 코드—수신자가 올바르게 연동하는 데 필요한 모든 것을 제공하세요.
웹훅 vs. 대안들
**서버 전송 이벤트(Server-Sent Events, SSE)**는 서버에서 클라이언트로의 업데이트를 위해 열린 연결을 유지합니다. 브라우저에 적합하지만 지속적인 연결이 필요합니다.
**웹소켓(WebSockets)**은 양방향 실시간 통신을 제공합니다. 더 복잡하지만 양방향 메시징이 가능합니다.
메시지 큐 (RabbitMQ, AWS SQS)는 신뢰할 수 있는 비동기 메시징을 제공합니다. 더 많은 인프라가 필요하지만 더 많은 보장을 제공합니다.
폴링은 웹훅을 사용할 수 없거나, 업데이트가 드물거나, 엔드포인트를 호스팅할 수 없는 경우에 여전히 적합합니다.
웹훅이 계속 쓰이는 이유는 단순함 때문입니다: 표준 HTTP, 무상태, 방화벽을 통해 작동하며, 최소한의 인프라가 필요합니다. 대부분의 이벤트 알림 요구에는 웹훅이 올바른 선택입니다.
웹훅에 관한 자주 묻는 질문
웹훅 엔드포인트가 다운되면 어떻게 되나요?
서비스는 지수 백오프 방식으로 실패한 전달을 재시도합니다—보통 1분, 5분, 30분 간격으로 재시도하며, 24~72시간 후에 포기합니다. 엔드포인트와 서비스의 웹훅 대시보드에서 실패를 모니터링하세요. 일부 서비스는 누락된 이벤트를 수동으로 다시 트리거할 수 있습니다.
웹훅이 진짜인지 공격자가 보낸 것인지 어떻게 알 수 있나요?
서명을 검증하세요. 서비스는 여러분과 서비스 사이에서만 공유되는 비밀 키를 사용해 웹훅 페이로드에 서명합니다. 엔드포인트는 페이로드로부터 예상 서명을 계산하고 요청 헤더의 서명과 비교합니다. 일치하면 해당 웹훅은 신뢰할 수 있습니다.
개발 중에 로컬호스트에서 웹훅을 받을 수 있나요?
직접은 불가능합니다—로컬호스트는 인터넷에서 접근할 수 없습니다. ngrok 같은 터널링 도구를 사용하면 로컬 서버로 요청을 전달하는 공개 URL이 생성됩니다. 서비스의 웹훅 설정을 ngrok URL로 지정하세요.
왜 같은 웹훅을 여러 번 받는 건가요?
서비스는 실패 시 재시도하며, 네트워크 문제로 중복 전달이 발생할 수 있습니다. 멱등성을 구현하세요: 처리된 이벤트 ID를 추적하고 이미 처리한 이벤트는 건너뜁니다. 이렇게 하면 동일한 웹훅이 몇 번 도착하더라도 핸들러가 안전하게 동작합니다.
이 페이지가 도움이 되었나요?