master-project
CHAPTER 35 / 50
읽기 약 2분
FUNCTION
AI API 연동: OpenAI/Claude + 스트리밍
핵심 개념
Vercel AI SDK·streamText·useChat·다중 Provider·에러 처리 — 모던 AI 통합 패턴.
본문
Vercel AI SDK 셋업
pnpm add ai @ai-sdk/openai @ai-sdk/anthropic# .env.local
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...Server Action으로 AI 호출
// src/lib/ai.ts
import { generateText, streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
import { anthropic } from '@ai-sdk/anthropic'
export async function generateCopy(prompt: string) {
const { text, usage } = await generateText({
model: anthropic('claude-sonnet-4-6'),
system: '한국 마케터를 위한 카피라이터. 짧고 임팩트 있게.',
prompt,
maxTokens: 500,
temperature: 0.7,
})
return { text, tokens: usage.totalTokens }
}스트리밍 (Route Handler)
// src/app/api/chat/route.ts
import { streamText } from 'ai'
import { anthropic } from '@ai-sdk/anthropic'
import { createClient } from '@/lib/supabase/server'
export async function POST(request: Request) {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) return new Response('unauthorized', { status: 401 })
const { messages } = await request.json()
const result = streamText({
model: anthropic('claude-sonnet-4-6'),
system: '한국 마케터를 위한 카피라이터.',
messages,
onFinish: async ({ usage, text }) => {
// 사용량·결과 DB 저장
await supabase.from('generations').insert({
user_id: user.id,
prompt: messages[messages.length - 1].content,
result: text,
tokens_used: usage.totalTokens,
})
},
})
return result.toDataStreamResponse()
}클라이언트 useChat 훅
// src/app/(app)/generate/page.tsx
'use client'
import { useChat } from 'ai/react'
export default function GeneratePage() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: '/api/chat',
})
return (
<div className="max-w-2xl mx-auto p-6">
<div className="space-y-4 mb-6 min-h-[400px]">
{messages.map(m => (
<div key={m.id} className={m.role === 'user' ? 'text-right' : ''}>
<div className={`inline-block p-3 rounded-lg ${
m.role === 'user' ? 'bg-primary text-primary-foreground' : 'bg-muted'
}`}>
{m.content}
</div>
</div>
))}
</div>
<form onSubmit={handleSubmit} className="flex gap-2">
<input
value={input}
onChange={handleInputChange}
placeholder="원하는 카피를 설명하세요"
className="flex-1 px-3 py-2 border rounded-md"
/>
<button disabled={isLoading} className="bg-primary text-primary-foreground px-4 py-2 rounded">
{isLoading ? '생성 중...' : '생성'}
</button>
</form>
</div>
)
}generateObject (구조화된 출력)
import { z } from 'zod'
import { generateObject } from 'ai'
const schema = z.object({
variants: z.array(z.object({
text: z.string(),
tone: z.enum(['friendly', 'professional', 'playful']),
length: z.number(),
})).length(5),
})
const { object } = await generateObject({
model: anthropic('claude-sonnet-4-6'),
schema,
prompt: '여름 세일 30% 카피 5가지 톤별',
})
// object.variants: [{ text, tone, length }, ...]다중 Provider Fallback
async function generateWithFallback(prompt: string) {
try {
return await generateText({
model: anthropic('claude-sonnet-4-6'),
prompt,
})
} catch (err) {
console.warn('Anthropic 실패, OpenAI fallback')
return await generateText({
model: openai('gpt-5.5'),
prompt,
})
}
}에러 처리
import { APICallError } from 'ai'
try {
const result = await generateText({ ... })
} catch (err) {
if (APICallError.isInstance(err)) {
if (err.statusCode === 429) {
return { error: 'AI 서버 과부하. 잠시 후 재시도.' }
}
if (err.statusCode === 401) {
return { error: '인증 실패. 관리자 문의.' }
}
}
throw err
}캐시 (같은 prompt 재사용)
import { unstable_cache } from 'next/cache'
const cachedGenerate = unstable_cache(
generateCopy,
['ai-generate'],
{ revalidate: 3600 } // 1시간
)다음 챕터
CH.36 "RAG 구현: 문서 임베딩 + 벡터 검색".
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 마스터 프로젝트의 AI API 연동 부분을 분석해서 실전 적용 + 개선 우선순위 3가지를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
AI API 연동 관련 모범 사례·안티패턴 5개를 비교 분석해서 실전 적용를 위한 추천 방안을 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 프로젝트 전체에서 AI API 연동 최적화 가능 위치와 리스크를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 1인 개발자 시장의 AI API 연동 트렌드와 차별화 포인트를 정리해줘.
⭐ 이것만 기억하세요
AI API 연동: OpenAI/Claude + 스트리밍은 이 3가지만 확실히 잡으세요
1.Vercel AI SDK = streamText + useChat 표준
2.다중 Provider + 에러 처리 = 안정성
3.다음 챕터에서 RAG 구현
공유하기
진행도 35 / 50