n8n AI 워크플로우 구축

Claude·OpenAI·Gemini·Ollama를 n8n과 연동하여 AI 에이전트·RAG·멀티에이전트·Human-in-the-Loop 파이프라인을 구축하는 완전 실전 가이드

전제 조건: n8n이 설치되어 있어야 합니다. → n8n 설치 가이드

n8n AI 노드 생태계

n8n은 LangChain 기반의 AI 노드들을 기본 제공합니다. 코드 없이 AI 에이전트, RAG 파이프라인, 멀티모달 처리를 워크플로우로 구성할 수 있습니다.

AI Agent 노드 자율 판단 + 도구 사용 (ReAct) Basic LLM Chain / Summarization / Q&A 프롬프트 → LLM → 출력 (단순 체인) Anthropic (Claude) claude-opus-4-7 등 OpenAI Chat Model gpt-4.1, gpt-4.1-mini Ollama / Groq 로컬 / 고속 추론 Window Buffer Memory 최근 N개 대화 Redis Chat Memory 영속 세션 메모리 HTTP Request Tool 외부 API 호출 Workflow Tool 서브워크플로우 실행 Vector Store (RAG) Pinecone / Qdrant / Supabase pgvector / In-Memory

n8n AI 노드 계층: AI Agent가 LLM 모델·메모리·도구를 조합하여 자율 실행

AI 노드 전체 카탈로그

카테고리노드역할
ChainBasic LLM Chain프롬프트 → LLM → 텍스트 출력
Summarization Chain긴 문서 요약 (Map-Reduce 또는 Stuffing)
Retrieval Q&A Chain문서 기반 Q&A (벡터 스토어 결합)
Conversational Chain메모리 포함 대화형 체인
AgentAI AgentReAct 패턴, 자율 도구 선택·실행
LLM 모델Anthropic Chat ModelClaude API (claude-opus-4-7 등)
OpenAI Chat ModelGPT-4.1, GPT-4.1-mini 등
Google Gemini Chat ModelGemini 3.1 Pro / 3 Flash
Ollama Chat Model로컬 LLM (Llama, Mistral 등)
Groq Chat Model초고속 Llama 추론 (무료 티어)
Azure OpenAI Chat ModelAzure 배포 GPT 모델
메모리Window Buffer Memory최근 N개 메시지 보관 (인메모리)
Redis Chat MemoryRedis 기반 세션별 영속 메모리
Postgres Chat MemoryPostgreSQL 기반 영속 메모리
Motorhead MemoryMotorhead 서버 기반 요약 메모리
벡터 스토어In-Memory Vector Store임시 메모리 벡터 (테스트용)
Pinecone Vector StorePinecone 클라우드
Qdrant Vector StoreQdrant 셀프호스팅
Supabase Vector StoreSupabase pgvector
Chroma Vector StoreChromaDB 셀프호스팅
임베딩OpenAI Embeddingstext-embedding-3-small/large
Anthropic (via HTTP)voyage-3 등 별도 호출
Ollama Embeddings로컬 임베딩 (무료)
문서 로더Default Data LoaderBinary 데이터(PDF, DOCX, CSV 등)
GitHub Document LoaderGitHub 저장소 파일 로드
Notion Document LoaderNotion 페이지/DB 로드
JSON Document LoaderJSON 파일 로드
Recursive URL Loader웹사이트 크롤링 + 로드
텍스트 분할Recursive Character Text Splitter범용 (권장)
Character Text Splitter단순 문자 기준 분할
Token Text Splitter토큰 수 기준 정확한 분할
출력 파서Auto-fixing Output Parser파싱 실패 시 LLM이 자동 수정
Structured Output ParserJSON Schema 기반 구조화 출력
Item List Output Parser목록 형태 출력 파싱
도구 (Tool)Calculator수학 계산
HTTP Request Tool에이전트가 외부 API 호출
WikipediaWikipedia 검색
SerpAPIGoogle 검색 결과
n8n Workflow Tool서브워크플로우를 도구로 사용

AI 모델 연동 심화 (Anthropic·OpenAI·Gemini)

다중 프로바이더 지원: n8n은 Anthropic(Claude), OpenAI(GPT), Google(Gemini), Ollama(로컬 LLM), Groq 등 다양한 AI 프로바이더를 동일한 인터페이스로 지원합니다. 아래 예시는 Anthropic 기준이지만, 다른 프로바이더도 같은 패턴으로 연동할 수 있습니다.

자격증명 설정

# UI에서 자격증명 추가 — 프로바이더별 설정

## Anthropic (Claude)
Settings → Credentials → Add Credential → Anthropic
API Key: sk-ant-api03-...

## OpenAI (GPT)
Settings → Credentials → Add Credential → OpenAI
API Key: sk-proj-...

## Google Gemini
Settings → Credentials → Add Credential → Google AI (Gemini)
API Key: AIza...

# 환경 변수로도 설정 가능 (n8n이 자동으로 자격증명 생성)
ANTHROPIC_API_KEY=sk-ant-api03-...
OPENAI_API_KEY=sk-proj-...
GOOGLE_AI_API_KEY=AIza...

