2강

n8n × OpenAI 연동

OpenAI 노드 검색·추가

n8n 에서 GPT를 부르는 가장 간단한 방법은 OpenAI 노드를 쓰는 것입니다. 노드 검색창에 open 만 입력해도 상단에 나옵니다.

노드 검색창 → 'open' → OpenAI 선택
💡
OpenAI 노드는 단발성 프롬프트에 좋고, 대화 기록·메모리·라우팅이 필요하면 뒤에 나오는 AI Agent 를 씁니다.

기본 사용법 — Message a Model

OpenAI 노드에서 가장 많이 쓰는 액션이 Message a Model 입니다. Credential(API 키) 등록 후 Resource=Text, Operation=Message a Model 로 시작합니다.

Resource: Text · Operation: Message a Model

모델 선택 (GPT-4o / GPT-5.5 등)

모델은 From list 로 드롭다운에서 고르는 게 편합니다. 기본은 GPT-4o 또는 GPT-5.5.

From list → GPT-4o / GPT-5.5 등
💡
간단한 대량 처리·초저비용은 5 mini, 일반 대화·분류·요약은 4o, 논리 추론·복잡한 지침 준수는 5.5 이상 권장. 비용은 모델별로 다르니 대량 처리 전에는 가격표 확인.

Role 개념 — User · Assistant · System

GPT에게 메시지를 보낼 때 Role을 지정합니다. 3가지가 있어요.

Role 드롭다운 — User / Assistant / System
  • User — 사용자가 보내는 메시지. 실제 질문/명령.
  • Assistant — 모델이 이전에 응답한 내용. 대화 이력을 넘겨줄 때.
  • System — 모델의 기본 성격·규칙·컨텍스트를 정하는 지침. 대화 시작 전에 세팅.
💡
실무에서는 System 으로 성격/포맷을 잡고 → User 로 실제 질문을 던지는 조합이 가장 흔합니다.

System · User 프롬프트 설정

메시지는 여러 개를 순서대로 쌓아 보낼 수 있습니다. 보통 System 먼저, User 다음 순서로 넣고, Add Message 로 계속 추가할 수 있어요.

① System 메시지로 규칙 지정 → ② User 메시지로 실제 질문

System — 모델의 기본 성격·규칙·응답 스타일을 정합니다. 한 번만 세팅하면 대화 내내 유지됩니다. 예를 들어 답변 언어, 문장 수 제한, 존댓말 여부, 응답 포맷(JSON, 마크다운 등)까지 여기에 명시합니다.

  • 역할 정의 — "당신은 ○○ 담당자입니다" 처럼 정체성을 부여
  • 규칙 목록 — 번호로 나열하면 모델이 잘 지킴
  • 출력 포맷 — 자유 텍스트인지, JSON인지, 마크다운인지 명시
  • 금지 사항 — "~하지 마세요" 는 위쪽에 강조
System 프롬프트 (샘플) text
당신은 친절한 고객센터 상담원입니다.

다음 규칙을 지켜 답변하세요.
1. 항상 한국어로 답변합니다.
2. 답변은 3문장 이내로 작성합니다.
3. 고객에게 정중하게 말합니다.
4. 확인되지 않은 사실은 추측하지 않습니다.

User — 실제 사용자의 질문·요청이 들어가는 자리입니다. n8n 워크플로우에서는 여기에 앞 노드의 값(예: 폼 입력, 이메일 본문)을 표현식으로 넣는 게 일반적입니다.

  • 실제 대화라면 사용자가 방금 던진 질문 그대로
  • 자동화라면 {{ $json.문의내용 }} 처럼 앞 노드의 값 참조
  • 여러 질문이면 Add Message 로 User 메시지를 여러 개 스택 가능
User 프롬프트 (샘플) text
배송이 5일째 오지 않고 있습니다. 언제 받을 수 있나요?
💡
System 에 출력 포맷(JSON, 마크다운 등)까지 명시해두면 뒤 노드에서 JSON.parse($json.output) 로 안전하게 값을 꺼낼 수 있습니다. 자동화에서는 이게 가장 흔한 실패 지점 이니 처음부터 포맷을 못박아 두세요.

프롬프트 엔지니어링이란 무엇인가

