웹훅
Webhook
도구
사건이 생긴 쪽이 상대가 미리 알려 준 주소로 먼저 알림을 보내 주는 방식입니다.
등장 배경
남의 시스템에서 일이 벌어졌는지 아는 방법이 계속 물어보는 것뿐이던 시절이 있었습니다. 결제가 승인됐는지 알려면 결제 대행사의 조회 창구를 1분마다 불러 봅니다. 하루에 1,440번 묻고, 그중 실제로 새 소식이 있는 응답은 몇 건입니다.
비용이 세 갈래로 붙었습니다. 의미 없는 요청이 하루 천 건 넘게 오가면서 양쪽 서버가 그만큼 일을 하고, 한 사람이 정해진 시간에 보낼 수 있는 횟수를 묶어 둔 요청 제한에 걸려 정작 필요한 요청이 거절당하고, 그러고도 알림은 최대 1분 늦습니다. 간격을 10초로 줄이면 요청이 여섯 배가 되고 지연은 10초가 됩니다. 둘 다 좋게 만들 방법이 없습니다.
그래서 방향을 뒤집었습니다. 묻는 쪽이 계속 두드리는 대신, 사건이 생긴 쪽이 미리 받아 둔 주소로 알려 줍니다. 주소만 등록해 두면 그 뒤로는 일이 생길 때만 통신이 일어납니다.
해결하는 문제
뒤집힌 방향이 세 가지를 한 번에 없앱니다. 사건과 알림 사이의 지연, 아무 일도 없을 때 오가는 요청, 그 요청이 잡아먹는 요청 한도입니다.
대신 받는 쪽이 준비할 것이 생깁니다. 실무에서 걸리는 것은 대부분 이쪽입니다.
- 받을 주소를 만들어 등록합니다. 이 주소는 인터넷에 열려 있어야 하므로 누구나 두드릴 수 있습니다. 그래서 보내는 쪽이 본문과 비밀 키로 만든 서명을 함께 실어 보내고, 받는 쪽은 그 서명을 다시 계산해 맞는지 확인한 뒤에야 내용을 믿습니다.
- 빠르게 받았다고 답하고 처리는 뒤로 넘깁니다. 대개 보내는 쪽은 몇 초 안에 응답이 없으면 실패로 보고 다시 보냅니다. 받은 즉시 저장만 해 두고 성공을 돌려준 다음, 실제 처리는 뒤에서 도는 작업으로 옮깁니다.
- 같은 사건이 두 번 와도 결과가 같게 만듭니다. 재시도가 정상 동작이라 중복 도착은 예외가 아니라 전제입니다. 같은 요청을 여러 번 받아도 결과가 달라지지 않는 성질을 멱등성이라고 하고, 사건마다 붙어 오는 고유 번호를 기록해 두었다가 이미 처리한 번호면 그냥 성공을 돌려주는 방식으로 만듭니다.
- 순서를 믿지 않습니다. 결제 승인과 취소가 연달아 일어나면 취소가 먼저 도착할 수 있습니다. 사건 본문에 실려 오는 시각이나 버전 값으로 판단하고, 이미 더 새로운 상태를 반영했다면 오래된 사건은 버립니다.
- 놓친 사건을 메울 조회 경로를 함께 둡니다. 우리 서버가 30분 멈춰 있었다면 그 동안의 알림은 재시도 한도를 넘겨 사라집니다. 그래서 하루에 한 번 상대 쪽 목록을 조회해 우리 기록과 맞춰 보는 작업을 붙입니다.
- 실패한 알림을 따로 쌓아 두고 다시 처리할 수단을 만듭니다. 이 화면이 없으면 문제가 났을 때 상대 회사에 재발송을 요청하는 것 말고 방법이 없습니다.
대안
같은 필요를 다르게 푸는 방법이 넷 있습니다.
- 계속 물어보는 방식입니다. 만들기 가장 쉽고 우리 쪽에서 통제할 수 있다는 점이 장점입니다. 사건이 드물고 1분 지연이 상관없는 자리, 또는 상대가 알림을 지원하지 않는 자리에서는 이쪽이 남습니다.
- 연결을 열어 두는 방식입니다. 웹소켓은 양쪽이 아무 때나 말을 걸 수 있게 연결을 유지합니다. 화면과 서버 사이에 쓰기 좋고, 서버와 서버 사이에는 연결을 계속 붙잡고 있어야 해서 부담이 큽니다.
- 서버에서 화면으로 한 방향으로 흘려보내는 방식입니다. 연결을 열어 두되 서버만 말하는 형태라 웹소켓보다 단순하고, 알림을 화면에 즉시 띄우는 자리에 맞습니다.
- 줄 세우는 장치를 함께 쓰는 방식입니다. 같은 회사 안의 서비스끼리라면 메시지 큐에 사건을 넣고 관심 있는 쪽이 꺼내 가는 편이 낫습니다. 받는 쪽이 멈춰 있어도 사건이 줄에 남아 있어서 놓치지 않습니다.
고르는 기준은 셋입니다. 회사 경계를 넘는지, 지연이 몇 초까지 허용되는지, 놓쳐도 되는 사건인지입니다. 경계를 넘고 몇 초 안에 알아야 하고 놓치면 안 되는 자리가 이 방식이 맞는 자리이고, 경계 안이라면 줄 세우는 장치가 대체로 낫습니다.
실무 용례
"결제 상태를 1분마다 조회하고 있습니다. 웹훅으로 바꾸죠."
묻는 방향을 뒤집자는 제안입니다.
"서명 검증 없이 본문만 믿고 처리하고 있습니다. 위조 요청이 통합니다."
열린 주소의 위험을 짚는 지적입니다.
"같은 사건이 세 번 왔는데 세 번 처리됐습니다. 멱등하게 고쳐야 합니다."
재시도가 전제라는 사실을 짚는 보고입니다.
페이지덱이 결제 대행사 연동을 이 방식으로 옮겼습니다. 태오가 먼저 조회 방식의 기록을 보니 하루 요청이 1,400건이고 그중 새 소식이 있는 응답은 서른 건이었습니다. 알림으로 바꾸고 나서 통신은 하루 서른 건이 됐고, 결제 성공을 사용자 화면에 띄우기까지 걸리던 시간이 평균 28초에서 1초 아래로 내려갔습니다.
옮긴 첫 주에 문제가 한 번 있었습니다. 배포 중에 서버가 4분 멈춘 사이 도착한 알림 열두 건이 사라졌습니다. 그래서 새벽에 하루치 결제 목록을 조회해 우리 기록과 맞추는 작업을 붙였습니다. 알림만 믿는 구조에서는 이 보정이 선택이 아니라는 것을 그때 확인했습니다.
흔한 오해
도착한 알림을 그대로 믿을 수 있다고 보는 경우가 가장 많습니다. 상대가 보낸 것이니 믿을 만해 보입니다. 하지만 그 주소는 인터넷에 열려 있고 주소를 아는 사람은 누구나 같은 모양의 요청을 만들어 보낼 수 있습니다. 결제 성공 알림을 위조해 보내면 돈을 받지 않고 유료 기능이 열립니다. 서명을 확인하고, 금액과 상태는 상대 쪽 조회로 한 번 더 맞춰 보는 것이 기본입니다.
알림이 있으면 조회 창구는 필요 없다고 보는 것도 흔합니다. 같은 정보를 두 경로로 받는 것처럼 보이니 그렇게 읽힙니다. 하지만 알림은 우리 서버가 받을 수 있는 상태일 때만 도착합니다. 배포와 장애와 네트워크 문제로 못 받는 구간이 반드시 생기고, 그 구간을 메우는 유일한 방법이 조회입니다. 두 경로는 대체 관계가 아니라 짝입니다.
자주 헷갈리는 용어
| 용어 | 연결을 어떻게 두는가 | 웹훅과의 차이 |
|---|---|---|
| 웹소켓 | 연결을 열어 둔 채 유지합니다 | 양쪽이 아무 때나 말을 걸 수 있고 지연이 더 짧습니다. 대신 연결을 계속 붙잡아야 해서 서버끼리보다 화면과 서버 사이에 맞습니다 |
같이 보면 좋은 페이지
마지막 업데이트 2026-09-16