웹훅(WebHook) 연동 가이드
웹훅(WebHook) 연동 가이드
쇼핑몰에서 주문, 상품, 게시판 등의 이벤트가 발생하면 등록한 URL로 이벤트 정보를 바로 전달받을 수 있습니다. 웹훅 등록 방법과 수신 조건, 메시지 형식, 제공 이벤트 목록을 안내합니다.
- 웹훅은 통합옵션 · 주문2.0 · UTF-8 쇼핑몰에서만 지원됩니다.
- APP에 등록된 API 권한에 해당하는 이벤트만 수신할 수 있습니다.
- 쇼핑몰 운영자가 APP 설치 시 웹훅 정보 제공에 동의해야 이벤트가 전송됩니다.
- 서비스 이용에 필수적인 웹훅만 등록해 주세요. 수신한 정보의 관리 및 이용에 대한 책임은 파트너에게 있습니다.
웹훅 동작 방식
웹훅을 사용하면 API를 주기적으로 호출(폴링)하지 않아도 쇼핑몰의 상태 변경을 바로 알 수 있습니다. 이벤트가 발생하면 메이크샵이 파트너가 등록한 수신 URL로 이벤트 정보를 POST 요청으로 전송합니다.
파트너센터 APP 상세에서 수신할 이벤트와 수신 URL을 등록합니다.
샵스토어에서 APP을 설치할 때 웹훅 정보 제공 동의 안내가 함께 노출됩니다.
주문 생성, 상품 수정, 후기 등록 등 등록한 이벤트가 발생합니다.
수신 조건을 모두 충족한 경우에만 파트너 수신 서버로 이벤트 정보가 전송됩니다.
이벤트 수신 조건
아래 조건을 모두 충족해야 이벤트가 전송됩니다. 하나라도 충족하지 않으면 웹훅이 등록되어 있어도 전송되지 않습니다.
| 조건 | 설명 |
|---|---|
| API 권한 보유 | 이벤트와 같은 분류의 API 권한이 APP에 등록되어 있어야 합니다. 예를 들어 ORDER_CREATED를 수신하려면 주문 권한이 필요합니다. |
| 웹훅 활성 상태 | 웹훅의 수신여부가 활성으로 설정되어 있어야 합니다. |
| 운영자 동의 | 쇼핑몰 운영자가 APP 설치 또는 업데이트 시 웹훅 정보 제공에 동의해야 합니다. |
| 지원 쇼핑몰 | 통합옵션 · 주문2.0 · UTF-8 쇼핑몰이어야 합니다. |
쇼핑몰 운영자 동의 안내
APP의 API 권한과 웹훅 이벤트가 하나 이상 일치하면, 샵스토어 상품 상세 > 설치하기 > 서비스 이용동의 팝업에 웹훅 정보 제공 동의 안내가 노출됩니다. 안내에는 API 권한과 웹훅이 모두 일치하는 이벤트만 표시되며, 운영자가 설치를 진행하면 동의한 것으로 처리됩니다.

웹훅 등록하기
웹훅은 파트너센터 App 목록 > 상세 > 개발 정보 탭의 WebHook 정보 영역에서 등록합니다.
수신할 이벤트에 해당하는 API 권한을 먼저 추가하고 APP을 저장합니다. APP을 한 번 이상 저장해야 웹훅을 등록할 수 있습니다.
WebHook 정보 영역의 등록 버튼을 클릭하면 WebHook 등록 팝업이 열립니다.
이벤트 분류와 수신할 이벤트를 선택하고, 수신 URL을 입력한 뒤 수신여부(활성/비활성)를 선택합니다.
저장하면 등록한 웹훅이 목록에 추가됩니다.
서비스 이용에 필수적인 웹훅만 등록해 주세요. 수신한 정보의 관리 및 이용에 대한 책임은 파트너에게 있습니다.