Basic LLM Chain 구성

# Basic LLM Chain 노드 설정 (Anthropic 예시)
Chat Model → Anthropic Chat Model
  Model: claude-opus-4-7
  Max Tokens: 4096
  Temperature: 0.7
  Top P: 0.9
  Extended Thinking: OFF (고급 추론 시 ON)

# 대안: OpenAI Chat Model → gpt-4.1 / gpt-4.1-mini
# 대안: Google Gemini Chat Model → gemini-3-flash
# 대안: Ollama Chat Model → llama3, mistral (로컬 무료)

Prompt:
  System: |
    당신은 전문적인 코드 리뷰어입니다.
    코드의 문제점을 구체적으로 지적하고 개선 방안을 제시하세요.
    응답은 반드시 한국어로 작성하세요.
  Human: {{ $json.code }}

HTTP Request로 LLM API 직접 호출

멀티모달(이미지 분석), 스트리밍, 캐시 제어 등 고급 기능은 HTTP Request 노드로 직접 호출합니다. 아래는 Anthropic API 예시이며, OpenAI는 https://api.openai.com/v1/chat/completions, Gemini는 https://generativelanguage.googleapis.com/v1beta/models/로 동일 패턴 적용이 가능합니다.

# HTTP Request 노드 — Anthropic Claude API 직접 호출 예시
Method: POST
URL: https://api.anthropic.com/v1/messages
Headers:
  x-api-key: {{ $env.ANTHROPIC_API_KEY }}
  anthropic-version: 2023-06-01
  content-type: application/json
  anthropic-beta: prompt-caching-2024-07-31   # 프롬프트 캐싱

Body (JSON):
{
  "model": "claude-opus-4-7",
  "max_tokens": 4096,
  "system": [
    {
      "type": "text",
      "text": "{{ $json.systemPrompt }}",
      "cache_control": { "type": "ephemeral" }
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "{{ $json.userMessage }}"
    }
  ]
}
// 응답 파싱 (Code 노드)
const resp = $json;
return [{
  json: {
    answer:       resp.content[0].text,
    inputTokens:  resp.usage.input_tokens,
    outputTokens: resp.usage.output_tokens,
    cacheRead:    resp.usage.cache_read_input_tokens ?? 0,
    cacheWrite:   resp.usage.cache_creation_input_tokens ?? 0,
    stopReason:   resp.stop_reason,
    // 비용 추정 (claude-opus-4-7 기준, 모델별 단가 상이)
    costUSD: (resp.usage.input_tokens / 1e6 * 5) +
             (resp.usage.output_tokens / 1e6 * 25),
  }
}];

이미지 분석 (Vision)

# 이미지 URL → Anthropic Vision 분석 (OpenAI·Gemini도 유사 API 제공)
## HTTP Request 노드 Body
{
  "model": "claude-opus-4-7",
  "max_tokens": 2048,
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "image",
          "source": {
            "type": "url",
            "url": "{{ $json.imageUrl }}"
          }
        },
        {
          "type": "text",
          "text": "이 이미지를 자세히 설명하고, 주요 객체를 JSON 배열로 나열하세요."
        }
      ]
    }
  ]
}
# Binary 이미지 → Base64 → LLM Vision API

## Code 노드 — Binary를 Base64로 변환
const item = $input.first();
const base64 = item.binary.data.data;  // 이미 base64
const mimeType = item.binary.data.mimeType;

return [{ json: { base64, mimeType } }];
## HTTP Request Body (base64 이미지)
{
  "model": "claude-opus-4-7",
  "max_tokens": 2048,
  "messages": [{
    "role": "user",
    "content": [
      {
        "type": "image",
        "source": {
          "type": "base64",
          "media_type": "{{ $json.mimeType }}",
          "data": "{{ $json.base64 }}"
        }
      },
      { "type": "text", "text": "{{ $json.prompt }}" }
    ]
  }]
}

출력 파서 (Output Parser)

LLM의 자유 형식 텍스트 출력을 구조화된 데이터로 변환합니다. 이후 노드에서 $json.fieldName으로 바로 접근할 수 있어 워크플로우 연결이 매우 간편해집니다.

Structured Output Parser

# Basic LLM Chain + Structured Output Parser 구성

Output Parser → Structured Output Parser
  Schema Type: Manual
  Attributes:
    - Name: category
      Type: string
      Description: "분류 카테고리 (결제/기술/계정/기타 중 하나)"
    - Name: severity
      Type: options
      Options: 긴급, 높음, 보통, 낮음
      Description: "심각도 수준"
    - Name: summary
      Type: string
      Description: "50자 이내 한국어 요약"
    - Name: requiresHuman
      Type: boolean
      Description: "인간 담당자 처리 필요 여부"

# 프롬프트에 파서 지침이 자동 추가됨
# 출력 결과 → 바로 $json.category, $json.severity 로 접근
// 파싱 결과 예시
{
  "category": "결제",
  "severity": "긴급",
  "summary": "신용카드 결제 실패, 즉시 처리 필요",
  "requiresHuman": true
}

Auto-fixing Output Parser

