웹훅 연동 방법 3단계, 놓치기 쉬운 보안 체크
- 웹훅은 이벤트 발생 시 서버가 먼저 알려주는 방식으로 API 폴링보다 실시간성이 높습니다.
- 연동은 엔드포인트 생성, URL·시크릿 등록, 서명 검증의 3단계로 진행합니다.
- 서명 검증 없이 URL만 노출하면 위조 요청에 그대로 노출될 수 있습니다.
- 재시도·멱등성 처리를 해두지 않으면 중복 이벤트로 데이터가 꼬일 수 있습니다.
웹훅(Webhook)이란? API 폴링과 뭐가 다른가

웹훅(Webhook)은 특정 이벤트가 발생했을 때 발신 서비스가 미리 등록해둔 URL로 HTTP POST 요청을 즉시 보내는 방식입니다. 예를 들어 GitHub 저장소에 코드를 push하면 GitHub 서버가 그 순간 여러분의 서버로 ‘방금 push가 있었다’는 데이터(페이로드, payload)를 바로 던져줍니다. 반대로 ‘주기적으로 서버에 물어보는’ API 폴링(polling)과 정반대 구조라서, 웹훅을 흔히 ‘콜백(callback) 방식 통신’이라고도 부릅니다.
API 폴링과의 차이
폴링은 클라이언트가 1분마다, 혹은 10초마다 “새 소식 있어?”라고 서버에 반복 요청하는 방식입니다. 구현은 단순하지만 이벤트가 없어도 요청이 계속 나가 서버 자원과 API 호출 한도(rate limit)를 낭비합니다. 웹훅은 이벤트가 실제로 발생했을 때만 통신이 일어나므로 실시간성이 높고 불필요한 요청이 없지만, 수신 측 서버가 항상 요청을 받을 수 있는 상태(공개 URL, 24시간 가동)여야 한다는 전제 조건이 붙습니다.
웹훅이 쓰이는 대표 사례
결제가 완료됐을 때 결제 대행사가 주문 상태를 알려주는 경우, GitHub·GitLab에 코드가 push됐을 때 CI/CD 파이프라인을 자동으로 트리거하는 경우, 고객 문의가 접수됐을 때 Slack이나 Discord 채널로 알림을 보내는 경우가 대표적입니다. 이 글에서는 개발 경험이 많지 않아도 따라 할 수 있도록 가장 기본적인 ‘수신 서버 만들기 → 등록 → 검증’ 흐름을 중심으로 설명합니다.
연동 전에 반드시 확인해야 할 것들
웹훅 연동에서 실수가 잦은 지점은 코드 자체보다 사전 준비입니다. 아래 항목을 먼저 점검하면 이후 단계에서 헤매는 시간을 크게 줄일 수 있습니다.
- 수신 서버가 외부에서 접근 가능한 공개 URL을 가지고 있는지 (로컬 PC의 localhost는 그대로 등록할 수 없습니다)
- 발신 서비스 문서에서 페이로드 형식(JSON인지 form-urlencoded인지)과 이벤트 종류를 미리 확인했는지
- 서명 검증에 쓸 시크릿(secret) 키 발급 방법을 파악했는지
- 실패 시 재시도 정책(몇 번, 몇 초 간격으로 재전송하는지)이 문서에 안내돼 있는지
로컬 개발 환경에서 테스트하려면 ngrok, localtunnel 같은 터널링 도구로 임시 공개 URL을 만들거나, webhook.site 같은 무료 웹훅 확인 도구로 페이로드 구조부터 눈으로 확인하는 것이 안전합니다.
웹훅 연동 방법 3단계