프롬프트 엔지니어링(Prompt Engineering) 은 AI 모델에게 원하는 결과를 얻기 위해 입력 문장을 설계·튜닝하는 기술입니다. 같은 GPT라도 프롬프트에 따라 결과 품질이 수 배 차이 나기 때문에, 실무 자동화에선 코드보다 이 부분이 더 중요할 때가 많습니다.

💡
쉽게 말해 "AI에게 일을 시키는 문서 작성법". 신입 담당자에게 업무 지시서를 정확하게 써주는 것과 같은 원리입니다.

왜 필요한가 — 모델이 알아서 잘 하지 않나?

  • 같은 질문도 표현 방식에 따라 결과가 크게 달라짐
  • 구체적으로 요청하지 않으면 추측·환각(hallucination) 이 자주 발생
  • 자동화는 결과를 파이프라인 다음 단계에 넘겨야 해서 일관된 포맷이 필수
  • 비용 문제 — 프롬프트가 길고 산만하면 토큰 낭비가 큼

좋은 프롬프트의 4가지 축

  • 역할(Role) — "당신은 ○○ 담당자입니다" 로 정체성을 부여
  • 맥락(Context) — 상황·제약·배경 정보 제공 (예: 어떤 회사, 어떤 고객 대상)
  • 지시(Instruction) — 무엇을 하라 · 하지 마라를 명확히
  • 포맷(Format) — 출력 형식 (JSON 스키마, 문장 수, 언어 등)

나쁜 예 vs 좋은 예

❌ 나쁜 예 (모호함) text
고객 문의 답변해줘.
✅ 좋은 예 (역할+맥락+지시+포맷) text
당신은 이커머스 회사 고객센터 상담원입니다.

[맥락]
- 응대 대상: 20~40대 온라인 쇼핑 고객
- 처리 가능한 문의 유형: 배송, 환불, 제품

[지시]
- 문의를 읽고 아래 규칙대로 분류하세요.
- 답변은 3문장 이내, 존댓말 사용.
- 확인되지 않은 사실은 추측하지 않습니다.

[출력 포맷]
반드시 아래 JSON 만 반환하세요.
{
  "category": "배송 | 환불 | 제품",
  "summary": "문의 한 줄 요약",
  "priority": "높음 | 보통 | 낮음"
}