LLM이 잘못된 형식을 반환하면, 에러 메시지와 함께 LLM에게 자동으로 재요청하여 수정합니다.

# Auto-fixing Output Parser 설정
Output Parser → Auto-fixing Output Parser
  Parser: Structured Output Parser (내부에 구조 정의)
  Max Retries: 3    # 최대 수정 재시도 횟수

# 동작 방식
1. LLM 출력 파싱 시도
2. 실패 → LLM에 에러 메시지와 함께 재요청
   "다음 에러를 수정하세요: JSON parse error at line 3..."
3. 최대 Retry 횟수까지 반복
4. 여전히 실패 → 노드 에러 처리

Code 노드로 수동 파싱

// LLM 출력에서 JSON 추출 (마크다운 코드블록 포함 경우)
const text = $json.text || $json.output;

// ```json ... ``` 블록 추출
const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
if (jsonMatch) {
  const parsed = JSON.parse(jsonMatch[1].trim());
  return [{ json: parsed }];
}

// 순수 JSON 파싱 시도
try {
  const parsed = JSON.parse(text.trim());
  return [{ json: parsed }];
} catch {
  // 정규식으로 키-값 추출 (폴백)
  const category = text.match(/category[:\s]+([^\n,}]+)/i)?.[1]?.trim();
  return [{ json: { category, rawText: text } }];
}

AI Agent 노드 완전 가이드

AI Agent 노드는 LLM이 스스로 "어떤 도구를 쓸지" 판단하고, 도구 실행 결과를 바탕으로 다음 행동을 결정하는 ReAct 패턴을 구현합니다.

사용자 질문 "BTC 현재 가격?" LLM (Chat Model) ① Thought 도구 선택 판단 ② Action 도구 호출 요청 ③ Observation 도구 결과 수신 ④ Final Answer 최종 응답 HTTP Request Tool CoinGecko API Calculator Tool 변동률 계산 Workflow Tool 서브워크플로우 최종 응답 "BTC: $XX,XXX"

AI Agent ReAct 루프: Thought → Action(도구 호출) → Observation → 반복 → Final Answer

AI Agent 핵심 설정

# AI Agent 노드 전체 설정 (Anthropic 예시)

Chat Model → Anthropic Chat Model
  Model: claude-opus-4-7         # 또는 OpenAI: gpt-4.1 / Gemini: gemini-3-flash
  Temperature: 0          # 도구 사용 시 결정론적 행동 권장
  Max Tokens: 4096

Memory → Window Buffer Memory
  Context Window Length: 10

Max Iterations: 10        # 무한 루프 방지 (도구 최대 호출 횟수)
Return Intermediate Steps: true  # 중간 Thought/Action 포함 출력

System Prompt: |
  당신은 유용한 AI 어시스턴트입니다.
  주어진 도구를 적극 활용하여 정확한 답변을 제공하세요.
  최종 답변은 반드시 한국어로 작성하세요.
  모르는 정보는 추측하지 말고 도구로 확인하세요.

Human Message: {{ $json.userMessage }}

도구(Tool) 설정 상세

# HTTP Request Tool — 주식/암호화폐 가격 조회
Name: get_crypto_price
Description: |
  암호화폐의 현재 가격과 24시간 변동률을 조회합니다.
  id 파라미터에 코인 ID를 입력하세요.
  예: bitcoin, ethereum, ripple
Method: GET
URL: https://api.coingecko.com/api/v3/simple/price
Query Parameters:
  ids: {{ $parameter.id }}
  vs_currencies: usd,krw
  include_24hr_change: true
# n8n Workflow Tool — 복잡한 DB 조회를 서브워크플로우로
Name: get_customer_info
Description: |
  고객 ID로 고객 정보(이름, 이메일, 주문 이력)를 조회합니다.
  customer_id 파라미터에 고객 ID(숫자)를 입력하세요.
Workflow: "고객 정보 조회 서브워크플로우"

# 서브워크플로우 내부:
Execute Workflow Trigger
  ↓
PostgreSQL
  Query: |
    SELECT c.*, json_agg(o.*) as orders
    FROM customers c
    LEFT JOIN orders o ON o.customer_id = c.id
    WHERE c.id = {{ $json.customer_id }}
    GROUP BY c.id
  ↓
Respond to Workflow

에이전트 시스템 프롬프트 설계

# 고객 지원 에이전트 시스템 프롬프트 예시
당신은 [회사명] 공식 고객 지원 AI입니다.

## 역할과 권한
- 주문 조회, 배송 상태 확인, 반품/교환 안내 가능
- 환불 처리는 50,000원 이하만 직접 처리 가능
- 50,000원 초과 또는 법적 분쟁 → 인간 담당자 연결

## 도구 사용 규칙
- 고객 정보 조회 시 반드시 get_customer_info 도구 사용
- 주문 상태 확인 시 반드시 get_order_status 도구 사용
- 추측으로 주문 상태를 답변하지 말 것

## 응답 형식
- 친절하고 공감적인 어조 유지
- 전문 용어 대신 쉬운 표현 사용
- 해결이 어려우면 담당자 연결 제안

