스트림 프로토콜
스트림 프로토콜
useChat과 useCompletion 같은 AI SDK UI 함수는 텍스트 스트림과 데이터 스트림을 모두 지원해요. 스트림 프로토콜은 HTTP 위에서 데이터가 프론트엔드로 흘러가는 방식을 정의하는 약속이에요. 이 페이지에서는 두 프로토콜이 무엇이 다른지, 백엔드와 프론트엔드에서 각각 어떻게 쓰는지 살펴볼게요.
출처: 공식문서
본문
텍스트 스트림 프로토콜
텍스트 스트림은 평문(plain text) 청크를 프론트엔드로 보내는 방식이에요. 받은 각 청크를 차례로 이어 붙이면 하나의 완전한 텍스트 응답이 됩니다. 텍스트 스트림은 useChat, useCompletion, useObject가 지원하는데, useChat이나 useCompletion을 쓸 때는 streamProtocol 옵션을 text로 설정해야 텍스트 스트리밍이 켜져요.
백엔드에서는 streamText로 텍스트 스트림을 만들 수 있어요. 결과의 stream을 toTextStream에 넘기고, 그 결과를 createTextStreamResponse로 감싸면 스트리밍 HTTP 응답이 됩니다. 텍스트 스트림은 기본 텍스트 데이터만 다룰 수 있어요. 도구 호출 같은 다른 타입의 데이터를 스트리밍해야 한다면 데이터 스트림을 써야 합니다.
import {
convertToModelMessages,
createTextStreamResponse,
streamText,
toTextStream,
UIMessage,
} from 'ai';
// 스트리밍 응답 시간을 최대 30초까지 허용
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({
model: "xai/grok-4.6",
messages: await convertToModelMessages(messages),
});
return createTextStreamResponse({
stream: toTextStream({ stream: result.stream }),
});
}
데이터 스트림 프로토콜
데이터 스트림은 AI SDK가 정보를 프론트엔드로 보내기 위해 제공하는 특별한 프로토콜이에요. 이 프로토콜은 표준화 개선, ping을 통한 keep-alive, 재연결(reconnect) 기능, 더 나은 캐시 처리를 위해 Server-Sent Events(SSE) 형식을 사용합니다.
- 텍스트 파트(Text Parts) — 텍스트 콘텐츠는 각 텍스트 블록에 고유 ID를 붙여 start/delta/end 패턴으로 스트리밍돼요. 증분 텍스트는 JSON 객체를 담은 Server-Sent Event로 오는데, 예를 들면 이런 모양이에요.
data: { "type": "text-delta", "id": "msg_...", "delta": "Hello" }
- 추론 파트(Reasoning Parts) — 추론 콘텐츠도 마찬가지로 고유 ID를 가진 블록 단위로 start/delta/end 패턴을 따라요.
data: { "type": "reasoning-delta", "id": "reasoning_123", "delta": "This is some reasoning" }
- 스트림 종료(Stream Termination) — 스트림은 마지막에 특별한
[DONE]마커로 끝나요.
data: [DONE]
데이터 스트림 프로토콜은 프론트엔드의 useChat과 useCompletion이 기본으로 사용해요. 다만 useCompletion은 text와 data 스트림 파트만 지원합니다. 백엔드에서는 streamText 결과의 stream을 toUIMessageStream에 넘기고, 그 결과를 createUIMessageStreamResponse로 감싸서 응답하면 돼요.
import {
convertToModelMessages,
createUIMessageStreamResponse,
streamText,
toUIMessageStream,
UIMessage,
} from 'ai';
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({
model: "xai/grok-4.6",
messages: await convertToModelMessages(messages),
});
return createUIMessageStreamResponse({
stream: toUIMessageStream({ stream: result.stream }),
});
}
더 알아보기
streamProtocol옵션 — 텍스트 스트림을 켜고 싶을 때text로 설정.toTextStream/toUIMessageStream— 백엔드 스트림을 각 프로토콜 응답으로 변환하는 도우미.- 데이터 스트림은 SSE 기반이라,
useChat과useCompletion이 기본 프로토콜로 사용.