ai-chatbot-builder
π€ Next.js AI μ±λ΄ λΉλ μ€ν¬
μ΄ μ€ν¬μ BSD λ°μ΄λΈμ½λ© μκ°μλ€μ΄ Next.jsμ Node.jsλ₯Ό μ¬μ©νμ¬ μ§λ₯ν AI μ±λ΄μ μΉμ¬μ΄νΈμ μ§μ ꡬμΆνκ³ λ°°ν¬ν μ μλλ‘ λμ΅λλ€.
π μ΄ μ€ν¬μ΄ νλ μΌ
- AI μμ§ μ€μ : OpenAI (GPT-4), Anthropic (Claude) λ± μ΅μ μ LLM μ ν
- λ°±μλ ꡬμΆ: Next.js API Routes (Route Handlers)λ₯Ό μ¬μ©ν μ±λ΄ μλ² κ΅¬ν
- νλ‘ νΈμλ ꡬν: React(Next.js) κΈ°λ°μ μ€μκ° μ€νΈλ¦¬λ° μ±ν UI μ μ
- μ§μλ² μ΄μ€(RAG): λ²‘ν° λ°μ΄ν°λ² μ΄μ€λ₯Ό νμ©ν μ μ© λ°μ΄ν° νμ΅ λ° λ΅λ³ μ΅μ ν
- μΈλΆ μ°λ: Slack, Discord, ν λ κ·Έλ¨ λ± λ©ν° μ±λ μ°λ κ°μ΄λ
π― μΈμ μ΄ μ€ν¬μ μ¬μ©νλμ?
- "Next.js μ¬μ΄νΈμ μ°λ¦¬ νμ¬λ§μ AI μλ΄μμ λ£κ³ μΆμ΄μ"
- "PDF λ¬Έμλ₯Ό νμ΅ν΄μ λ΅λ³ν΄μ£Όλ μ±λ΄μ μ§μ κ°λ°νκ³ μΆμ΄μ"
- "μ¬μ©μ λ°μ΄ν°λ₯Ό λΆμν΄μ κ°μΈνλ μΆμ²μ ν΄μ£Όλ AI λ΄μ΄ νμν΄μ"
π οΈ κΈ°μ μ€ν (Code-First)
1. Framework & Language
- Next.js 14+ (App Router): νλ‘ νΈμλ λ° API μλ² ν΅ν©
- TypeScript: μμ μ μΈ μ½λ κ°λ°
2. AI SDKs
- AI SDK (Vercel): ν μ€νΈ μμ± λ° μ€νΈλ¦¬λ° μ΅μ ν
- LangChain / LlamaIndex: 볡μ‘ν μ²΄μΈ λ° λ°μ΄ν° μ°λ
3. Database & Vector Store
- Supabase (pgvector): μ¬μ©μ κ΄λ¦¬ λ° λ²‘ν° κ²μ
- Pinecone: λκ·λͺ¨ λ°μ΄ν°μ© λ²‘ν° μμ§
π» Next.js μ±λ΄ ꡬν μμ
1. Client UI (components/ChatBox.tsx)
"use client";
import { useChat } from "ai/react";
export default function ChatBox() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<div className="flex flex-col w-full max-w-md mx-auto stretch">
{messages.map((m) => (
<div
key={m.id}
className={`whitespace-pre-wrap p-4 ${
m.role === "user"
? "bg-slate-100"
: "bg-blue-50 text-blue-900 border-l-4 border-blue-500"
}`}
>
<strong>{m.role === "user" ? "π€ λ: " : "π€ AI: "}</strong>
{m.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input
className="fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl focus:outline-none focus:ring-2 focus:ring-blue-500"
value={input}
placeholder="무μμ΄λ λ¬Όμ΄λ³΄μΈμ..."
onChange={handleInputChange}
/>
</form>
</div>
);
}
2. Server API (app/api/chat/route.ts)
import { OpenAIStream, StreamingTextResponse } from "ai";
import OpenAI from "openai";
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
export async function POST(req: Request) {
const { messages } = await req.json();
const response = await openai.chat.completions.create({
model: "gpt-4-turbo",
stream: true,
messages: [
{
role: "system",
content: "λΉμ μ BSD λ°μ΄λΈμ½λ© μΌν°μ μΉμ ν μλ΄μμ
λλ€.",
},
...messages,
],
});
const stream = OpenAIStream(response);
return new StreamingTextResponse(stream);
}
π μ±λ΄ μ νλ³ νμ© μ¬λ‘
1. μ§μ κΈ°λ° μλ΄ λ΄ (RAG)
- νμ¬μ λ§€λ΄μΌ, μ μ± PDFλ₯Ό νμ΅νμ¬ λ΅λ³
- API μ°λμΌλ‘ μ€μκ° μ¬κ³ λ κ°κ²© μ 보 λ°μ
2. μμ λ° λ¦¬λ μ λ€λ μ΄μ λ΄
- λνλ₯Ό ν΅ν΄ μ¬μ©μμ λμ¦ νμ ν DBμ μ μ₯
- κ΄λ ¨ μνμ κ²°μ λ§ν¬(Check-out)λ‘ μ λ
π¬ μμ λν
μ¬μ©μ: "μ°λ¦¬ μΌνλͺ°μ μν μΆμ²ν΄μ£Όλ AI μ±λ΄μ Next.jsλ‘ λ§λ€κ³ μΆμ΄"
Claude: "Next.jsμ OpenAI APIλ₯Ό μ¬μ©νμ¬ λ§μΆ€ν μν μΆμ² μ±λ΄μ ꡬμΆν΄λλ¦¬κ² μ΅λλ€. λνν μΈν°νμ΄μ€λ₯Ό ν΅ν΄ μ¬μ©μμ μ·¨ν₯μ λΆμνκ³ , λ΄λΆ DBμ μ°λνμ¬ μ΅μ μ μνμ μ μνλ λ‘μ§μ ν¬ν¨ν μ½λλ₯Ό μμ±ν΄ λ릴κ²μ..."
π― ν΅μ¬ μ 리
μ΄ μ€ν¬μ μ¬μ©νλ©΄: β Vercel AI SDKλ₯Ό νμ©ν κ³ μ±λ₯ μ±λ΄ ꡬν β Stream μλ΅μΌλ‘ μ€μ μ¬λκ³Ό λννλ λ―ν UX μ 곡 β Node.js λ°±μλλ₯Ό ν΅ν΄ 보μ μ΄μ(API Key λ ΈμΆ) ν΄κ²° β Custom Data μ°λμΌλ‘ μ°λ¦¬ νμ¬λ§μ νΉλ³ν AI ꡬμΆ
BSD νμμ΄λΌλ©΄: μΈλΆ μ λ£ μ±λ΄ μ루μ μ μμ‘΄νμ§ μκ³ , μ§μ AI νλ‘λνΈλ₯Ό κ°λ°νμ¬ λΉμ¦λμ€ κ°μΉλ₯Ό λμΌ μ μμ΅λλ€! π€