## 개인정보 보호
- 전화번호, 신용카드 번호를 응답에 포함하지 말 것
- 이메일은 마스킹 처리: hong***@example.com

메모리 전략

메모리 종류 비교

메모리 타입영속성토큰 사용적합한 사용처세션 분리
Window Buffer인메모리 (임시)최근 N개 × 메시지 길이단일 실행 내 대화실행 ID 기준
Redis ChatRedis에 영속설정한 Window 크기다중 세션, 챗봇Session ID 키
Postgres ChatDB에 영속설정한 Window 크기대화 이력 분석 필요 시Session ID 컬럼
없음(Stateless)없음없음단발성 질의, 분류·요약-

세션별 메모리 관리

# Redis Chat Memory — 사용자별 독립 메모리

AI Agent
  Memory → Redis Chat Memory
    Session Key: {{ $json.userId }}        # 사용자별 분리
    Session ID: {{ $json.sessionId }}      # 또는 대화 세션별 분리
    Context Window Length: 20             # 최근 20개 메시지
    Redis Credential: (Redis 자격증명)

# Telegram 봇 예시 — chat.id로 세션 분리
Session Key: {{ $json.message.chat.id }}
// Code 노드 — 오래된 메모리 수동 정리 (Redis)
// 특정 사용자의 대화 이력 초기화
const userId = $json.userId;
const sessionKey = `n8n:${userId}:history`;

// 다음 Redis 노드에서 DEL 명령 실행
return [{ json: { sessionKey } }];

RAG 파이프라인 완전 구축

문서 로더 종류

로더지원 형식특이사항
Default Data Loader (Binary)PDF, DOCX, TXT, HTML, CSV, JSONBinary 노드 출력을 연결
GitHub Document LoaderGitHub 저장소 파일특정 디렉토리·확장자 필터 가능
Notion Document LoaderNotion 페이지·DBNotion API 자격증명 필요
Recursive URL Loader웹페이지 (크롤링)최대 깊이, 도메인 제한 설정
JSON Document LoaderJSON 파일/구조특정 키만 텍스트로 추출 가능

텍스트 분할기 비교

분할기분할 기준권장 설정적합한 경우
Recursive Character\n\n → \n → 공백 → 문자Chunk: 1000, Overlap: 200범용 (가장 추천)
Character단일 구분자 (기본: \n\n)Chunk: 2000, Overlap: 200문단 기준 명확한 문서
TokenLLM 토큰 수 기준Chunk: 512 tokens토큰 한도 정확히 제어 시

워크플로우 1: 문서 인덱싱 파이프라인

# 문서 → 청크 → 임베딩 → 벡터 DB 저장

## 트리거: 파일 업로드 Webhook
Webhook Trigger (multipart/form-data)
  ↓
## 메타데이터 추출
Code 노드
  const filename = $binary.data.fileName;
  const source = $json.source ?? 'upload';
  const uploadedBy = $json.uploadedBy ?? 'system';
  return [{ json: { filename, source, uploadedBy }, binary: $input.first().binary }];
  ↓
## 중복 체크 (선택)
Supabase 노드
  Query: SELECT id FROM documents WHERE filename = '{{ $json.filename }}'
  ↓
IF (이미 존재하면) → 409 응답 반환

## 문서 → 텍스트 청크 분할
Default Data Loader
  Data Type: Binary (자동 감지: PDF/DOCX/TXT)
  Text Splitter → Recursive Character Text Splitter
    Chunk Size: 1000
    Chunk Overlap: 200
    Separators: ["\n\n", "\n", " ", ""]
  ↓
## 임베딩 생성 + 벡터 DB 저장
Supabase Vector Store
  Operation: Insert Documents
  Embedding → OpenAI Embeddings (text-embedding-3-small)
  Table: documents
  Query Name: match_documents
  Metadata:
    source: {{ $json.filename }}
    uploadedBy: {{ $json.uploadedBy }}
    uploadedAt: {{ $now.toISO() }}
  ↓
## 완료 응답
Respond to Webhook
  Body: { "success": true, "chunks": {{ $input.all().length }} }

워크플로우 2: RAG 질의응답

# 질문 → 벡터 검색 → LLM 답변 생성

Webhook Trigger
  Body: { "question": "...", "userId": "...", "topK": 5 }
  ↓
## 방법 A: Retrieval Q&A Chain (간단)
Retrieval Q&A Chain
  Chat Model → Anthropic (claude-opus-4-7)   # 또는 OpenAI (gpt-4.1) / Gemini 등
  Vector Store → Supabase (Retrieve Documents)
    Query: {{ $json.question }}
    Top K: {{ $json.topK ?? 5 }}
  Prompt Template: |
    다음 문서를 참고하여 질문에 답변하세요.
    문서에 없는 내용은 "문서에서 확인할 수 없습니다"라고 답변하세요.

    문서:
    {context}

    질문: {question}
  ↓
Respond to Webhook (answer + sources)
## 방법 B: AI Agent + Vector Store Tool (더 유연)

