결재 한 건이 막히면 그 뒤 작업 전체가 멈췄습니다. 담당자는 메일함을 새로고침했고, 요청자는 "승인 되셨나요?"를 반복해서 물었습니다. 문제는 승인 자체가 아니라, 승인을 기다리는 시간이었습니다.
그래서 결재를 메일함 밖으로 꺼냈습니다. 요청이 들어오면 담당자의 텔레그램으로 카드가 날아가고, 버튼 한 번이면 워크플로우가 다음 단계를 바로 실행합니다.
REQ요청 접수TGTelegram 카드✓승인 / 반려n8다음 단계 실행
어떻게 동작하나
워크플로우는 두 개의 트리거 체인으로 구성됩니다. 첫 번째는 결재 요청을 받고 텔레그램 카드를 보내는 발송 체인, 두 번째는 담당자의 버튼 탭을 폴링으로 받아 결과를 다운스트림으로 되돌려주는 콜백 체인입니다. 상태는 n8n의 워크플로우 정적 데이터(static data)에 잠깐 저장했다가, 콜백이 도착하면 꺼내 씁니다.
발송 체인
- Webhook 노드가 결재 요청을 HTTP POST로 받습니다.
- Edit Fields (Set) 노드로 페이로드를 정규화합니다 (requestId, title, amount, requester, approverChatId, callbackUrl).
- Code 노드가 워크플로우 정적 데이터에
{ requestId: callbackUrl }을 저장합니다. - Telegram Send Message 노드가 담당자 채팅으로 승인 카드를 보냅니다. 카드에는
callback_data가approve:REQ-ID또는reject:REQ-ID형태인 인라인 버튼 두 개가 붙습니다. - Respond to Webhook 노드가 요청자에게
{"status":"pending","requestId":"..."}을 즉시 반환합니다.
콜백 체인
- Telegram Trigger 노드가
callback_query업데이트를 폴링으로 받습니다. 외부에서 n8n으로 들어오는 웹훅이 필요 없어 로컬 개발 환경에서도 그대로 동작합니다. - Code 노드가
callback_data에서decision과requestId를 파싱하고, 저장된callbackUrl을 조회한 뒤 정적 데이터에서 제거합니다. - HTTP Request 노드가 요청자가 지정한
callbackUrl로{decision, requestId}를 POST합니다. - Telegram: Answer Callback Query 노드가 버튼 로딩 스피너를 지우고 사용자에게 완료 알림을 보냅니다.
필요한 것
- n8n 2.29.9 이상 (자체 호스팅 또는 Cloud). 검증은 자체 호스팅 Docker(
docker.n8n.io/n8nio/n8n)에서 진행했습니다. - 코어 노드만 사용합니다 (Webhook · Set · Code · Telegram Send Message · Telegram Trigger · HTTP Request · Respond to Webhook · Telegram Answer Callback Query). 커뮤니티 노드 없음.
- BotFather에서 발급한 Telegram Bot 토큰 — n8n Credentials에
Telegram API로 등록합니다. - 결재자의 숫자 chat ID —
@userinfobot에게 메시지를 보내면 알려줍니다.@username은 사용할 수 없습니다. - 결재자가 봇에게 최소 1회 이상 메시지를 보낸 상태여야 합니다 (Telegram 정책). 봇을 검색해서
Start한 번 눌러 두세요. - 결과를 받을 다운스트림 엔드포인트 (
callbackUrl). 테스트에는webhook.site무료 URL이면 충분합니다. - 발송 체인과 콜백 체인은 같은 워크플로우 안에 있어야 합니다. 워크플로우 정적 데이터(
$getWorkflowStaticData('global'))를 상태 저장소로 쓰기 때문입니다. - 잘못된 chat ID를 넣으면 Telegram Send Message 노드가
Bad Request: chat not found로 실패합니다. 실제 운영에서는 이 분기에 알림·재시도 처리를 붙이세요. - 정적 데이터는 워크플로우 비활성화·삭제 시 사라지는 휘발성 저장소입니다. 시간이 오래 걸리는 결재나 감사 로그가 필요한 운영 환경에서는 Postgres 등 영구 저장소로 교체하세요.
샘플 페이로드
curl -X POST http://localhost:5678/webhook/telegram-approval \
-H "Content-Type: application/json" \
-d '{
"requestId": "REQ-2026-001",
"title": "예산 승인 요청 — 3분기 마케팅",
"amount": 1500000,
"requester": "김지훈",
"approverChatId": "8104222459",
"callbackUrl": "https://webhook.site/your-uuid"
}'이 워크플로우는 n8n 2.29.9에서 curl → 텔레그램 카드 발송 → 담당자 버튼 탭 → callbackUrl POST → 스피너 해제까지 실제로 실행하며 검증했습니다. 마지막 검증: 2026-07-11.
6.2h → 40분
평균 승인 대기 시간
0건
누락된 결재
3일
구축 기간
출근하면서 폰으로 결재 다 끝냅니다. 사무실 도착하면 이미 다음 단계가 돌고 있어요.— 운영 매니저