발행일: 2026-10-06(화) 11:44
← 목차로 돌아가기|하루 30분 n8n 시리즈 ② 실무 자동화 레시피 100
RECIPE 042

FAQ 키워드 매칭 → 자동 답변 발송

  • ▸긴 문서(PDF, Docs, 텍스트)를 OpenAI로 자동 요약할 수 있다
  • ▸문서 길이에 따라 청크(chunk) 분할 처리를 할 수 있다
  • ▸요약 결과를 1페이지 브리핑 형식으로 Notion 또는 이메일로 발송할 수 있다

✅사전 준비

  • □OpenAI API 자격증명 연결 완료
  • □요약 소스 결정 (Google Drive PDF / Notion 페이지 / Webhook 텍스트 수신)
  • □Notion 또는 Gmail 자격증명 연결 완료 (결과 저장용)

텍스트 청크 분할 — Code 노드

const text = $input.first().json.content ?? '';
const chunkSize = 3000; // 토큰 절약을 위해 3000자씩
const chunks = [];

for (let i = 0; i < text.length; i += chunkSize) {
  chunks.push(text.slice(i, i + chunkSize));
}

return chunks.map((chunk, idx) => ({
  json: { chunk, index: idx, total: chunks.length }
}));

청크별 요약 — OpenAI 프롬프트

Model: gpt-4o-mini

Prompt:
다음 텍스트(전체 {{ $json.total }}개 파트 중 {{ $json.index + 1 }}번째)의
핵심 내용을 3~5줄로 한국어 요약해줘.

텍스트:
{{ $json.chunk }}

청크 요약 합치기 — Code 노드

const summaries = $input.all().map(i => i.json.message.content);
const combined = summaries.join('\n\n');

return [{ json: {
  partialSummaries: combined,
  chunkCount: summaries.length,
} }];

최종 1페이지 브리핑 — OpenAI 프롬프트

Model: gpt-4o

Prompt:
다음은 긴 문서의 파트별 요약입니다.
이를 바탕으로 경영진이 읽을 1페이지 브리핑 보고서를 작성해줘.

형식:
## 핵심 요약 (3줄)
## 주요 내용
## 시사점 및 액션아이템

파트별 요약:
{{ $json.partialSummaries }}
💡 TIPgpt-4o의 컨텍스트 윈도우는 128K 토큰입니다. 문서가 10만자 이하라면 청크 분할 없이 한 번에 보내는 것이 더 품질이 좋습니다. 청크 분할은 그보다 긴 문서에만 적용하세요.
⚡

워크플로우 JSON

아래 JSON을 복사해 n8n에 바로 임포트하세요

📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
  "recipeId": "recipe042",
  "title": "FAQ 키워드 매칭 → 자동 답변 발송",
  "chapter": 4,
  "category": "고객 응대 자동화",
  "difficulty": "⭐⭐",
  "estimatedTime": "30분",
  "description": "이메일 내용과 구글 시트 FAQ 키워드를 대조하여 매칭되면 자동 답변을 발송하고, 매칭되지 않으면 담당자에게 수동 답변 필요 알림을 보냅니다.",
  "apps": [
    "Gmail",
    "Google Sheets",
    "Slack"
  ],
  "nodes": [
    {
      "id": "trigger_gmail",
      "type": "trigger",
      "name": "Gmail Trigger - 새 문의 이메일 감지",
      "service": "gmail",
      "config": {
        "event": "newEmail",
        "filter": {
          "to": "={{ $env.SUPPORT_EMAIL }}"
        }
      }
    },
    {
      "id": "sheets_faq",
      "type": "action",
      "name": "Google Sheets - FAQ 목록 읽기",
      "service": "googleSheets",
      "config": {
        "operation": "readAllRows",
        "documentId": "={{ $env.FAQ_SHEET_ID }}",
        "sheetName": "FAQ"
      }
    },
    {
      "id": "function_match",
      "type": "function",
      "name": "Function - 키워드 매칭",
      "code": "const emailText = $node['trigger_gmail'].json['text'];\nconst faqList = $input.all();\nconst matched = faqList.find(row =>\n  row.json['키워드'].split(',').some(kw => emailText.includes(kw.trim()))\n);\nreturn [{ json: { matched: !!matched, answer: matched ? matched.json['답변'] : null, emailFrom: $node['trigger_gmail'].json['from'] } }];"
    },
    {
      "id": "if_matched",
      "type": "condition",
      "name": "키워드 매칭 여부",
      "config": {
        "conditions": [
          {
            "field": "={{ $json[\"matched\"] }}",
            "operator": "equals",
            "value": true
          }
        ]
      }
    },
    {
      "id": "gmail_auto_reply",
      "type": "action",
      "name": "Gmail - 자동 답변 발송",
      "service": "gmail",
      "config": {
        "to": "={{ $json[\"emailFrom\"] }}",
        "subject": "Re: 문의 주셔서 감사합니다",
        "body": "안녕하세요!\n\n문의해 주신 내용에 대한 답변입니다.\n\n{{ $json[\"answer\"] }}\n\n추가 문의사항이 있으시면 언제든지 연락 주세요.\n감사합니다."
      }
    },
    {
      "id": "slack_manual",
      "type": "action",
      "name": "Slack - 수동 답변 필요 알림",
      "service": "slack",
      "config": {
        "channel": "={{ $env.SLACK_CS_CHANNEL }}",
        "message": "📨 수동 답변이 필요한 이메일이 있어요!\n발신: {{ $json[\"emailFrom\"] }}\n→ FAQ에서 매칭되지 않은 문의입니다."
      }
    }
  ],
  "connections": [
    {
      "from": "trigger_gmail",
      "to": "sheets_faq"
    },
    {
      "from": "sheets_faq",
      "to": "function_match"
    },
    {
      "from": "function_match",
      "to": "if_matched"
    },
    {
      "from": "if_matched",
      "to": "gmail_auto_reply",
      "branch": "true"
    },
    {
      "from": "if_matched",
      "to": "slack_manual",
      "branch": "false"
    }
  ],
  "envVars": [
    {
      "key": "SUPPORT_EMAIL",
      "description": "고객 응대 전용 이메일 주소"
    },
    {
      "key": "FAQ_SHEET_ID",
      "description": "FAQ 구글 시트 ID"
    },
    {
      "key": "SLACK_CS_CHANNEL",
      "description": "CS팀 Slack 채널 ID"
    }
  ],
  "qrCodeUrl": "https://www.koreaaitimes.com/books/n8n-vol2/recipe042"
}
← 이전 레시피☰ 목차다음 레시피 →