AI Agent
  Chat Model: Anthropic claude-opus-4-7  # 또는 OpenAI gpt-4.1 등
  Memory: Redis Chat Memory (userId 키)
  Tools:
    Vector Store Retriever Tool
      Vector Store: Supabase
      Name: search_documents
      Description: "내부 문서에서 관련 정보를 검색합니다. query에 검색할 내용을 입력하세요."
      Top K: 5
      Filter: { "source": "{{ $json.docSource }}" }  # 특정 문서만

  System Prompt: |
    당신은 내부 문서 기반 AI 어시스턴트입니다.
    반드시 search_documents 도구로 문서를 확인한 후 답변하세요.
    출처 파일명을 항상 명시하세요.
    문서에 없는 내용은 솔직히 모른다고 하세요.

  Human: {{ $json.question }}

고급 RAG 기법

// 하이브리드 검색: 벡터 유사도 + 키워드 검색 결합

// 1. 벡터 검색 (의미적 유사도)
Supabase Vector Store Retrieve → 상위 10개

// 2. PostgreSQL 키워드 검색 (Full-Text Search)
PostgreSQL:
  SELECT *, ts_rank(to_tsvector('korean', content), query) AS rank
  FROM documents, to_tsquery('korean', '{{ $json.keywords }}') query
  WHERE to_tsvector('korean', content) @@ query
  ORDER BY rank DESC LIMIT 10

// 3. Code 노드 — 결과 병합 및 중복 제거
const vector = $items("Vector Store").map(i => i.json);
const keyword = $items("PostgreSQL").map(i => i.json);
const merged = [...vector, ...keyword];
const seen = new Set();
const unique = merged.filter(d => {
  if (seen.has(d.id)) return false;
  seen.add(d.id);
  return true;
});
return [{ json: { documents: unique.slice(0, 8) } }];
  ↓
// 4. LLM에 컨텍스트와 함께 전달
// 쿼리 재작성 (Query Rewriting) — 검색 품질 향상

Basic LLM Chain (쿼리 재작성 전용, 빠른 모델 사용)
  Chat Model: claude-haiku-4-5   # 또는 gpt-4.1-mini, gemini-3-flash (경량 모델 권장)
  Prompt: |
    대화 이력과 사용자 질문을 보고, 문서 검색에 최적화된
    독립적인 검색 쿼리를 한국어로 작성하세요.
    대화 이력 없이도 이해 가능한 완전한 쿼리여야 합니다.

    대화 이력: {{ $json.history ?? "없음" }}
    사용자 질문: {{ $json.question }}

    검색 쿼리만 출력 (설명 없이):
  ↓
벡터 DB 검색 (재작성된 쿼리로)

멀티에이전트 패턴

패턴 1: 병렬 전문가 에이전트

# 하나의 복잡한 질문을 여러 전문 에이전트가 병렬 처리

Webhook Trigger ("분기별 실적 분석해줘")
  ↓
Code 노드 (질문 분해)
  return [
    { json: { question: "Q1-Q2 매출 트렌드", agent: "sales" } },
    { json: { question: "비용 구조 분석", agent: "finance" } },
    { json: { question: "시장 점유율 변화", agent: "market" } },
  ];
  ↓ (3개 아이템, 병렬 처리)

## 각 아이템에 대해 담당 에이전트 라우팅
Switch 노드 ({{ $json.agent }}으로 분기)
  "sales"  → 매출 분석 에이전트 (DB Tool + Chart Tool)
  "finance"→ 재무 분석 에이전트 (DB Tool + Calculator)
  "market" → 시장 분석 에이전트 (Web Search Tool + DB Tool)
  ↓ (Merge: Append)

## 결과 통합 에이전트
AI Agent (통합 요약)
  System: "세 전문가의 분석을 종합하여 경영 보고서를 작성하세요."
  Human: "분석 결과:\n{{ $json.allResults }}"

패턴 2: 슈퍼바이저 에이전트

# 슈퍼바이저가 전문 에이전트들을 지휘

Chat Trigger (사용자 요청)
  ↓
슈퍼바이저 AI Agent
  System: |
    당신은 팀 슈퍼바이저입니다.
    사용자 요청을 분석하고 적절한 전문 에이전트에게 작업을 할당하세요.
    사용 가능한 에이전트:
    - research_agent: 웹 검색, 정보 수집
    - code_agent: 코드 작성, 디버깅
    - data_agent: 데이터 분석, 시각화
    결과를 검토하고 최종 답변을 사용자에게 전달하세요.
  Tools:
    → research_agent (Workflow Tool)
    → code_agent (Workflow Tool)
    → data_agent (Workflow Tool)

패턴 3: Human-in-the-Loop

# AI 처리 → 사람 검토 → 승인/거절 → 계속 실행

Webhook Trigger (자동화 요청)
  ↓
AI Agent (초안 작성)
  ↓
## 사람 검토 요청 (Slack에 승인 요청)
Slack 노드
  Text: "AI가 다음 초안을 작성했습니다:\n{{ $json.draft }}\n승인하시겠습니까?"
  Blocks:
    - type: actions
      elements:
        - type: button
          text: "✅ 승인"
          action_id: approve
          value: "{{ $execution.resumeUrl }}?action=approve"
        - type: button
          text: "❌ 거절"
          action_id: reject
          value: "{{ $execution.resumeUrl }}?action=reject"
          style: danger
  ↓