플랫폼마다 화면 구성은 다르지만, 실제 연동 절차는 아래 3단계로 거의 동일합니다.
1단계: 웹훅을 받을 엔드포인트(URL) 만들기
- 서버 애플리케이션에 POST 요청만 받는 별도 경로를 하나 만듭니다(예:
/webhook/github). - 요청이 들어오면 본문(body)을 파싱해 로그로 남기거나 DB에 임시 저장하도록 구현합니다.
- 처리 로직과 관계없이 요청을 받자마자 HTTP 200 응답을 먼저 반환하도록 설계합니다. 무거운 처리는 응답 후 별도 큐나 백그라운드 작업으로 넘기는 것이 안전합니다.
2단계: 발신 서비스에 웹훅 URL과 시크릿 등록하기
- 발신 서비스(예: GitHub 저장소 Settings → Webhooks, Discord 채널 설정 → 연동 → 웹후크)로 이동합니다.
- 1단계에서 만든 공개 URL을 Payload URL 항목에 입력합니다.
- 이벤트 발생 시 위조를 막기 위한 Secret 값을 생성해 저장하고, 어떤 이벤트(push, issue, 결제완료 등)에서 웹훅을 보낼지 선택합니다.
- 저장 후 대부분의 서비스가 제공하는 테스트 전송(ping/test delivery) 버튼으로 연결 상태를 즉시 확인합니다.
3단계: 서명 검증 로직 추가하고 실제 이벤트로 테스트하기
- 요청 헤더에 담겨 오는 서명 값(예: GitHub의
X-Hub-Signature-256)을 읽습니다. - 등록해둔 시크릿 키로 요청 본문을 HMAC(암호학적 해시 기반 서명 검증 방식) 알고리즘으로 직접 계산합니다.
- 계산한 값과 헤더의 서명 값이 일치할 때만 정상 이벤트로 처리하고, 불일치하면 401 등으로 거부합니다.
- 실제로 코드를 push하거나 결제를 시도하는 등 실제 이벤트를 한 번 발생시켜 로그에 정상 도착하는지 최종 확인합니다.
서명 검증을 생략하고 URL만 등록하면, 그 URL을 알아낸 누구나 가짜 페이로드를 보내 여러분의 시스템을 조작할 수 있습니다. 테스트 단계라도 시크릿 발급과 서명 검증은 건너뛰지 않는 것이 안전합니다.
보안 체크포인트
서명 검증(HMAC)과 HTTPS
웹훅 URL은 인증 로그인 절차 없이 아는 사람은 누구나 요청을 보낼 수 있는 구조입니다. 그래서 서명 검증이 사실상 유일한 방어선입니다. HMAC 서명 검증에 더해, URL은 반드시 HTTP가 아닌 HTTPS로 등록하고, 가능하다면 발신 서비스가 공개한 IP 대역만 허용하는 방화벽 규칙(IP allowlist)을 추가로 걸어두면 이중 방어가 됩니다.
재전송(재시도)과 멱등성 처리
일반적으로 웹훅 발신 서비스는 수신 서버가 정해진 시간 안에 200번대 응답을 하지 않으면 같은 이벤트를 여러 차례 재전송합니다. 네트워크 지연이나 서버 재시작 등으로 같은 이벤트가 중복 도착할 수 있다는 뜻입니다. 이벤트 고유 ID를 저장해두고 이미 처리한 ID면 다시 처리하지 않는 멱등성(idempotency, 같은 요청을 여러 번 받아도 결과가 달라지지 않도록 하는 처리) 로직을 넣어야 중복 결제 반영이나 중복 알림 같은 사고를 막을 수 있습니다.
- 주요 플랫폼별 웹훅 설정 위치: GitHub·GitLab은 저장소 Settings → Webhooks, Discord는 채널 설정 → 연동, Slack은 App 설정의 Incoming Webhooks, Stripe 등 결제 서비스는 대시보드의 Developers → Webhooks 메뉴에 있습니다.
자주 발생하는 오류와 해결법

웹훅 연동 중 마주치는 오류는 몇 가지 패턴으로 반복됩니다. 아래 표로 원인과 해결 방향을 정리했습니다.
| 증상 | 주로 발생하는 원인 | 해결 방법 |
|---|---|---|
| 401/403 오류 | 서명 검증 로직 불일치, 시크릿 키 오타 | 헤더 서명값과 서버에서 계산한 값을 로그로 직접 비교해 확인 |
| 408/타임아웃 | 응답 전에 무거운 처리를 먼저 수행 | 요청을 받자마자 200 먼저 응답, 실제 처리는 비동기로 분리 |
| 웹훅이 아예 도착하지 않음 | URL이 로컬 주소이거나 방화벽에 막힘 | ngrok 등 터널링으로 공개 URL 확인, 방화벽 인바운드 규칙 점검 |
| 같은 이벤트 중복 수신 | 발신 서비스의 정상적인 재시도 동작 | 이벤트 ID 저장 후 중복 여부 확인하는 멱등성 처리 추가 |
수신 서버를 둘 위치 자체가 아직 정해지지 않았다면 웹호스팅 종류 비교, 내 서비스엔 뭐가 맞을까 글을 참고해 상시 가동이 가능한 환경인지부터 확인하는 것이 좋습니다.
자주 묻는 질문
Q. 웹훅과 API는 완전히 다른 개념인가요?
웹훅도 결국 HTTP 요청을 주고받는 API 통신의 한 형태입니다. 차이는 방향성인데, 일반 API는 클라이언트가 요청을 시작하고, 웹훅은 이벤트가 발생한 서버가 먼저 요청을 시작한다는 점이 다릅니다.
Q. 로컬 컴퓨터에서도 웹훅을 테스트할 수 있나요?
가능합니다. localhost 주소는 외부에서 접근할 수 없으므로 ngrok, localtunnel 같은 터널링 도구로 임시 공개 URL을 발급받아 그 주소를 발신 서비스에 등록하면 로컬 환경에서도 실제 이벤트를 받아볼 수 있습니다.
Q. 서명 검증을 꼭 해야 하나요? 내부용이라 괜찮지 않나요?
내부용이라도 웹훅 URL이 외부에 노출되면 방어 수단이 사실상 없는 상태가 됩니다. 서명 검증은 구현 비용이 크지 않으므로, 사용량이 적은 프로젝트라도 처음부터 넣어두는 것을 권장합니다.
Q. 재시도가 계속 실패하면 이벤트를 영영 놓치게 되나요?
발신 서비스마다 재시도 횟수와 기간에 한도가 있어, 그 한도를 넘기면 더 이상 재전송하지 않습니다. 대부분의 서비스는 대시보드에서 실패한 웹훅 전송 이력과 응답 코드를 확인하고 수동으로 재전송하는 기능을 제공하므로, 이 로그를 주기적으로 확인하는 습관이 필요합니다.
Q. 여러 서비스의 웹훅을 한 서버에서 같이 받아도 되나요?
가능합니다. 다만 서비스별로 페이로드 형식과 서명 방식이 다르므로, 서비스마다 별도의 엔드포인트 경로를 만들고 검증 로직도 각각 분리해서 작성하는 편이 오류 추적에 유리합니다.
