Vercel AI SDK 완벽 가이드 | Streaming·Chat UI·RAG·Edge·실전 활용
이 글의 핵심
Vercel AI SDK로 AI 앱을 구축하는 완벽 가이드입니다. Streaming, Chat UI, RAG, Edge Runtime, OpenAI/Anthropic 통합까지 실전 예제로 정리했습니다.
실무 경험 공유: 직접 구현한 Chat UI를 Vercel AI SDK로 전환하면서, 개발 시간이 80% 단축되고 Streaming 구현이 간편해진 경험을 공유합니다.
들어가며: “Chat UI 구현이 복잡해요”
실무 문제 시나리오
시나리오 1: Streaming이 어려워요
SSE 구현이 복잡합니다. Vercel AI SDK는 자동으로 처리합니다.
시나리오 2: Chat UI가 필요해요
처음부터 만들기 어렵습니다. Vercel AI SDK는 컴포넌트를 제공합니다.
시나리오 3: 다양한 LLM을 지원해야 해요
각각 연동이 복잡합니다. Vercel AI SDK는 통합 API를 제공합니다.
1. Vercel AI SDK란?
핵심 특징
Vercel AI SDK는 AI 앱 개발 도구입니다.
주요 기능:
- Streaming: 실시간 응답
- Chat UI: React 컴포넌트
- 다중 LLM: OpenAI, Anthropic, Cohere
- Edge Runtime: 빠른 응답
- RAG: 문서 기반 응답
2. 설치 및 설정
설치
npm install ai
환경 변수
OPENAI_API_KEY=sk-...
3. Chat Completion
API Route
// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export const runtime = 'edge';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = await streamText({
model: openai('gpt-4-turbo'),
messages,
});
return result.toAIStreamResponse();
}
클라이언트
// app/page.tsx
'use client';
import { useChat } from 'ai/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<div>
<div>
{messages.map((m) => (
<div key={m.id}>
<strong>{m.role}:</strong> {m.content}
</div>
))}
</div>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
placeholder="Say something..."
/>
<button type="submit">Send</button>
</form>
</div>
);
}
4. Streaming
Text Generation
// app/api/generate/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export async function POST(req: Request) {
const { prompt } = await req.json();
const result = await streamText({
model: openai('gpt-4-turbo'),
prompt,
});
return result.toAIStreamResponse();
}
클라이언트
'use client';
import { useCompletion } from 'ai/react';
export default function Generate() {
const { completion, input, handleInputChange, handleSubmit } = useCompletion();
return (
<div>
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
<button type="submit">Generate</button>
</form>
<div>{completion}</div>
</div>
);
}
5. Function Calling
import { openai } from '@ai-sdk/openai';
import { streamText, tool } from 'ai';
import { z } from 'zod';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = await streamText({
model: openai('gpt-4-turbo'),
messages,
tools: {
weather: tool({
description: 'Get the weather for a location',
parameters: z.object({
location: z.string().describe('The city name'),
}),
execute: async ({ location }) => {
const weather = await getWeather(location);
return weather;
},
}),
},
});
return result.toAIStreamResponse();
}
6. RAG 구현
import { openai } from '@ai-sdk/openai';
import { streamText, embed } from 'ai';
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_KEY!
);
export async function POST(req: Request) {
const { messages } = await req.json();
const lastMessage = messages[messages.length - 1].content;
// 1. 질문 임베딩
const { embedding } = await embed({
model: openai.embedding('text-embedding-3-small'),
value: lastMessage,
});
// 2. 유사 문서 검색
const { data: documents } = await supabase.rpc('match_documents', {
query_embedding: embedding,
match_threshold: 0.7,
match_count: 3,
});
// 3. 컨텍스트 구성
const context = documents.map((doc) => doc.content).join('\n\n');
// 4. LLM 호출
const result = await streamText({
model: openai('gpt-4-turbo'),
messages: [
{
role: 'system',
content: `Answer based on the following context:\n\n${context}`,
},
...messages,
],
});
return result.toAIStreamResponse();
}
7. 다중 LLM
Anthropic
import { anthropic } from '@ai-sdk/anthropic';
const result = await streamText({
model: anthropic('claude-3-opus-20240229'),
messages,
});
Ollama
import { createOllama } from 'ollama-ai-provider';
const ollama = createOllama();
const result = await streamText({
model: ollama('llama3'),
messages,
});
8. 실전 예제: 문서 챗봇
'use client';
import { useChat } from 'ai/react';
export default function DocumentChat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } =
useChat({
api: '/api/chat',
});
return (
<div className="flex flex-col h-screen">
<div className="flex-1 overflow-y-auto p-4">
{messages.map((m) => (
<div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
<div className="inline-block p-2 rounded bg-gray-100">
{m.content}
</div>
</div>
))}
{isLoading && <div>Thinking...</div>}
</div>
<form onSubmit={handleSubmit} className="p-4 border-t">
<input
value={input}
onChange={handleInputChange}
placeholder="Ask a question..."
className="w-full p-2 border rounded"
/>
</form>
</div>
);
}
정리 및 체크리스트
핵심 요약
- Vercel AI SDK: AI 앱 개발 도구
- Streaming: 실시간 응답
- Chat UI: React 컴포넌트
- 다중 LLM: OpenAI, Anthropic, Ollama
- Edge Runtime: 빠른 응답
- RAG: 문서 기반 응답
구현 체크리스트
- Vercel AI SDK 설치
- API Route 구현
- Chat UI 구현
- Streaming 구현
- Function Calling 구현
- RAG 구현
- 배포
같이 보면 좋은 글
- LangChain 완벽 가이드
- Next.js App Router 가이드
- OpenAI API 가이드
이 글에서 다루는 키워드
Vercel AI SDK, AI, Streaming, Chat, OpenAI, Next.js, React
자주 묻는 질문 (FAQ)
Q. LangChain과 비교하면 어떤가요?
A. Vercel AI SDK가 더 간단하고 React 통합이 완벽합니다. LangChain은 더 많은 기능을 제공합니다.
Q. 무료로 사용할 수 있나요?
A. 네, SDK는 무료이고 LLM API 비용만 발생합니다.
Q. Ollama를 사용할 수 있나요?
A. 네, ollama-ai-provider를 사용하면 가능합니다.
Q. 프로덕션에서 사용해도 되나요?
A. 네, Vercel에서 만든 안정적인 SDK입니다.