## Webhook 재개 대기 (최대 24시간)
Wait 노드
  Resume: On Webhook Call
  Webhook Suffix: /approval/{{ $execution.id }}
  Max Wait Time: 86400   # 24시간 후 자동 타임아웃## 승인/거절 처리
IF ({{ $json.action }} === "approve")
  True → 실제 실행 (이메일 발송, DB 저장 등)
  False → 취소 알림 + 로그
# Wait 노드 재개 URL 호출 방법

## Slack 버튼 클릭 시 n8n으로 재개 신호 전송
## action_id에 따라 resumeUrl에 파라미터 추가

## 외부에서 재개 호출 (curl 예시)
curl -X POST "{{ $execution.resumeUrl }}" \
  -H "Content-Type: application/json" \
  -d '{"action": "approve", "approvedBy": "manager@company.com"}'

실전 AI 자동화 사례

사례 1: Slack AI 분류 & 자동 라우팅

# Slack 새 메시지 → AI 분류 → 담당자 태그 + DB 로그

Slack Trigger (새 메시지)
  Channel: #customer-support
  ↓
Basic LLM Chain (경량 모델: claude-haiku-4-5 / gpt-4.1-mini / gemini-3-flash)
  System: |
    고객 메시지를 JSON으로만 분류하세요.
    category: ["결제", "기술", "계정", "배송", "일반", "기타"]
    severity: ["긴급", "높음", "보통", "낮음"]
    sentiment: ["화남", "불만", "중립", "만족"]
    language: ["한국어", "영어", "기타"]
  User: {{ $json.text }}

Output Parser → Structured Output Parser
  category, severity, sentiment, language (모두 string)
  ↓
Code 노드 (담당자 매핑)
  const assigneeMap = {
    "결제": { user: "U01FINANCE", channel: "#finance-support" },
    "기술": { user: "U02DEVTEAM", channel: "#dev-support" },
    "계정": { user: "U03OPSCORE", channel: "#ops-support" },
  };
  const assignee = assigneeMap[$json.category] ?? { user: "U04GENERAL" };
  return [{ json: { ...$json, assignee } }];
  ↓
[병렬]
  Slack (원본 채널에 분류 태그 추가)
    Thread TS: {{ $json.ts }}
    Text: "카테고리: {{ $json.category }} | 심각도: {{ $json.severity }}"
  PostgreSQL (티켓 생성)
    INSERT INTO support_tickets ...
  IF (severity == "긴급")
    → Slack DM to assignee.user (즉시 알림)

사례 2: GitHub PR AI 코드 리뷰

# PR 오픈 → diff 가져오기 → AI 리뷰 → GitHub 코멘트

GitHub Trigger
  Event: Pull Request, Action: opened/synchronize
  ↓
Code 노드 (PR 메타데이터)
  const pr = $json.pull_request;
  return [{ json: {
    title: pr.title,
    author: pr.user.login,
    diffUrl: pr.diff_url,
    commentsUrl: pr.comments_url,
    prNumber: pr.number,
    repoFullName: $json.repository.full_name,
  }}];
  ↓
HTTP Request (diff 다운로드)
  URL: {{ $json.diffUrl }}
  Headers: Authorization: token {{ $env.GITHUB_TOKEN }}, Accept: application/vnd.github.v3.diff
  ↓
Code 노드 (diff 전처리)
  const diff = $json.data;
  const MAX_CHARS = 12000;
  const truncated = diff.length > MAX_CHARS
    ? diff.slice(0, MAX_CHARS) + '\n... (이하 생략)'
    : diff;
  const addedLines = (diff.match(/^\+[^+]/mg) ?? []).length;
  const removedLines = (diff.match(/^-[^-]/mg) ?? []).length;
  return [{ json: { diff: truncated, addedLines, removedLines } }];
  ↓
Basic LLM Chain (고성능 모델: claude-opus-4-7 / gpt-4.1 / gemini-3.1-pro)
  System: |
    당신은 시니어 소프트웨어 엔지니어입니다.
    PR 코드 변경사항을 분석하고 건설적인 피드백을 작성하세요.

    ## 리뷰 항목 (중요도 순)
    1. 🐛 버그 및 잠재적 오류
    2. 🔒 보안 취약점
    3. ⚡ 성능 이슈
    4. 🏗️ 코드 구조 및 가독성
    5. 🧪 테스트 커버리지
    6. ✅ 잘된 점

    각 항목에 해당하는 내용이 없으면 생략하세요.
    구체적인 코드 라인을 인용하면 더 좋습니다.
  User: |
    PR 제목: {{ $node["Code"].json.title }}
    작성자: {{ $node["Code"].json.author }}
    변경: +{{ $node["Code 1"].json.addedLines }}줄 / -{{ $node["Code 1"].json.removedLines }}줄

    코드 변경사항:
    ```diff
    {{ $json.diff }}
    ```
  ↓