입력 항목
| 항목 | 필수 | 설명 |
|---|---|---|
| 이벤트 | 필수 | 분류를 선택한 뒤 수신할 이벤트를 선택합니다. APP의 API 권한에 해당하는 이벤트만 선택할 수 있습니다. |
| 수신 URL | 필수 | 이벤트를 수신할 URL입니다. https 형식만 등록할 수 있으며, IP 주소나 포트 번호는 입력할 수 없습니다. |
| 수신여부 | 필수 | 활성으로 설정한 웹훅만 이벤트가 전송됩니다. |
선택한 이벤트 분류의 API 권한이 APP에 없을 때 나타납니다. 개발 정보 탭에서 해당 분류의 API 권한을 추가하고 저장한 뒤 다시 등록해 주세요. 이벤트별 필요 권한은 제공 이벤트 목록에서 확인할 수 있으며, 파트너센터의 전체 이벤트 및 권한 안내 버튼으로도 확인할 수 있습니다.
수신 서버 준비
발송 서버 IP 허용
수신 서버에 방화벽이나 접근 제어를 적용하고 있다면, 아래 메이크샵 웹훅 발송 서버의 IP를 허용해 주세요. 허용되지 않으면 이벤트를 수신할 수 없습니다.
| 구분 | IP | Port |
|---|---|---|
| WebHook 발송 서버 | 14.129.76.217 | 443 (HTTPS) |
수신 URL 요구사항
- 유효한 SSL 인증서가 적용된
httpsURL이어야 합니다. - 도메인 기반 URL만 등록할 수 있습니다. 예:
https://example.com/webhook POST요청과application/json본문을 처리할 수 있어야 합니다.
테스트 전송
실제 이벤트가 발생하기 전에 수신 서버가 정상적으로 동작하는지 확인할 수 있습니다. 등록된 웹훅 목록에서 TEST 버튼을 클릭하고 전송을 누르면 해당 이벤트 형식의 샘플 데이터가 수신 URL로 전송됩니다.

- TEST 버튼은 APP을 한 번 이상 저장한 뒤 사용할 수 있습니다.
- 테스트로 전송되는 데이터는 실제 데이터와 다를 수 있습니다.
- 전송 결과는 화면 알림으로 확인할 수 있고, 전송내역에 테스트 구분으로 기록됩니다.
전송내역 조회 및 재전송
WebHook 정보 영역의 전송내역 버튼을 클릭하면 웹훅 전송 결과를 조회하고, 실패한 건을 다시 전송할 수 있습니다.

