Webhook 노드 — 외부 세계와 연결하는 문

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 노드 설정

기본 설정

  1. 새 워크플로우 생성
  2. Tab → "Webhook" 검색 → Webhook 선택
  3. 기본 설정:
설정 설명 기본값
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-test vs webhook). 개발 중에는 Test URL을, 실제 서비스에서는 Production URL을 사용하자.

커스텀 Path 설정

자동 생성된 UUID 대신 기억하기 쉬운 경로를 설정할 수 있다.

기본: /webhook/a1b2c3d4-e5f6-7890-abcd-ef1234567890
커스텀: /webhook/github-pr-notify

Path 필드에 원하는 경로를 입력하면 된다.


첫 Webhook 테스트하기

Step 1: Webhook 노드 추가

  1. 새 워크플로우 생성 → 이름: "🔔 Webhook 테스트"
  2. Webhook 노드 추가
  3. HTTP Method: POST
  4. Path: test-hook

Step 2: 테스트 모드 시작

  1. Webhook 노드 클릭
  2. "Listen for test event" 버튼 클릭
  3. "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 등록

  1. GitHub 리포지토리 → Settings → Webhooks → Add webhook
  2. Payload URL: n8n의 Production Webhook URL
  3. Content type: application/json
  4. Secret: 보안 키 입력
  5. 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의 스위스 아미 나이프를 완전 해부한다.