HTTP Request (GitHub 코멘트 등록)
  URL: https://api.github.com/repos/{{ $node["Code"].json.repoFullName }}/issues/{{ $node["Code"].json.prNumber }}/comments
  Method: POST
  Headers: Authorization: token {{ $env.GITHUB_TOKEN }}
  Body: { "body": "## 🤖 AI 코드 리뷰\n\n{{ $json.text }}\n\n---\n*자동 생성된 리뷰입니다. 참고용으로 활용하세요.*" }

사례 3: AI 콘텐츠 생성 파이프라인

# 주제 입력 → AI 리서치 → 초안 작성 → SEO 최적화 → 발행

Webhook Trigger
  Body: { "topic": "n8n으로 AI 자동화 구축하기", "language": "ko", "targetLength": 1500 }
  ↓
AI Agent (리서치 에이전트)
  Tools: Wikipedia, SerpAPI, HTTP Request (뉴스 API)
  System: 주제에 대한 최신 정보를 수집하고 JSON으로 요약하세요.
  ↓
Basic LLM Chain (초안 작성, claude-opus-4-7 / gpt-4.1 등 고성능 모델)
  Prompt: |
    리서치 결과를 바탕으로 블로그 포스트 초안을 작성하세요.
    - 언어: {{ $json.language }}
    - 목표 길이: {{ $json.targetLength }}자
    - H2/H3 구조, 예제 코드 포함
    - SEO 최적화된 제목과 소제목

    리서치 결과:
    {{ $json.research }}
  ↓
Basic LLM Chain (SEO 메타데이터 추출, claude-haiku-4-5 / gpt-4.1-mini 등 경량 모델)
  Prompt: |
    다음 블로그 포스트에서 SEO 메타데이터를 JSON으로 추출하세요.
    - title: SEO 최적화 제목 (60자 이내)
    - description: 메타 설명 (160자 이내)
    - keywords: 핵심 키워드 배열 (5-10개)
    - readingTime: 예상 읽기 시간 (분)

    {{ $json.text }}

Output Parser → Structured Output Parser
  ↓
[병렬]
  HTTP Request (WordPress API 발행 또는 Notion 저장)
  Google Sheets (콘텐츠 캘린더 기록)
  Slack (팀 알림: 새 포스트 초안 완료)

사례 4: AI 장애 대응 자동화

# 모니터링 알림 → AI 원인 분석 → 자동 복구 시도 → 에스컬레이션

Webhook Trigger (Prometheus AlertManager)
  Body: { "alertname": "HighCPUUsage", "service": "api-server", "severity": "critical" }
  ↓
Code 노드 (경보 파싱)
  const alert = $json.alerts[0];
  return [{ json: {
    alertname: alert.labels.alertname,
    service: alert.labels.service,
    severity: alert.labels.severity,
    startedAt: alert.startsAt,
    description: alert.annotations.description,
  }}];
  ↓
[병렬]
  HTTP Request (최근 로그 조회 - Loki/Elasticsearch)
  HTTP Request (메트릭 조회 - Prometheus)
  PostgreSQL (최근 배포 이력)
  ↓ (Merge)
AI Agent (원인 분석 + 복구 방안)
  System: |
    DevOps 전문가로서 장애 원인을 분석하고 즉시 조치 방안을 제시하세요.
    제공된 도구로 추가 조사를 할 수 있습니다.
    복구 명령어는 반드시 실행 전 승인을 요청하세요.
  Tools:
    → SSH Command Tool (서버 명령어 실행)
    → Kubernetes API Tool (Pod 재시작 등)
  User: |
    장애 내용:
    {{ $json.description }}

    최근 로그: {{ $json.logs }}
    메트릭: {{ $json.metrics }}
    최근 배포: {{ $json.deployments }}
  ↓
Slack 노드 (즉시 알림 + AI 분석 결과)
  Channel: #incidents
  Text: |
    🚨 *{{ $json.alertname }}* - {{ $json.service }}
    AI 분석: {{ $json.output }}
  ↓
IF (severity == "critical" && 자동 복구 제안 있음)
  → Human-in-the-Loop (승인 후 복구 실행)
  → PagerDuty (온콜 담당자 호출)

사례 5: AI 리드 스코어링

# CRM 신규 리드 → AI 분석 → 점수 산출 → 영업팀 라우팅

HubSpot Trigger (새 Contact 생성)
  ↓
HTTP Request (회사 정보 보강 - Clearbit/Apollo)
  URL: https://company.clearbit.com/v2/companies/find
  Query: domain={{ $json.company.domain }}
  ↓
Basic LLM Chain (claude-opus-4-7 / gpt-4.1 등 고성능 모델)
  System: |
    B2B SaaS 영업 전문가로서 리드를 분석하고 점수를 산출하세요.

    점수 기준 (0-100점):
    - 회사 규모 (직원 수): 대기업 30점, 중기업 20점, 소기업 10점
    - 업종 적합성: AI/Tech 25점, 제조 15점, 서비스 10점
    - 타이틀 적합성: C레벨/VP 20점, 매니저 15점, 일반 5점
    - 인게이지먼트: 데모 신청 25점, 콘텐츠 다운 15점, 방문만 5점

    JSON으로만 응답: { "score": number, "tier": "A|B|C", "reason": string, "nextAction": string }
  User: |
    이름: {{ $json.firstname }} {{ $json.lastname }}
    직책: {{ $json.jobtitle }}
    회사: {{ $json.company }}
    직원 수: {{ $json.company_size }}
    업종: {{ $json.industry }}
    유입 경로: {{ $json.lead_source }}

