SvelteKit과 OpenAI로 AI 챗봇 만들기 - 초보자 가이드
SvelteKit과 OpenAI API를 활용하여 실시간 스트리밍 응답과 대화 히스토리 관리 기능을 갖춘 AI 챗봇을 처음부터 만들어보는 단계별 튜토리얼입니다.
안녕하세요! 이번 튜토리얼에서는 SvelteKit과 OpenAI API를 활용하여 실시간으로 대화할 수 있는 AI 챗봇을 만들어보겠습니다. 초보자도 쉽게 따라할 수 있도록 단계별로 자세히 설명하겠습니다.
📦 전체 소스코드
이 튜토리얼의 완성된 소스코드는 GitHub에서 확인하실 수 있습니다:
- GitHub Repository: https://github.com/ibank/ai-chatbot
- Live Demo: 아래 이미지와 같은 챗봇을 만들어볼 예정입니다
실제 구현된 AI 챗봇 실행 화면
🎯 무엇을 만들까요?
이 튜토리얼을 완료하면 다음 기능을 갖춘 AI 챗봇을 만들 수 있습니다:
- ✅ 실시간 채팅 인터페이스: 사용자 친화적인 대화 UI
- ✅ OpenAI API 연동: GPT 모델과 실제 대화
- ✅ 스트리밍 응답: 타이핑하듯 실시간으로 답변 표시
- ✅ 대화 히스토리 관리: 이전 대화 내용을 기억하는 컨텍스트 유지
현대적인 AI 챗봇 인터페이스 예시 (ChatGPT)
📋 사전 준비사항
시작하기 전에 다음 항목을 준비해주세요:
1. Node.js 설치 및 버전 확인
⚠️ 중요: 최신 SvelteKit은 특정 Node.js 버전이 필요합니다!
SvelteKit 최신 버전 요구사항:
- Node.js 20.19.0 이상 (20.x 시리즈 사용 시)
- Node.js 22.12.0 이상 (22.x 시리즈 사용 시)
- Node.js 24.0.0 이상 (24.x 시리즈 사용 시)
# 현재 Node.js 버전 확인
node --version
# 예시 출력:
# v22.11.0 ❌ (22.12.0 필요)
# v22.12.0 ✅ (사용 가능)
# v20.18.0 ❌ (20.19.0 필요)
# v20.19.0 ✅ (사용 가능) Node.js 업데이트 방법
방법 1: nvm 사용 (권장 - Mac/Linux)
# nvm이 설치되어 있지 않다면 먼저 설치
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
# 터미널 재시작 또는
source ~/.bashrc # 또는 ~/.zshrc
# Node.js 22.12.0 설치 및 사용
nvm install 22.12.0
nvm use 22.12.0
# 또는 Node.js 20.19.0 사용
nvm install 20.19.0
nvm use 20.19.0
# 기본 버전으로 설정
nvm alias default 22.12.0 방법 2: 직접 다운로드 (모든 OS)
Node.js 공식 사이트에서 다운로드:
- LTS 버전 (20.x): 20.19.0 이상 다운로드
- Current 버전 (22.x): 22.12.0 이상 다운로드
방법 3: Homebrew (Mac)
# Homebrew로 Node.js 업데이트
brew update
brew upgrade node
# 특정 버전 설치가 필요한 경우
brew install node@20 # 20.x LTS 버전 방법 4: Windows (nvm-windows)
# nvm-windows 설치 후
nvm install 22.12.0
nvm use 22.12.0 💡 버전 확인 팁: Node.js를 업데이트한 후 반드시 새 터미널을 열고
node --version으로 확인하세요!
2. 기타 필수 도구
OpenAI API 키
- OpenAI Platform에 가입
- API Keys 페이지에서 새 키 생성
- 키는
sk-로 시작하는 긴 문자열입니다
코드 에디터
- VS Code 권장
- Svelte 확장 프로그램 설치 권장
기본적인 프로그래밍 지식
- HTML/CSS 기초
- JavaScript 기본 문법
- async/await 개념 (설명 포함)
🚀 프로젝트 설정
1. SvelteKit 프로젝트 생성
터미널을 열고 새로운 SvelteKit 프로젝트를 생성합니다:
# 프로젝트 생성 명령어
npx sv@latest create ai-chatbot 💡 참고: SvelteKit 5부터는
npm create svelte가npx sv create로 변경되었습니다.
프로젝트 생성 과정에서 다음과 같은 선택 화면이 나타납니다:
┌ Welcome to the Svelte CLI! (v0.9.9)
│
◇ Which template would you like?
│ ○ SvelteKit demo
│ ● SvelteKit minimal ← 이것을 선택
│ ○ Library
│
◇ Add type checking with TypeScript?
│ ○ Yes, using JavaScript with JSDoc comments
│ ● Yes, using TypeScript syntax ← 이것을 선택
│
◇ What would you like to add to your project?
│ ◻ prettier ← 코드 포맷팅 (권장)
│ ◻ eslint ← 코드 검사 (권장)
│ ◻ vitest ← 테스트 (선택사항)
│ ◻ playwright ← E2E 테스트 (선택사항)
│
◇ Which package manager do you want to install dependencies with?
│ ● npm ← 이것을 선택
│ ○ pnpm
│ ○ yarn
│ ○ bun 2. 프로젝트 디렉토리로 이동 및 의존성 설치
# 프로젝트 폴더로 이동
cd ai-chatbot
# 의존성 설치 (프로젝트 생성 시 자동으로 되지 않았다면)
npm install 3. 프로젝트 구조 확인
생성된 프로젝트 구조는 다음과 같습니다:
ai-chatbot/
├── src/
│ ├── routes/ # 페이지와 API 라우트
│ │ └── +page.svelte # 메인 페이지
│ ├── lib/ # 공통 컴포넌트와 유틸리티
│ └── app.html # HTML 템플릿
├── static/ # 정적 파일 (이미지, 폰트 등)
├── package.json # 프로젝트 설정
├── svelte.config.js # SvelteKit 설정
├── vite.config.js # Vite 설정
└── tsconfig.json # TypeScript 설정 4. 필요한 패키지 설치
OpenAI API를 사용하기 위한 공식 패키지를 설치합니다:
# OpenAI 공식 SDK 설치
npm install openai
# 환경 변수 관리를 위한 dotenv 설치 (개발용)
npm install -D dotenv 설치가 완료되면 package.json 파일에 다음과 같이 추가됩니다:
{
"dependencies": {
"openai": "^4.x.x"
},
"devDependencies": {
"dotenv": "^16.x.x"
}
} 5. 환경 변수 설정
5-1. .env 파일 생성
프로젝트 루트 디렉토리에서 .env 파일을 생성합니다:
# VS Code에서 파일 생성 (VS Code가 설치되어 있는 경우)
code .env
# 또는 터미널에서 직접 생성
touch .env # Mac/Linux
# 또는
echo. > .env # Windows 5-2. OpenAI API 키 추가
.env 파일을 열고 다음 내용을 입력합니다:
# .env
OPENAI_API_KEY=sk-proj-실제키를여기에붙여넣으세요 📝 API 키 발급 방법:
- OpenAI Platform 접속
- 로그인 또는 회원가입
- 우측 상단 설정 아이콘 → 왼쪽 API Keys 클릭
- “Create new secret key” 버튼 클릭
- 생성된 키 복사 (한 번만 볼 수 있으니 안전하게 보관!)
5-3. .gitignore 확인
.gitignore 파일에 .env가 포함되어 있는지 확인합니다:
# .gitignore 파일 확인
cat .gitignore | grep .env 없다면 추가합니다:
echo ".env" >> .gitignore ⚠️ 보안 주의사항:
- API 키는 절대로 GitHub에 업로드하지 마세요
- 실수로 커밋했다면 즉시 OpenAI에서 키를 재생성하세요
- 키가 노출되면 요금이 발생할 수 있습니다
안전한 환경 변수 관리
💻 백엔드 구현
1. API 라우트 생성
API 라우트는 서버에서 실행되는 백엔드 코드입니다. 폴더 구조를 먼저 생성해야 합니다:
# src/routes/api/chat 폴더 생성
mkdir -p src/routes/api/chat 이제 src/routes/api/chat/+server.ts 파일을 생성하고 다음 코드를 작성합니다:
import { OpenAI } from 'openai';
import { OPENAI_API_KEY } from '$env/static/private';
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
// OpenAI 클라이언트 초기화
const openai = new OpenAI({
apiKey: OPENAI_API_KEY
});
export const POST: RequestHandler = async ({ request }) => {
try {
const { messages } = await request.json();
// OpenAI API 호출 (스트리밍 모드)
const stream = await openai.chat.completions.create({
model: 'gpt-3.5-turbo', // 또는 'gpt-4-turbo' 사용 가능
messages: messages,
stream: true,
temperature: 0.7,
max_tokens: 1000
});
// 스트리밍 응답을 위한 ReadableStream 생성
const encoder = new TextEncoder();
const readable = new ReadableStream({
async start(controller) {
try {
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
const data = JSON.stringify({ content });
controller.enqueue(encoder.encode('data: ' + data + '\n\n'));
}
}
controller.enqueue(encoder.encode('data: [DONE]\n\n'));
controller.close();
} catch (error) {
controller.error(error);
}
}
});
return new Response(readable, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
});
} catch (error) {
console.error('Chat API error:', error);
return json({ error: 'Failed to process chat request' }, { status: 500 });
}
}; 코드 설명:
stream: true: 스트리밍 모드로 응답을 받아 실시간으로 표시ReadableStream: 서버에서 클라이언트로 데이터를 스트리밍text/event-stream: Server-Sent Events (SSE) 방식으로 데이터 전송
2. 타입 정의
TypeScript를 사용하여 데이터 구조를 정의합니다. 먼저 lib 폴더가 없다면 생성합니다:
# src/lib 폴더 확인 및 생성
mkdir -p src/lib src/lib/types.ts 파일을 생성하고 다음 내용을 작성합니다:
export interface Message {
role: 'user' | 'assistant' | 'system';
content: string;
}
export interface ChatState {
messages: Message[];
isLoading: boolean;
error: string | null;
} 깔끔한 코드 구조가 유지보수를 쉽게 만듭니다
🎨 프론트엔드 구현
1. 채팅 페이지 생성
기본으로 생성된 src/routes/+page.svelte 파일의 내용을 모두 지우고 다음 코드로 교체합니다.
💡 초보자 팁:
.svelte파일은 HTML, CSS, JavaScript를 하나의 파일에 작성할 수 있습니다<script>태그 안에는 JavaScript/TypeScript 코드를 작성합니다<style>태그 안에는 CSS 스타일을 작성합니다- 나머지 부분에는 HTML 마크업을 작성합니다
src/routes/+page.svelte 파일을 열고 다음과 같이 작성합니다:
<script lang="ts">
import { onMount } from 'svelte';
import type { Message } from '$lib/types';
let messages: Message[] = [];
let inputMessage = '';
let isLoading = false;
let chatContainer: HTMLDivElement;
// 메시지 전송 함수
async function sendMessage() {
if (!inputMessage.trim() || isLoading) return;
const userMessage: Message = {
role: 'user',
content: inputMessage
};
messages = [...messages, userMessage];
inputMessage = '';
isLoading = true;
// AI 응답 준비
const assistantMessage: Message = {
role: 'assistant',
content: ''
};
messages = [...messages, assistantMessage];
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: messages.filter(m => m.content) // 빈 메시지 제외
})
});
if (!response.body) throw new Error('No response body');
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') continue;
try {
const parsed = JSON.parse(data);
// 마지막 메시지(AI 응답)에 내용 추가
messages[messages.length - 1].content += parsed.content;
messages = messages; // Svelte 반응성 트리거
scrollToBottom();
} catch (e) {
// JSON 파싱 에러 무시
}
}
}
}
} catch (error) {
console.error('Error:', error);
messages[messages.length - 1].content = '죄송합니다. 오류가 발생했습니다.';
messages = messages;
} finally {
isLoading = false;
}
}
// 자동 스크롤
function scrollToBottom() {
setTimeout(() => {
if (chatContainer) {
chatContainer.scrollTop = chatContainer.scrollHeight;
}
}, 0);
}
// Enter 키로 전송
function handleKeydown(event: KeyboardEvent) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
sendMessage();
}
}
onMount(() => {
scrollToBottom();
});
</script>
<main class="container">
<div class="chat-wrapper">
<header>
<h1>🤖 AI 챗봇</h1>
<p>OpenAI GPT-3.5로 구동되는 대화형 AI 어시스턴트</p>
</header>
<div class="chat-container" bind:this={chatContainer}>
{#if messages.length === 0}
<div class="welcome">
<h2>👋 안녕하세요!</h2>
<p>무엇을 도와드릴까요? 궁금한 것을 물어보세요.</p>
</div>
{/if}
{#each messages as message, i}
<div class="message {message.role}">
<div class="avatar">
{#if message.role === 'user'}
👤
{:else}
🤖
{/if}
</div>
<div class="content">
<div class="text">{message.content}</div>
</div>
</div>
{/each}
{#if isLoading && messages[messages.length - 1]?.content === ''}
<div class="typing-indicator">
<span></span>
<span></span>
<span></span>
</div>
{/if}
</div>
<form class="input-container" on:submit|preventDefault={sendMessage}>
<textarea
bind:value={inputMessage}
on:keydown={handleKeydown}
placeholder="메시지를 입력하세요... (Shift+Enter로 줄바꿈)"
rows="1"
disabled={isLoading}
/>
<button type="submit" disabled={isLoading || !inputMessage.trim()}>
{isLoading ? '⏳' : '📤'}
</button>
</form>
</div>
</main>
<style>
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
height: 100vh;
display: flex;
flex-direction: column;
}
.chat-wrapper {
display: flex;
flex-direction: column;
height: 100%;
background: white;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
header {
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
text-align: center;
}
header h1 {
margin: 0;
font-size: 1.8rem;
}
header p {
margin: 8px 0 0;
opacity: 0.9;
font-size: 0.9rem;
}
.chat-container {
flex: 1;
overflow-y: auto;
padding: 20px;
background: #f7f7f7;
}
.welcome {
text-align: center;
padding: 40px 20px;
color: #666;
}
.welcome h2 {
margin: 0 0 10px;
color: #333;
}
.message {
display: flex;
gap: 12px;
margin-bottom: 20px;
animation: fadeIn 0.3s ease-in;
}
.message.user {
flex-direction: row-reverse;
}
.avatar {
font-size: 2rem;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.content {
max-width: 70%;
}
.message.user .content {
background: #667eea;
color: white;
border-radius: 18px 18px 4px 18px;
}
.message.assistant .content {
background: white;
color: #333;
border-radius: 18px 18px 18px 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.text {
padding: 12px 16px;
line-height: 1.5;
word-wrap: break-word;
}
.typing-indicator {
display: flex;
gap: 6px;
padding: 20px;
}
.typing-indicator span {
width: 8px;
height: 8px;
background: #999;
border-radius: 50%;
animation: bounce 1.4s infinite ease-in-out;
}
.typing-indicator span:nth-child(1) {
animation-delay: -0.32s;
}
.typing-indicator span:nth-child(2) {
animation-delay: -0.16s;
}
.input-container {
display: flex;
gap: 10px;
padding: 20px;
background: white;
border-top: 1px solid #e0e0e0;
}
textarea {
flex: 1;
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 24px;
font-family: inherit;
font-size: 1rem;
resize: none;
max-height: 120px;
transition: border-color 0.2s;
}
textarea:focus {
outline: none;
border-color: #667eea;
}
textarea:disabled {
background: #f5f5f5;
cursor: not-allowed;
}
button {
width: 48px;
height: 48px;
border: none;
background: #667eea;
color: white;
border-radius: 50%;
font-size: 1.2rem;
cursor: pointer;
transition: all 0.2s;
flex-shrink: 0;
}
button:hover:not(:disabled) {
background: #5568d3;
transform: scale(1.05);
}
button:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes bounce {
0%, 80%, 100% {
transform: scale(0);
}
40% {
transform: scale(1);
}
}
/* 스크롤바 스타일링 */
.chat-container::-webkit-scrollbar {
width: 8px;
}
.chat-container::-webkit-scrollbar-track {
background: #f1f1f1;
}
.chat-container::-webkit-scrollbar-thumb {
background: #888;
border-radius: 4px;
}
.chat-container::-webkit-scrollbar-thumb:hover {
background: #555;
}
</style> 직관적이고 아름다운 채팅 인터페이스
🔧 주요 기능 설명
1. 스트리밍 응답
스트리밍 응답은 AI의 답변이 생성되는 즉시 사용자에게 표시되어 더 자연스러운 대화 경험을 제공합니다:
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// 받은 데이터를 실시간으로 화면에 표시
messages[messages.length - 1].content += parsed.content;
messages = messages; // Svelte 반응성 트리거
} 2. 대화 히스토리 관리
모든 메시지를 배열로 관리하여 OpenAI API에 전체 대화 컨텍스트를 전달합니다:
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({
messages: messages // 전체 대화 히스토리 전송
})
}); 이렇게 하면 AI가 이전 대화 내용을 기억하고 문맥에 맞는 답변을 할 수 있습니다.
3. 자동 스크롤
새 메시지가 추가될 때마다 자동으로 스크롤하여 최신 메시지를 표시합니다:
function scrollToBottom() {
setTimeout(() => {
if (chatContainer) {
chatContainer.scrollTop = chatContainer.scrollHeight;
}
}, 0);
} 실시간 스트리밍으로 자연스러운 대화 경험 제공
🚀 실행하기
모든 코드 작성이 완료되었습니다! 이제 실행해봅시다:
# 개발 서버 실행
npm run dev
# 또는 특정 포트로 실행
npm run dev -- --port 3000 성공적으로 실행되면 다음과 같은 메시지가 표시됩니다:
VITE v5.x.x ready in xxx ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help 브라우저에서 http://localhost:5173을 열고 챗봇과 대화를 시작하세요!
동작 테스트하기
첫 메시지 보내기:
- 입력창에 “안녕하세요!”라고 입력
- Enter 키를 누르거나 전송 버튼 클릭
- AI가 실시간으로 응답하는 것을 확인
스트리밍 응답 확인:
- “파이썬에 대해 설명해줘”와 같은 긴 답변이 필요한 질문
- AI 응답이 한 글자씩 나타나는 것을 확인
대화 컨텍스트 테스트:
- “내 이름은 홍길동이야”라고 입력
- 다음에 “내 이름이 뭐야?”라고 질문
- AI가 이전 대화를 기억하고 답변하는지 확인
🔧 자주 발생하는 문제 해결
1. Node.js 버전 오류
문제:
npm error engine Unsupported engine
npm error engine Not compatible with your version of node/npm: @sveltejs/[email protected]
npm error notsup Required: {"node":"^20.19 || ^22.12 || >=24"}
npm error notsup Actual: {"npm":"10.9.0","node":"v22.11.0"} 원인:
- Node.js 22.11.0은 SvelteKit이 요구하는 22.12.0보다 낮은 버전입니다.
해결방법:
# 1. 현재 버전 확인
node --version # v22.11.0 같은 경우 문제
# 2. nvm이 설치되어 있다면
nvm install 22.12.0
nvm use 22.12.0
# 3. nvm이 없다면 설치
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.zshrc # 또는 ~/.bashrc
# 4. 그 후 Node.js 설치
nvm install 22.12.0
nvm use 22.12.0
nvm alias default 22.12.0
# 5. 버전 확인
node --version # v22.12.0 이상이어야 함
# 6. 프로젝트 재생성
npx sv@latest create ai-chatbot 대안: Node.js 20.x LTS 사용:
# 더 안정적인 LTS 버전 사용
nvm install 20.19.0
nvm use 20.19.0 2. OpenAI API 키 오류
문제:
Error: Incorrect API key provided 해결방법:
.env파일의 API 키 확인- 키가
sk-proj-로 시작하는지 확인 - 키 앞뒤 공백 제거
- OpenAI 대시보드에서 키 활성화 상태 확인
3. CORS 오류
문제:
Access to fetch at 'http://localhost:5173/api/chat' from origin 'http://localhost:5173' has been blocked by CORS policy 해결방법: 서버 재시작:
# Ctrl+C로 서버 중지 후
npm run dev 4. 포트 충돌
문제:
Error: Port 5173 is already in use 해결방법:
# 다른 포트 사용
npm run dev -- --port 3000
# 또는 기존 프로세스 종료 (Mac/Linux)
lsof -i :5173
kill -9 [PID]
# Windows
netstat -ano | findstr :5173
taskkill /PID [PID] /F 5. 환경 변수를 찾을 수 없음
문제:
Cannot find module '$env/static/private' 해결방법:
.env파일이 프로젝트 루트에 있는지 확인- 서버 재시작 (환경 변수는 서버 시작 시 로드됨)
- SvelteKit이 최신 버전인지 확인
🎯 다음 단계
기본 챗봇이 완성되었습니다! 다음과 같은 기능을 추가하여 더욱 발전시킬 수 있습니다:
추천 개선사항
대화 저장 기능
- LocalStorage를 사용하여 대화 히스토리 저장
- 페이지 새로고침 후에도 대화 내용 유지
마크다운 지원
- AI 응답에 코드 블록, 리스트 등 포맷팅 적용
marked라이브러리 활용
다크 모드
- 사용자 선호도에 따른 테마 전환
- 시스템 설정 자동 감지
파일 업로드
- 이미지나 문서 업로드 기능
- GPT-4 Vision API 활용
음성 입력
- Web Speech API로 음성 인식
- 텍스트 음성 변환 (TTS)
💡 팁과 주의사항
보안 관련
- ✅ API 키는 서버 사이드에서만 사용하세요
- ✅
.env파일을.gitignore에 추가하세요 - ✅ 프로덕션 환경에서는 요청 제한(rate limiting)을 구현하세요
비용 관리
- 💰 OpenAI API는 사용량에 따라 과금됩니다
- 💰
max_tokens설정으로 응답 길이 제한 - 💰 개발 중에는 GPT-3.5-turbo 사용 (GPT-4보다 저렴)
- 💰 OpenAI 가격 계산기로 예상 비용 확인 가능
성능 최적화
- ⚡ 스트리밍으로 체감 속도 향상
- ⚡ debounce로 과도한 API 호출 방지
- ⚡ 긴 대화는 토큰 제한에 주의
보안과 성능을 고려한 베스트 프랙티스
🎓 학습 자료
더 깊이 있게 학습하고 싶다면:
마무리
축하합니다! 🎉 SvelteKit과 OpenAI API를 활용한 실시간 AI 챗봇을 성공적으로 만들었습니다.
이 튜토리얼에서 배운 내용:
- ✅ SvelteKit API 라우트 구현
- ✅ OpenAI API 연동 및 스트리밍 응답 처리
- ✅ 실시간 채팅 UI 구현
- ✅ 대화 컨텍스트 관리
이제 여러분만의 창의적인 기능을 추가하여 더욱 발전시켜 보세요!