Webhook 노드 — 외부 세계와 연결하는 문
Schedule Trigger가 "시계"라면, Webhook은 "문"이다. 외부 세계에서 n8n의 문을 두드리면 워크플로우가 깨어난다.
Webhook이란?
Webhook은 "역방향 API"라고 생각하면 쉽다.
- 일반 API: 내가 서버에 요청을 보내서 데이터를 가져온다 (Pull)
- Webhook: 서버가 나에게 이벤트를 알려준다 (Push)
일반 API (Pull):
나 ──요청──▶ 서버
나 ◀──응답── 서버
Webhook (Push):
서버에 이벤트 발생 ──▶ 서버가 내 URL로 데이터 전송 ──▶ 내 워크플로우 실행
실제 예시: - GitHub에 PR이 생성되면 → 내 n8n Webhook URL로 PR 정보를 보내준다 - Stripe에 결제가 완료되면 → 내 n8n Webhook URL로 결제 정보를 보내준다 - 내 앱에서 회원가입이 되면 → 내 n8n Webhook URL로 회원 정보를 보내준다
Webhook Trigger 노드 설정
기본 설정
- 새 워크플로우 생성
Tab→ "Webhook" 검색 → Webhook 선택- 기본 설정:
| 설정 | 설명 | 기본값 |
|---|---|---|
| HTTP Method | 허용할 HTTP 메서드 | POST |
| Path | Webhook URL 경로 | 자동 생성 UUID |
| Authentication | 인증 방식 | None |
| Respond | 응답 방식 | Immediately |
Webhook URL 이해하기
Webhook 노드를 추가하면 2개의 URL이 생성된다.
| URL 종류 | 용도 | 언제 동작 |
|---|---|---|
| Test URL | 개발/테스트용 | "Listen for test event" 클릭 시 |
| Production URL | 실제 운영용 | 워크플로우 Active ON 시 |
Test URL:
https://your-n8n.com/webhook-test/abc123-def456
Production URL:
https://your-n8n.com/webhook/abc123-def456
⚠️ 주의: Test URL과 Production URL은 경로가 다르다 (
webhook-testvswebhook). 개발 중에는 Test URL을, 실제 서비스에서는 Production URL을 사용하자.
커스텀 Path 설정
자동 생성된 UUID 대신 기억하기 쉬운 경로를 설정할 수 있다.
기본: /webhook/a1b2c3d4-e5f6-7890-abcd-ef1234567890
커스텀: /webhook/github-pr-notify
Path 필드에 원하는 경로를 입력하면 된다.
첫 Webhook 테스트하기
Step 1: Webhook 노드 추가
- 새 워크플로우 생성 → 이름: "🔔 Webhook 테스트"
- Webhook 노드 추가
- HTTP Method: POST
- Path:
test-hook
Step 2: 테스트 모드 시작
- Webhook 노드 클릭
- "Listen for test event" 버튼 클릭
- "Waiting for test event..." 메시지가 표시됨
Step 3: curl로 테스트
새 터미널을 열고 아래 명령어를 실행한다:
curl -X POST http://localhost:5678/webhook-test/test-hook \
-H "Content-Type: application/json" \
-d '{"name": "홍길동", "action": "signup", "email": "[email protected]"}'
Step 4: 결과 확인
n8n 에디터로 돌아오면 Webhook 노드에 데이터가 수신된 것을 확인할 수 있다:
{
"headers": {
"content-type": "application/json",
"user-agent": "curl/8.x.x",
...
},
"params": {},
"query": {},
"body": {
"name": "홍길동",
"action": "signup",
"email": "[email protected]"
}
}
수신된 데이터의 구조를 이해하자:
| 필드 | 설명 | 접근 방법 |
|---|---|---|
headers | HTTP 요청 헤더 | {{ $json.headers["content-type"] }} |
params | URL 경로 파라미터 | {{ $json.params.id }} |
query | URL 쿼리 파라미터 (?key=value) | {{ $json.query.status }} |
body | 요청 본문 (POST 데이터) | {{ $json.body.name }} |
HTTP Method 선택
Webhook이 받아들일 HTTP 메서드를 설정할 수 있다.
| 메서드 | 용도 | 예시 |
|---|---|---|
| GET | 데이터 조회. body 없음 | ?id=123&status=active 쿼리 파라미터 |
| POST | 데이터 생성/전달. body 포함 | GitHub Webhook, Stripe Webhook |
| PUT | 데이터 수정 | 리소스 업데이트 알림 |
| DELETE | 데이터 삭제 | 리소스 삭제 알림 |
대부분의 외부 서비스 Webhook은 POST를 사용한다.
GET 요청 처리
URL 쿼리 파라미터로 데이터를 전달하는 경우:
curl "http://localhost:5678/webhook-test/test-hook?name=홍길동&city=서울"
데이터 접근:
{{ $json.query.name }} // "홍길동"
{{ $json.query.city }} // "서울"
Webhook 인증
프로덕션 환경에서는 아무나 Webhook을 호출하면 안 된다. n8n은 여러 인증 방식을 지원한다.
1. Header Auth
Authentication: Header Auth
Header Name: X-API-Key
Header Value: my-secret-api-key-123
호출 시 헤더에 키를 포함해야 한다:
curl -X POST http://localhost:5678/webhook/test-hook \
-H "X-API-Key: my-secret-api-key-123" \
-H "Content-Type: application/json" \
-d '{"data": "hello"}'
키가 일치하지 않으면 403 Forbidden 응답을 반환한다.
2. Basic Auth
Authentication: Basic Auth
Username: myuser
Password: mypassword
curl -X POST http://localhost:5678/webhook/test-hook \
-u "myuser:mypassword" \
-H "Content-Type: application/json" \
-d '{"data": "hello"}'
3. JWT 검증 (Code 노드 활용)
GitHub, Stripe 등의 서비스는 요청에 서명(Signature)을 포함한다. Webhook 다음에 Code 노드를 추가해서 검증할 수 있다:
// GitHub Webhook의 서명 검증 예시
const crypto = require('crypto');
const secret = $env.GITHUB_WEBHOOK_SECRET;
const signature = $json.headers['x-hub-signature-256'];
const payload = JSON.stringify($json.body);
const hmac = crypto.createHmac('sha256', secret);
hmac.update(payload);
const expected = 'sha256=' + hmac.digest('hex');
if (signature !== expected) {
throw new Error('Invalid webhook signature');
}
return $input.all();
응답 설정 (Respond)
Webhook 노드는 호출자에게 응답을 어떻게 보낼지 설정할 수 있다.
Immediately (즉시 응답)
워크플로우 실행 완료를 기다리지 않고 바로 응답한다.
호출자 ──POST──▶ n8n Webhook
호출자 ◀──200── n8n (즉시 응답)
↓ (비동기 처리)
[Node A] → [Node B] → ...
장점: 호출자가 오래 기다리지 않아도 된다.
사용 시나리오: 외부 서비스의 Webhook (GitHub, Stripe 등). 이들은 응답 시간 제한이 있다.
When Last Node Finishes (완료 후 응답)
워크플로우가 끝난 후 마지막 노드의 출력을 응답으로 보낸다.
호출자 ──POST──▶ n8n Webhook
↓ (처리 중...)
[Node A] → [Node B] → [결과]
호출자 ◀──200── n8n (결과 데이터 포함)
장점: 처리 결과를 응답에 포함할 수 있다.
사용 시나리오: n8n을 API 서버처럼 사용할 때. 예: 데이터 조회 API 만들기.
Using 'Respond to Webhook' Node (커스텀 응답)
워크플로우 중간에 Respond to Webhook 노드를 배치하여 원하는 시점에 원하는 내용으로 응답한다.
[Webhook] → [처리] → [Respond to Webhook] → [후속 작업]
↑ 여기서 응답 전송 ↑ 응답 후에도 계속 실행
Respond to Webhook 노드 설정:
| 설정 | 설명 |
|---|---|
| Response Code | HTTP 상태 코드 (200, 201, 400 등) |
| Response Body | 응답 본문 (JSON, 텍스트 등) |
| Response Headers | 커스텀 응답 헤더 |
// Respond to Webhook 응답 예시
{
"status": "success",
"message": "요청이 접수되었습니다",
"requestId": "{{ $execution.id }}"
}
실전 예제: GitHub PR 알림 받기
GitHub에 Pull Request가 생성되면 알림을 받는 워크플로우를 만들어보자.
워크플로우 구조
[Webhook] → [IF: PR 생성?] → [Edit Fields] → [결과/알림]
Step 1: Webhook 설정
| 설정 | 값 |
|---|---|
| HTTP Method | POST |
| Path | github-pr |
| Authentication | Header Auth |
| Header Name | X-Hub-Signature-256 |
Step 2: GitHub에서 Webhook 등록
- GitHub 리포지토리 → Settings → Webhooks → Add webhook
- Payload URL: n8n의 Production Webhook URL
- Content type:
application/json - Secret: 보안 키 입력
- Events: "Pull requests" 선택
Step 3: IF 노드로 이벤트 필터링
GitHub는 PR의 모든 이벤트(생성, 수정, 닫기 등)를 보내므로, "생성"만 필터링한다:
IF: $json.body.action === "opened"
Step 4: Edit Fields로 데이터 정제
PR 제목: {{ $json.body.pull_request.title }}
작성자: {{ $json.body.pull_request.user.login }}
URL: {{ $json.body.pull_request.html_url }}
리포: {{ $json.body.repository.full_name }}
이후 Slack이나 Email 노드를 연결하면 실시간 알림 시스템이 완성된다.
Webhook 디버깅 팁
1. 외부에서 접근이 안 될 때
로컬 개발 환경에서는 localhost에 외부 서비스가 접근할 수 없다.
해결법:
- ngrok 사용: ngrok http 5678으로 임시 공개 URL 생성
- n8n Cloud 사용: 클라우드 환경이면 이 문제가 없다
- 서버 배포: VPS에 n8n을 설치하면 공개 URL이 생긴다
2. 데이터가 비어있을 때
{ "body": {} }
원인: Content-Type 헤더가 없거나 잘못되었다.
해결: 호출 시 -H "Content-Type: application/json" 헤더를 반드시 포함하자.
3. 405 Method Not Allowed
원인: Webhook 설정의 HTTP Method와 실제 요청 Method가 다르다.
해결: 노드 설정에서 올바른 Method를 선택했는지 확인하자.
📝 정리
- [x] Webhook: 외부 서비스가 n8n에 이벤트를 알려주는 "역방향 API"
- [x] 2개의 URL: Test URL(개발용)과 Production URL(운영용)
- [x] 인증 방식: Header Auth, Basic Auth, Signature 검증
- [x] 응답 설정: Immediately(즉시), Last Node(완료 후), Respond 노드(커스텀)
- [x] 데이터 접근:
$json.body(본문),$json.query(쿼리),$json.headers(헤더)
다음 편 예고
7편: HTTP Request 노드 심화 — 모든 API를 연결하는 만능 도구
Webhook이 "받는 것"이라면, HTTP Request는 "보내는 것"이다. REST API 호출, OAuth 인증, 페이지네이션, 파일 다운로드까지 — n8n의 스위스 아미 나이프를 완전 해부한다.