Output Parser → Structured Output Parser
  ↓
HubSpot 노드 (리드 점수 업데이트)
  Update Contact Property: lead_score, lead_tier, ai_reason
  ↓
Switch (tier)
  "A" → 영업팀 즉시 알림 + 자동 미팅 일정 제안
  "B" → 이메일 시퀀스 등록
  "C" → 뉴스레터만 구독

프롬프트 보안

프롬프트 인젝션 방지

// Code 노드 — 사용자 입력 위생처리
const userInput = $json.userMessage;

// 1. 길이 제한
if (userInput.length > 2000) {
  throw new Error('입력이 너무 깁니다 (최대 2000자)');
}

// 2. 인젝션 패턴 감지
const injectionPatterns = [
  /ignore\s+(all\s+)?previous\s+instructions/i,
  /system\s+prompt/i,
  /jailbreak/i,
  /\[INST\]/i,
  /<system>/i,
];
for (const pattern of injectionPatterns) {
  if (pattern.test(userInput)) {
    throw new Error('허용되지 않는 입력입니다');
  }
}

// 3. 특수 문자 이스케이프 (SQL 인젝션 방지)
const sanitized = userInput
  .replace(/[<>&"']/g, c => ({
    '<': '<', '>': '>', '&': '&',
    '"': '"', "'": '''
  }[c]));

return [{ json: { sanitizedInput: sanitized } }];

Rate Limiting

// Code 노드 — 사용자별 요청 제한 (Redis 기반)
const userId = $json.userId;
const key = `ratelimit:${userId}:${$now.toFormat('yyyy-MM-dd-HH')}`;
const MAX_REQUESTS_PER_HOUR = 20;

// 다음 Redis 노드에서:
// INCR key → TTL 3600 → IF count > MAX → 429 반환
return [{ json: { ratelimitKey: key, maxRequests: MAX_REQUESTS_PER_HOUR } }];

AI 비용 최적화

모델 라우팅 전략

// Code 노드 — 복잡도 기반 모델 자동 선택
const { prompt, taskType } = $json;
const tokenEstimate = Math.ceil(prompt.length / 3.5);

let model, temperature;

// Anthropic 모델 기준 예시 (OpenAI: gpt-4.1-mini → gpt-4.1, Gemini: flash → pro)
if (taskType === 'classification' || tokenEstimate < 500) {
  model = 'claude-haiku-4-5';  // 빠르고 저렴 (대안: gpt-4.1-mini, gemini-3-flash)
  temperature = 0;
} else if (taskType === 'code' || tokenEstimate < 2000) {
  model = 'claude-sonnet-4-6';  // 균형 (대안: gpt-4.1, gemini-3.1-pro)
  temperature = 0.3;
} else {
  model = 'claude-opus-4-7';    // 복잡한 추론 (대안: gpt-4.1, gemini-3.1-pro)
  temperature = 0.7;
}

return [{ json: { ...($json), model, temperature } }];

프롬프트 캐싱 (Anthropic 고유 기능)

Anthropic Claude API는 프롬프트 캐싱을 지원하여 반복 호출 시 비용을 크게 절감할 수 있습니다. OpenAI는 자동 캐싱(Predicted Outputs)을, Gemini는 Context Caching을 별도로 제공합니다.

# Anthropic 전용: 긴 시스템 프롬프트에 캐시 활성화 → 비용 90% 절감
# 최소 1024 토큰 이상인 시스템 프롬프트에 적용

{
  "system": [
    {
      "type": "text",
      "text": "{{ $json.longSystemPrompt }}",
      "cache_control": { "type": "ephemeral" }  # 이 부분 캐시
    }
  ],
  "messages": [
    { "role": "user", "content": "{{ $json.userMessage }}" }
  ]
}

# 캐시 히트 시 비용
# 입력 토큰: $5/MTok → $0.50/MTok (90% 절감)
# 유효 시간: 5분 또는 1시간 (호출할 때마다 갱신)
작업 유형권장 모델 (Anthropic)대안 (OpenAI / Gemini)이유
분류·태깅·감정분석claude-haiku-4-5gpt-4.1-mini / gemini-3-flash단순 작업, 속도·비용 우선
요약·번역·추출claude-haiku-4-5 / sonnetgpt-4.1-mini / gemini-3-flash충분한 품질, 저비용
코드 생성·리뷰claude-sonnet-4-6gpt-4.1 / gemini-3.1-pro품질-비용 균형
복잡한 추론·에이전트claude-opus-4-7gpt-4.1 / gemini-3.1-pro최고 품질 필요
대량 반복 처리Ollama (로컬 LLM: Llama, Mistral 등)비용 제로, 프라이버시
빠른 추론 (저지연)Groq (Llama)무료 티어, 초고속

다음 단계

📚 관련 가이드