| 검색 항목 | 설명 |
|---|---|
| 전송일 | 조회할 기간을 지정합니다. 최대 1개월까지 선택할 수 있습니다. |
| 구분 | 실시간(실제 이벤트), 테스트(TEST 버튼 전송), 실시간(재전송)(재전송한 건) |
| 상태 | 성공, 실패, 대기중, 전송중 |
| 이벤트 | 특정 이벤트의 전송 결과만 조회합니다. |
| 검색어 | 쇼핑몰 ID 또는 WebHook ID로 검색합니다. |
메시지 형식과 서명 검증
요청 본문
이벤트 정보는 JSON 형식으로 전송됩니다. 아래는 앱 삭제(APP_DELETED) 이벤트의 예시입니다.
{
"id": "id",
"event_type": "APP_DELETED",
"shop_id": "testshop",
"occurred_at": "2026-06-10 20:00:00",
"data": {
"deleted_date": "2026-06-10 20:00:00"
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
id | String | 이벤트 ID (ex.evt_d509d7a1b8894c51b00cb9d8) |
event_type | String | 이벤트 타입 |
shop_id | String | 이벤트 발생한 쇼핑몰 ID |
occurred_at | DateTime | 이벤트 발생 시각 |
sequence | Integer | 이벤트 순번 (APP_* 이벤트에는 제외 / ex. 1792300501312416) |
data | Object | payload data |
data.deleted_date | DateTime | APP 삭제 시각 |
이벤트별 data 상세 필드는 API 문서를 참고해 주세요.
인증 정보와 서명 검증
개발 정보 탭의 인증 정보는 메이크샵에서 보낸 것인지 확인하는 데 사용합니다. 수신 서버에서는 서명을 검증한 뒤 요청을 처리해 주세요.
| 요청 헤더 | 설명 |
|---|---|
webhook-id | 메시지 고유 ID. 재전송 시에도 같은 값이 유지되어 중복 처리 방지에 사용할 수 있습니다. |
webhook-timestamp | 전송 시각(Unix timestamp, 초) |
webhook-signature | 요청 서명. v1, 접두사 뒤에 Base64 인코딩된 서명이 붙습니다. |
x-client-id | App Client ID |
서명은 {webhook-id}.{webhook-timestamp}.{요청 본문} 문자열을 인증 정보로 HMAC-SHA256 계산한 값입니다.
인증 정보가 whsec_로 시작하면 접두사를 제외한 나머지를 Base64 디코딩하여 키로 사용합니다.
webhook-signature에는 공백으로 구분된 여러 서명이 올 수 있으며(인증 정보 재발급 직후 등), 그중 하나라도 일치하면 유효한 요청입니다.
요청 본문은 수신한 원문 그대로 사용하고, webhook-timestamp가 현재 시각과 5분 이상 차이 나면 거부하는 것을 권장합니다.
const crypto = require('crypto');
// secret: 앱 인증정보 whsec_... (앱당 1개)
// headers: 소문자 키 헤더 맵 (Node http/Express는 기본으로 소문자)
// rawBody: 수신한 원본 body (파싱 전 Buffer 또는 문자열)
function verify(rawBody, headers, secret) {
const id = headers['webhook-id'];
const timestamp = headers['webhook-timestamp'];
const signatureHeader = headers['webhook-signature']; // "v1,xxx v1,yyy"
// 필수 헤더가 하나라도 없으면 거부합니다.
if (!id || !timestamp || !signatureHeader) return false;
// 5분 이상 차이 나는 요청은 거부해 재전송 공격을 막습니다.
// 숫자가 아닌 값(NaN)도 여기서 걸러집니다.
const ts = Number(timestamp);
if (!Number.isFinite(ts) || Math.abs(Date.now() / 1000 - ts) > 300) return false;
const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');
const expected = crypto
.createHmac('sha256', key)
.update(`${id}.${timestamp}.${rawBody}`)
.digest('base64');
const expectedBuf = Buffer.from(expected);
// v1 서명 중 하나라도 일치하면 통과합니다 (timing-safe 비교).
return signatureHeader
.split(' ')
.filter((part) => part.startsWith('v1,'))
.map((part) => Buffer.from(part.slice(3)))
.some((sig) => sig.length === expectedBuf.length && crypto.timingSafeEqual(sig, expectedBuf));
}
// 사용 예 (Express)
// body를 파싱하지 않은 원본 그대로 받아야 서명이 맞습니다.
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
if (!verify(req.body, req.headers, process.env.WEBHOOK_SECRET)) {
return res.status(401).end();
}
const event = JSON.parse(req.body);
// ... Webhook-Id로 중복 확인 후 처리
res.status(200).end();
});
인증 정보가 유출되어 발생하는 데이터 노출, 시스템 부정 사용 등의 모든 책임은 파트너에게 있습니다. 인증 정보는 서버 환경 변수 등 안전한 곳에 보관해 주세요. 재발급은 키가 유출되었거나 인증에 장애가 생긴 경우에만 사용해 주세요. 재발급 후 일정 시간 동안은 기존 키와 새 키 서명이 함께 전송되므로, 그 안에 수신 서버의 키를 새 키로 교체해 주세요.
응답 및 재시도 정책
이벤트를 정상 수신했다면 수신 서버는 HTTP 2xx 상태 코드로 응답해야 합니다. 2xx 이외의 응답을 보내거나 제한 시간 안에 응답하지 않으면 전송 실패로 처리되고, 일정 간격으로 다시 전송합니다.
| 시도 | 직전 시도 이후 대기 시간 |
|---|---|
| 1회차 | 즉시 |
| 2회차 | 5초 |
| 3회차 | 1분 |
| 4회차 | 5분 |
| 5회차 | 30분 |
모든 재시도에 실패한 건은 전송내역에서 상태를 확인하고 직접 재전송할 수 있습니다.
권장 구현 방식
- 먼저 응답하고 나중에 처리하세요. 요청을 받으면 바로 2xx로 응답하고, 실제 처리는 큐 등을 이용해 비동기로 진행하는 것을 권장합니다. 처리 시간이 길어지면 타임아웃으로 실패 처리되어 같은 이벤트가 다시 전송될 수 있습니다.
- 중복 수신에 대비하세요. 재시도나 재전송으로 같은 이벤트가 두 번 이상 도착할 수 있습니다. WebHook ID를 저장해 두고 이미 처리한 이벤트는 건너뛰도록 구현해 주세요.
- 전송 순서에 의존하지 마세요. 이벤트가 발생 순서대로 도착한다는 보장은 없습니다. 최신 상태가 필요하면 이벤트 수신 후 API로 다시 조회해 주세요.
제공 이벤트 목록
현재 제공되는 이벤트는 총 22종입니다. 모든 이벤트는 해당 분류의 Read 권한이 있으면 수신할 수 있습니다.
| 분류 | 이벤트 코드 | 이벤트명 | 필요 권한 |
|---|---|---|---|
| 앱 | APP_DELETED | 앱 삭제 | Read |
APP_EXPIRED | 앱 만료 | Read | |
APP_EXPIRY_EXTENDED | 앱 만료 연장 | Read | |
| 주문 | ORDER_CREATED | 주문 생성 | Read |
ORDER_CANCELED | 주문 취소 | Read | |
ORDER_PAID | 주문 입금 완료 | Read | |
ORDER_RETURNED | 주문 반품 | Read | |
ORDER_EXCHANGED | 주문 교환 | Read | |
ORDER_REFUNDED | 주문 환불 | Read | |
ORDER_TRACKING_CHANGED | 주문 운송장 변경 | Read | |
| 상품 | PRODUCT_CREATED | 상품 생성 | Read |
PRODUCT_DELETED | 상품 삭제 | Read | |
PRODUCT_UPDATED | 상품 수정 | Read | |
PRODUCT_OPTION_UPDATED | 상품 옵션 수정 | Read | |
PRODUCT_STOCK_UPDATED | 상품 재고 수정 | Read | |
PRODUCT_CATEGORY_CREATED | 상품 분류 추가 | Read | |
PRODUCT_CATEGORY_UPDATED | 상품 분류 수정 | Read | |
PRODUCT_CATEGORY_DELETED | 상품 분류 삭제 | Read | |
| 회원 | CART_ITEM_ADDED | 장바구니 상품 담기 | Read |
| 게시판 | REVIEW_CREATED | 코멘트평점 후기 등록 | Read |
REVIEW_UPDATED | 코멘트평점 후기 수정 | Read | |
REVIEW_DELETED | 코멘트평점 후기 삭제 | Read |
앱 결제(APP_PAID), 앱 환불 요청(APP_REFUND_REQUESTED), 앱 환불 완료(APP_REFUND_COMPLETED) 이벤트는 샵스토어 결제 기능 오픈 시점에 제공될 예정입니다.
웹훅 수정 · 삭제
| 작업 | 안내 |
|---|---|
| 웹훅 수정 | APP 심사 상태와 관계없이 언제든 수정할 수 있으며, 수정해도 재심사는 진행되지 않습니다. |
| 이벤트 추가 | 새 이벤트를 추가하고 저장하면, 이미 APP을 설치한 쇼핑몰의 샵스토어 마이페이지 > 설치내역 > 연동관리 버튼이 [업데이트]로 바뀝니다. 해당 쇼핑몰이 업데이트 팝업에서 동의하기 전까지는 추가한 이벤트가 전송되지 않습니다. |
| 웹훅 삭제 | 목록의 삭제 버튼을 클릭하면 별도 확인 없이 바로 삭제됩니다. 삭제 시에는 쇼핑몰 재동의가 필요하지 않습니다. |
| API 권한 삭제 | 같은 분류의 웹훅이 등록된 상태에서 API 권한을 삭제하면 안내가 표시됩니다. 삭제를 진행하면 웹훅 설정은 남아 있지만 해당 이벤트는 전송되지 않습니다. |
APP을 이미 설치한 쇼핑몰은 업데이트에 동의해야 추가 이벤트를 받을 수 있습니다. 새 이벤트를 기반으로 하는 기능은 동의하지 않은 쇼핑몰에서도 오류 없이 동작하도록 구현해 주세요.
이벤트가 수신되지 않을 때
아래 항목을 순서대로 확인해 주세요.
- 전송내역 확인 — 전송내역에 기록이 있는지, 상태가 실패인지 확인합니다. 기록이 없다면 아래 수신 조건을 확인해 주세요.
- API 권한 — 이벤트와 같은 분류의 API 권한이 APP에 등록되어 있는지 확인합니다.
- 수신여부 — 웹훅이 활성 상태인지 확인합니다.
- 운영자 동의 — 이벤트를 추가했다면 해당 쇼핑몰 운영자가 업데이트에 동의했는지 확인합니다.
- 쇼핑몰 환경 — 통합옵션 · 주문2.0 · UTF-8 쇼핑몰인지 확인합니다.
- 방화벽 — 발송 서버 IP
14.129.76.217이 허용되어 있는지 확인합니다. - 응답 코드 — 수신 서버가 제한 시간 안에 2xx로 응답하는지 확인합니다. TEST 전송으로 빠르게 점검할 수 있습니다.
API 권한별 요청/응답 형식과 파라미터 등 상세 스펙은 API 문서를 참고해 주세요.