n8n Form Trigger + Wait 노드 — 사람의 승인이 필요한 자동화
"AI가 100점짜리 이메일 초안을 작성했다. 그런데 그냥 보내도 될까?" — 결국 사람의 최종 확인이 필요한 순간이 온다. 이것이 Human-in-the-Loop다.
Human-in-the-Loop란?
자동화 흐름 중간에 사람의 판단이나 승인을 삽입하는 패턴이다.
[자동 처리] → [PAUSE: 사람의 승인 대기] → [승인되면 실행]
↑
(이메일/Slack으로 승인 요청)
적합한 케이스
| 케이스 | 이유 |
|---|---|
| AI 생성 이메일 발송 | 부정확한 내용이 고객에게 가면 안 됨 |
| 대규모 데이터 삭제 | 되돌릴 수 없는 작업 |
| 결제/환불 처리 | 금액 관련 최종 확인 |
| 채용 프로세스 | 인사 담당자 최종 판단 |
| 콘텐츠 발행 | 품질 검수 후 공개 |
Wait 노드 — 워크플로우 일시 정지
기본 모드
| 모드 | 설명 |
|---|---|
| After Time Interval | 지정 시간 후 자동 재개 (5분, 1시간, 1일 등) |
| At Specified Time | 특정 날짜/시간에 재개 |
| On Webhook Call | 외부 Webhook 호출 시 재개 (승인 패턴) |
| On Form Submission | n8n 폼 제출 시 재개 |
Webhook 기반 승인 패턴
[처리] → [Slack: 승인 요청 (링크 포함)] → [Wait: Webhook 대기]
│
(승인자가 링크 클릭)
↓
[승인 후 처리 계속]
Wait 노드의 Resume URL이 핵심이다:
{{ $execution.resumeUrl }}
→ https://n8n.example.com/webhook/resume/exec_abc123
이 URL을 승인자에게 전달하고, 승인자가 이 URL을 호출하면 워크플로우가 재개된다.
승인/거부 분기
승인 URL과 거부 URL을 각각 만들어 분기:
승인 URL: {{ $execution.resumeUrl }}?action=approve
거부 URL: {{ $execution.resumeUrl }}?action=reject
Wait 노드 이후:
[IF: $json.action === "approve"]
true → [실행]
false → [취소 알림]
Form Trigger — 커스텀 입력 폼
n8n은 코드 없이 입력 폼을 생성할 수 있다.
Form Trigger 필드 설정
| 필드 타입 | 설명 |
|---|---|
| Text | 한 줄 텍스트 입력 |
| Textarea | 여러 줄 텍스트 |
| Number | 숫자 |
| Date | 날짜 선택 |
| Dropdown | 드롭다운 선택 |
| File | 파일 업로드 |
폼 예시: 휴가 신청
Form Title: "휴가 신청서"
Fields:
- 이름 (Text, Required)
- 부서 (Dropdown: [개발팀, 마케팅, 영업, 인사])
- 휴가 시작일 (Date, Required)
- 휴가 종료일 (Date, Required)
- 사유 (Textarea)
- 유형 (Dropdown: [연차, 반차, 병가, 경조])
Form URL: https://n8n.example.com/form/vacation-request
실전: AI 이메일 초안 → 관리자 승인 → 자동 발송
[Webhook: 고객 문의 접수]
→ [AI Agent: 답변 초안 생성]
→ [Slack: 관리자에게 승인 요청 (초안 + 승인/거부 버튼)]
→ [Wait: Webhook 대기]
→ [IF: 승인?]
true → [Gmail: 이메일 발송] → [Slack: "✅ 발송 완료"]
false → [Slack: "❌ 발송 취소됨"]
Slack 승인 요청 메시지
[
{
"type": "header",
"text": { "type": "plain_text", "text": "📧 이메일 발송 승인 요청" }
},
{
"type": "section",
"text": { "type": "mrkdwn", "text": "*받는 사람:* {{ $json.to }}\n*제목:* {{ $json.subject }}" }
},
{
"type": "section",
"text": { "type": "mrkdwn", "text": "```{{ $json.draft }}```" }
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "✅ 승인" },
"style": "primary",
"url": "{{ $execution.resumeUrl }}?action=approve"
},
{
"type": "button",
"text": { "type": "plain_text", "text": "❌ 거부" },
"style": "danger",
"url": "{{ $execution.resumeUrl }}?action=reject"
}
]
}
]
Wait 노드 타임아웃
승인자가 응답하지 않으면 워크플로우가 영원히 대기한다. 타임아웃을 설정하자.
Wait → Limit Wait Time: ON
→ Resume After: 24 hours
24시간 내 응답이 없으면 자동으로 재개되고, 타임아웃 분기 처리:
[Wait] → [IF: 타임아웃?]
true → [Slack: "⏰ 승인 시간 초과. 자동 취소됨."]
false → [정상 승인/거부 처리]
📝 정리
- [x] Human-in-the-Loop: 자동화 중간에 사람의 판단/승인을 삽입하는 패턴
- [x] Wait 노드: Time/Webhook/Form 방식으로 워크플로우 일시 정지
- [x] Resume URL:
$execution.resumeUrl로 승인 링크 생성 - [x] Form Trigger: 코드 없이 커스텀 입력 폼 생성
- [x] 타임아웃: Limit Wait Time으로 무한 대기 방지
다음 편 예고
27편: Credential 관리와 보안 — 프로덕션 환경 구축
API 키, OAuth 토큰, DB 비밀번호... 프로덕션 환경에서 Credential을 안전하게 관리하는 모범 사례.