자주 쓰는 실무 패턴

  • Few-shot — 예시 2~3개를 프롬프트에 넣어 원하는 스타일 학습시키기
  • Chain-of-Thought — "단계별로 생각한 뒤 답하세요" 로 추론 정확도 향상
  • Delimiter--- · ``` · <task> 등으로 섹션 분리해서 모델이 헷갈리지 않게
  • Escape — 사용자 입력을 <user_input> ... </user_input> 로 감싸서 프롬프트 인젝션 방지

튜닝 순서 (실무 팁)

  • 먼저 System 만 짜서 대표 케이스 5개로 테스트
  • 결과가 이상하면 포맷 지시를 먼저 강화 (JSON 스키마·예시 추가)
  • 그래도 안 되면 Few-shot 예시 2~3개 추가
  • 여전히 실패율이 높으면 모델 승급 (4o → 5.5) 고려
  • 비용이 부담되면 반대로 5.5 → 4o → 5 mini 로 내리며 재테스트

주의점 — 프롬프트 자체 검토

💡
내가 넣은 프롬프트가 서로 상충하지 않게 논리적으로 맞는지 반드시 검토하세요. 프롬프트 안의 지시들끼리 모순이 있으면 모델이 어떤 규칙을 우선할지 예측 불가해집니다.
  • 모순 예시 — "3문장 이내로 답하세요" + "모든 세부사항을 빠짐없이 설명하세요"
  • 모순 예시 — "JSON 만 반환하세요" + "친근한 인사말을 앞에 붙이세요"
  • 모순 예시 — "확인되지 않은 사실은 추측하지 마세요" + "모르는 것도 최선을 다해 답변하세요"
  • 모순 예시 — Role 은 "엄격한 법률 상담사" 인데 톤은 "친근하고 캐주얼하게"
  • 검토 체크리스트
  • 지시들이 동시에 만족 가능한가
  • 규칙 간 우선순위가 명확한가 ("충돌 시 A 를 따르세요" 명시)
  • 출력 포맷과 응답 톤이 같은 방향인가 (JSON 이면 인사말·이모지 금지)
  • 예시(Few-shot)를 넣었다면 그 예시가 지시와 모두 일치하는가
  • 긴 프롬프트라면 같은 얘기를 다르게 두 번 하고 있진 않은가
💡
논리 검증하는 팁: 프롬프트를 다 짠 뒤 ChatGPT/Claude 에 직접 붙여넣고 "이 프롬프트에 모순되거나 서로 충돌하는 지시가 있는지 검토해줘" 라고 물어보세요. 사람보다 잘 찾아냅니다.
💡
자동화는 결국 프롬프트가 결정합니다. 노드 배치보다 여기에 시간을 더 투자하세요. 좋은 프롬프트 하나가 워크플로우 유지보수 비용을 절반으로 줄여줍니다.

구조화된 출력 — JSON 으로 받기

자동화의 핵심은 데이터입니다. AI가 아무리 좋은 답변을 내놔도, 그 답변이 사람이 읽는 자유 문장이면 다음 노드에서 다시 파싱해야 하고, 그 파싱은 100% 성공하지 않습니다. 그래서 실무에서는 AI 출력물을 반드시 구조화된 JSON으로 받도록 요청합니다.

💡
규칙: AI의 결과를 다음 노드에서 프로그램적으로 다뤄야 한다면, 무조건 JSON 으로 받아라. 자유 텍스트는 사람에게 보여줄 때만.

자유 텍스트 vs 구조화된 출력 — 뭐가 다른가

❌ 자유 텍스트 (파싱 지옥) text
이 문의는 배송 관련이고 우선순위는 높아 보입니다.
주문한 상품이 일주일째 도착하지 않았다는 내용이네요.
✅ 구조화된 JSON (즉시 재사용) json
{
  "category": "배송",
  "summary": "주문한 상품이 일주일째 도착하지 않음",
  "priority": "높음"
}

자유 텍스트는 Switch·조건분기·DB 저장 어느 것에도 그대로 넣을 수 없습니다. JSON 은 $json.category 로 바로 참조 가능.

구조화된 출력을 얻는 3가지 방법

  • 프롬프트에 JSON 스키마 명시 — 가장 간단, 대부분 상황에서 충분
  • OpenAI 노드의 Require Specific Output Format — 토글로 켜면 스키마 강제
  • Response Format = json_object (Chat Completions) — 모델이 JSON 이외의 출력을 못 하도록 강제

프롬프트에서 JSON 스키마 명시하는 법 — 실무에서 가장 많이 쓰는 방식

System 프롬프트 (JSON 강제) text
당신은 고객 문의 분류 담당자입니다.

반드시 아래 JSON 형식으로만 응답하세요.
다른 텍스트·설명·마크다운은 절대 포함하지 마세요.

{
  "category": "배송 | 환불 | 제품 중 하나",
  "summary": "문의를 한 줄로 요약",
  "priority": "높음 | 보통 | 낮음"
}
💡
핵심 3가지: ① 반드시 JSON · ② 다른 텍스트 절대 금지 · ③ 각 필드의 허용 값을 열거. 이 세 가지만 지키면 모델은 거의 실패하지 않습니다.

다음 노드에서 JSON 값 꺼내기

n8n 표현식 — JSON 파싱 n8n expression
{{ JSON.parse($json.output).category }}

AI Agent · OpenAI 노드의 output 필드는 문자열 형태이므로 JSON.parse() 로 객체화한 뒤 필드에 접근합니다. 이 표현식을 Switch·Set·IF 노드 어디든 그대로 붙여넣을 수 있어요.

JSON 응답이 깨질 때 대응법

  • 가끔 모델이 앞뒤에 ```json ... ``` 마크다운 코드블록을 붙임 → 프롬프트에 "마크다운 금지" 명시하거나 Code 노드로 output.replace(/```json|```/g, '') 정제
  • 필드가 누락되는 경우 → 스키마에 모든 필드는 필수임을 명시
  • 숫자 필드가 문자열로 오는 경우 → Number($json.가격) 로 캐스팅
  • 완전 실패 시 → Enable Fallback Model 토글로 상위 모델 자동 재시도
💡
이 강의 뒤에 나오는 Switch → Set → Chat 라우팅 챗봇도 구조화된 JSON 출력이 있어야 성립하는 구조입니다. 자동화에서 JSON 은 옵션이 아니라 기본 언어입니다.

또 다른 방법 — AI Agent 노드

단순 프롬프트 하나가 아니라 대화형 챗봇, 메모리, 도구(tools) 연결, 자동 라우팅 이 필요하면 AI Agent 노드를 씁니다.

노드 검색 → 'agent' → AI Agent
AI Agent — Chat Model / Memory / Tool 3개 하위 슬롯을 가짐
💡
AI Agent 는 Chat Model + Memory + Tool 세 가지를 하위 노드로 연결하는 구조입니다. 이 조합이 n8n 을 다른 노코드 대비 강력하게 만드는 핵심입니다.

AI Agent — Chat Model 연결

AI Agent 아래 Chat Model 슬롯에 OpenAI Chat Model 을 연결합니다. 여기서도 Credential + 모델을 선택합니다.

Chat Model 슬롯 → OpenAI Chat Model 선택
Credential 등록 후 모델 선택

AI Agent — 메모리 연결 (Context Window)

챗봇이 이전 대화 내용을 기억하려면 Memory 슬롯에 메모리 노드를 연결합니다. 가장 간단한 건 Simple Memory (세션별 인메모리).

Memory 슬롯 → Simple Memory (또는 Postgres, Redis 등)
Context Window — 몇 개의 이전 메시지를 기억할지
💡
Context Window 는 이전 대화 몇 개를 기억할지 정합니다. 너무 크면 토큰 비용이 급증하니 실무에선 5~10 정도가 적당.

AI Agent 시스템 지침 입력

AI Agent 노드 자체에 지침서(System Message) 를 넣습니다. 이게 챗봇의 성격·역할·출력 포맷을 결정합니다.

AI Agent 노드 파라미터 (지침은 이 노드 자체에)

① 하단 Options 를 열고 Add Option → System Message 선택.

Options → Add Option → System Message

② 시스템 메시지에 지침을 입력. 실습 예시는 고객 문의 분류 담당자 역할.

System Message — 배송/환불/제품 3가지로 분류하도록 지시
System Message (샘플) text
당신은 고객 문의 분류 담당자입니다.

사용자의 문의를 읽고 다음 세 가지 중 하나로 분류하세요.
- 배송
- 환불
- 제품

반드시 아래 JSON 형태로만 답하세요.
{
  "category": "배송 | 환불 | 제품 중 하나",
  "summary": "문의 요약",
  "priority": "높음 | 보통 | 낮음"
}
💡
지침에 출력 형식(JSON 스키마)까지 명시해두면 다음 Switch 노드에서 JSON.parse($json.output).category 로 안전하게 꺼낼 수 있습니다.

채팅 실행 & JSON 응답 확인

AI Agent 는 When chat message received 트리거와 짝을 이룹니다. 하단 채팅창에 질문을 입력하면 워크플로우가 자동 실행됩니다.

하단 Chat 탭에서 실제 사용자처럼 질문 입력

AI Agent 가 지침대로 JSON 형태로 답변하는지 확인합니다.

답변 예: { "category": "배송", "summary": "주문한 상품이 일주일째 도착하지 않아…", "priority": "높음" }

Switch 노드 — 분류 결과로 분기

AI Agent 결과의 category 값에 따라 배송/환불/제품 세 갈래로 흐름을 나눕니다. Switch 노드를 추가.

AI Agent 뒤에 Switch 노드 연결

Routing Rules 를 3개 추가합니다. 각각 조건은 아래처럼.

규칙 3개 — 배송/환불/제품
조건 값 (Value 1) n8n expression
{{ JSON.parse($json.output).category }}

각 규칙마다 Rename Output 을 켜서 output 이름을 배송 / 환불 / 제품 으로 정하면 캔버스에서 알아보기 쉽습니다.

각 규칙: is equal to → 값 지정 → Rename Output 켜기 → 이름 지정
결과: Switch 노드에 배송/환불/제품 3개 출력 포트가 생성됨

분기별 Set 노드로 답변 준비

Switch 의 각 출력 뒤에 Edit Fields (Set) 노드를 하나씩 붙입니다. 총 3개.

Switch 3개 output → 각각 Set 노드

각 Set 노드에서 answer 필드를 만들고 상황별 응답 문구를 세팅. 아래 3가지 샘플.

배송 분기 → answer: '배송 지연으로 불편을 드려 죄송합니다…'
환불 분기 → answer: '환불 접수 도와드리겠습니다…'
제품 분기 → answer: '제품 관련 문의 안내드리겠습니다…'
💡
실제 서비스에서는 이 자리에 DB 조회 · 주문번호 검색 · CRM 티켓 생성 등을 함께 붙입니다. 지금은 단순 텍스트 응답 예제.

Chat 노드로 최종 응답

n8n 챗봇이 사용자에게 실제로 말풍선으로 답하게 하려면 마지막에 Chat 노드가 필요합니다. 노드 검색에서 chat → Chat 을 추가.

각 Set 노드 뒤에 Chat 노드 추가
💡
챗봇 응답 세팅에는 매우 중요한 규칙 하나가 있습니다.
⚠️ 첫 번째 Chat 노드에서 응답 설정을 해야 나머지도 동작
첫 Chat 노드가 응답 모드를 결정 → 이후 노드들이 이를 따라감

Chat 노드에서 Message 필드에 앞 Set 노드의 answer 를 참조하는 표현식을 넣습니다.

Message: 앞 Set 노드의 answer 참조
Chat Message (표현식) n8n expression
{{ $json.answer }}

같은 방식으로 나머지 두 분기의 Chat 노드도 세팅.

환불·제품 Chat 노드도 동일 방식으로 answer 참조

최종 테스트 — 3가지 분기 모두 확인

이제 하단 채팅창에서 3가지 유형의 문의를 실제로 던져 테스트합니다.

입력: "주문한 상품이 일주일째 도착하지 않았어요." → 배송 분기 → 배송 안내 응답
환불 요청 문의 → 환불 분기 → 환불 안내 응답
제품 문의 → 제품 분기 → 제품 안내 응답
💡
여기까지 만들면 단순 OpenAI 호출 → 지능형 라우팅 챗봇 으로 확장이 끝났습니다. 실제 운영에선 각 분기 Set 자리에 DB/CRM/알림톡 노드를 이어붙여 완전 자동화 상담 시스템으로 발전시킬 수 있습니다.

챗봇을 공용 URL 로 공개하기

지금까지는 n8n 에디터 안에서만 테스트했습니다. 실제 고객이 접속해서 사용할 수 있는 공용 URL 로 배포하는 방법입니다.

완성된 라우팅 챗봇 — 이걸 그대로 외부에 공개

When chat message received 트리거 노드를 클릭 후 파라미터에서 Make Chat Publicly Available 토글을 켭니다.

① 트리거 노드 파라미터 → 상단 토글 켜기

② 토글을 켜면 아래에 공용 접속 URL 이 생성됩니다. 함께 나타나는 옵션들을 세팅.

① 공용 Chat URL · ② 첫 인사말(Initial Message) · ③ Response Mode: Using Response Nodes
  • Chat URL — 이 주소를 고객에게 공유하거나 사이트에 임베드
  • Authentication — 접근 제한이 필요하면 여기서 설정 (기본은 None)
  • Initial Message(s) — 챗봇 첫 화면에 뜨는 인사말 (예: 안녕하세요. 무엇을 도와드릴까요?)
  • Response ModeUsing Response Nodes 로 두어야 뒤쪽 Chat 노드들이 응답을 보냄
💡
⚠️ 파라미터만 켠 상태에서는 아직 접속되지 않습니다. 워크플로우를 Publish 해야 URL 이 실제로 살아납니다.

③ 우측 상단 Publish 버튼으로 워크플로우 게시. 상태가 Published 로 바뀝니다.

우측 상단 상태가 'Published' 로 전환되면 공용 URL 활성

④ 위에서 복사한 Chat URL 을 새 창에서 열면 실제 챗봇 UI 가 뜹니다. 첫 인사말 표시 후 사용자가 질문을 입력하면 우리가 만든 워크플로우가 실행됩니다.

고객 접속 화면 — 인사말 → 사용자 질문 → 우리 챗봇 응답
💡
이제 이 URL 을 자사 사이트에 iframe 임베드 하거나, 카카오 채널·인스타그램 DM 등과 연결하면 실제 CS 대응 채널로 활용할 수 있습니다. 사용량이 늘면 Authentication 을 켜서 인증된 사용자만 쓰도록 제한하는 것도 잊지 마세요.