
Vercel AI SDK를 쓰던 프로젝트에서 v6로 올려야 한다는 걸 알고 있었는데, 한동안 미뤘다. 어차피 package.json에서 버전 숫자 몇 개 바꾸는 거라고 생각했거든. 근데 막상 시작했더니 타입 에러가 세 개나 한꺼번에 터졌고, 평소에 쓰던 함수 두 개가 deprecated 됐다는 경고가 떴다. 결국 반나절 날렸다. 그 과정에서 알게 된 것들을 정리해봤다.
Vercel AI SDK v6에서 진짜 달라진 것들
v6는 마이너 업데이트가 아니다. 핵심 아키텍처가 바뀌었다. 크게 세 가지다.
첫째, Server Actions 지원이 정식으로 들어왔다. 기존엔 AI 스트리밍을 하려면 /api/chat 같은 REST 엔드포인트를 반드시 만들어야 했다. v6부터는 Server Action을 직접 써도 된다. app/api/chat/route.ts 파일 없이도 스트리밍이 된다는 뜻이다.
둘째, generateObject와 streamObject가 deprecated 됐다. 구조화된 출력을 쓰려면 이 둘을 주로 썼는데, v6에서는 streamText/generateText에 output 옵션을 붙이는 방식으로 통합됐다. 함수 자체는 아직 작동하지만 경고가 계속 뜨고, 다음 버전에서 제거될 예정이다.
셋째, CoreMessage 타입이 제거됐다. ModelMessage로 대체됐는데, 기존 코드에서 CoreMessage를 import하고 있었으면 빌드가 깨진다. 이게 내가 처음에 맞은 타입 에러 중 하나였다.
추가로, convertToModelMessages 함수가 이제 비동기다. 예전에 동기로 쓰던 곳에 await를 안 붙이면 타입 에러가 조용히 생긴다. 공식 migration guide에 codemod 명령어가 있긴 한데(npx @ai-sdk/codemod upgrade), 이게 전부 해결해주진 않는다는 걸 나중에 알았다.
/api/chat 없이 스트리밍하는 법 — Server Actions 실전 코드
Server Actions 방식의 핵심은 createStreamableValue와 readStreamableValue다. 기존 방식이랑 코드를 직접 비교해봤다.
기존 방식 (API 라우트)
// app/api/chat/route.ts
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
messages,
});
return result.toDataStreamResponse();
}
클라이언트에선 useChat({ api: '/api/chat' })로 연결하면 됐다. 직관적이고 HTTP 표준에 맞는 방식이다.
v6 Server Actions 방식
// app/actions/chat.ts
"use server";
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { createStreamableValue } from 'ai/rsc';
import type { UIMessage } from '@ai-sdk/react';
export async function chat(messages: UIMessage[]) {
const stream = createStreamableValue("");
(async () => {
const result = streamText({
model: openai('gpt-4o'),
messages,
});
for await (const text of result.textStream) {
stream.update(text);
}
stream.done();
})();
return { output: stream.value };
}
클라이언트에서는 readStreamableValue로 스트림을 소비한다.
// 클라이언트 컴포넌트
import { readStreamableValue } from 'ai/rsc';
import { chat } from '@/app/actions/chat';
const { output } = await chat(messages);
for await (const chunk of readStreamableValue(output)) {
// chunk를 UI에 반영
}
Server Actions 방식은 별도 API 파일이 없고, 타입이 end-to-end로 맞는다는 게 장점이다. messages가 any로 흘러다니는 상황이 없어진다. 특히 monorepo 구조에서 타입 일관성 유지가 훨씬 쉬워진다는 걸 직접 써보고 체감했다.
v5 → v6 마이그레이션할 때 실제로 막혔던 것들
공식 문서에 migration guide가 있긴 하다. 근데 순서대로 따라가다 보면 놓치는 게 생긴다. 직접 경험한 것들을 기록해뒀다.
CoreMessage가 사라진 이유와 대처법
v6에서 CoreMessage는 완전히 제거됐다. ModelMessage로 대체됐는데, UI 레이어에서 쓰는 UIMessage와 헷갈리기 쉽다. 정리하면 이렇다.
ModelMessage: AI 모델로 보내는 메시지 타입 (서버 측)UIMessage: UI 상태로 관리하는 메시지 타입 (클라이언트 측)convertToModelMessages: UIMessage → ModelMessage 변환, 이제 async
기존 코드에 import { CoreMessage } from 'ai'가 있으면 전부 ModelMessage로 바꿔야 한다. codemod가 rename-core-message-to-model-message를 지원하니 이건 자동화할 수 있다.
generateObject를 streamText로 바꾸는 법
Zod 스키마로 구조화된 JSON을 뽑아야 하는 경우, v6에서는 이렇게 바뀐다.
// 기존 (deprecated)
const { object } = await generateObject({
model, schema: z.object({ summary: z.string() }), prompt: '...',
});
// v6 방식
const { experimental_output } = await generateText({
model, output: z.object({ summary: z.string() }), prompt: '...',
});
experimental_output이라는 이름이 아직 실험적인 느낌을 주는데, 공식 가이드에서 이 방식으로 권장하고 있으니 그냥 따라가면 된다.
codemod 쓰면 되는 거 vs 직접 고쳐야 하는 거
npx @ai-sdk/codemod upgrade는 타입 rename이나 함수명 변경 같은 기계적인 것들만 처리해준다. 직접 고쳐야 했던 건 이런 것들이었다.
convertToModelMessages에await추가 (codemod 지원되지만 놓친 곳 있음)- Server Actions 패턴으로 구조 변경 (codemod 범위 밖)
- Azure provider — Responses API 기본값으로 변경. 기존 Chat Completions API 코드가 조용히 깨짐.
azure.chat()으로 수동 변경 필요
Server Actions 방식이 항상 좋은 건 아니다
공식 문서나 튜토리얼 대부분이 Server Actions를 "새로운 표준"처럼 소개하는데, 솔직히 모든 상황에서 맞진 않다.
첫째, 엣지 런타임과 충돌한다. Server Actions는 Node.js 런타임에서 돌아간다. 기존에 export const runtime = 'edge'를 설정해 쓰던 API 라우트를 Server Actions로 바꾸면 엣지에서 실행되지 않는다. Vercel Edge Functions의 저지연 특성이 필요한 경우엔 API 라우트를 유지하는 게 낫다.
둘째, Next.js 13.4 미만은 지원 안 된다. Server Actions가 정식 스펙에 들어온 게 13.4부터다. 레거시 프로젝트에 AI SDK v6를 쓰려면 Next.js도 같이 올려야 하는 경우가 생긴다.
셋째, 외부 서비스가 스트리밍 엔드포인트를 직접 호출해야 한다면 API 라우트가 맞다. 모바일 앱이나 외부 서비스가 SSE(Server-Sent Events) 호환 엔드포인트를 필요로 한다면 toDataStreamResponse()를 쓰는 기존 방식이 훨씬 유연하다. Server Action은 그 용도로 설계되지 않았다.
순수하게 Next.js 앱 안에서 AI 기능이 완결되는 구조라면 Server Actions가 타입 안전성과 코드 단순화 측면에서 확실히 낫다. 반면 API 레이어가 독립적으로 필요한 경우엔 기존 REST 방식을 유지하는 게 현실적이다. 아키텍처 결정을 배포 이후에 바꾸는 건 항상 비용이 크다. AI 에이전트가 프로덕션에서 망하는 이유에서도 같은 패턴이 반복된다.
📎 참고 자료
- Migrate AI SDK 5.x to 6.0 — 공식 마이그레이션 가이드 (ai-sdk.dev)
- Vercel AI SDK v6 Next.js Tutorial (2026) — Next.js Launchpad
- Vercel AI SDK 6: Streaming AI Chat with Next.js — Digital Applied
📌 함께 보면 좋은 글
'AI.IT' 카테고리의 다른 글
| Hermes Agent, 7주 만에 95.6K 스타 — OpenClaw와 다른 길을 잡았다 (0) | 2026.05.11 |
|---|---|
| Perplexity Sonar API 모델 선택, 비용이 40배 차이 나는 이유가 있었다 (0) | 2026.05.11 |
| Claude 멀티 에이전트 OS 표준화, ClaudeClaw V3와 공식 발표 정리 (0) | 2026.05.10 |
| Higgsfield MCP Claude 연동, 이미지·영상 생성 Cowork에서 굴려보기 (1) | 2026.05.10 |
| Blender MCP × Claude, 공식 connector와 21.4k 스타 커뮤니티 프로젝트는 뭐가 다른가 (0) | 2026.05.10 |