FrontendAIReactVercel AI SDK

프론트엔드 모던 AI 챗 인터페이스 구축 - 1부작, Vercel AI SDK

·11 min read

ChatGPT, Gemini, Claude...

사실 현재 대형 LLM들의 디자인은 제법 비슷하다.

채팅 UI 있고, 대화 이력 있고

상태 관리 측면에서도 메시지가 실시간으로 스트리밍 처리가 되고

비슷하다는 말은, 공통화 및 모듈화가 가능하다는 것인데

오늘은 프론트환경에서 AI 애플리케이션 구현을 위한 라이브러리를 소개하고자 한다.

Vercel AI SDK

AI 애플리케이션 구현에 사용 가능한 기능적 Toolkit이라고 보면 된다.

프론트엔드 라이브러리지만, 상태 관리에 특화되어있고,

UI를 직접적으로 구현하지는 않는다.

일단 일차적으로는 다양한 LLM 공급자의 API 차이점을 추상화해서 통일된 인터페이스 제공을 목표로 한다.

Vercel AI SDK는 두 가지 주요 라이브러리로 분류된다.

AI SDK Core: 텍스트 생성, 구조화된 객체, 도구 호출, LLM으로 에이전트 구축을 위한 통합 API

AI SDK UI: hook 모음으로, 채팅과 생성형 사용자 인터페이스 빠르게 구축

AI SDK RSC라고 생성형 사용자 인터페이스 스트리밍이 따로 있는데

아직 개발중이고 아직 사용할 이유는 없어서 이번 시간에서 다루지는 않겠다.

AI SDK Core

기본적인 사용법부터 보고가자

import { generateText } from "ai"
const { text } = await generateText({
  model: "google/gemini-3-pro-preview",
  prompt: "What is love?"
})

LLM이 GPT인지, gemini인지 상관없이 model 명을 명시하는 것으로 수십가지 종류의 LLM을 그냥 호출한다.

일단 LLM을 프론트엔드가 직접 호출한다는 시점에서 AI SDK Core는 비즈니스 로직 처리를 FE에서 모두 처리함을 가정한다.

즉 내가 만약 백엔드 서버가 있고, 복잡한 AI 처리와 비즈니스 로직이 별도로 있다면 AI SDK Core는 과감하게 스킵해도 된다.

기본 프로젝트 진행시 기본적으로 BE 서버가 존재하기에 상태 관리 측면에서 AI SDK를 사용했지만,

AI SDK의 진가는 복잡한 비즈니스 처리 및 도구 호출과 임베딩 처리 등의 AI 작업을 프론트 환경에서 처리가 가능하도록 함에 있다.

즉 AI 서비스 개발에서 백엔드 의존성이 적어지는 것이다.

텍스트 생성

LLM에 질문 던지고 받는 과정에서 SDK는 2가지 방법을 제공한다.

generateText: 텍스트 줘!

streamText: 텍스트 실시간으로 줘!

질문 던지고 화면에 한글자씩 순차적으로 타닥타닥 직히는거 보고 싶으면 streamText 쓰면 된다는 것이다.

단순 텍스트 생성만 관여하는건 아니고,

참고 자료 출처, 수행된 도구 호출 등...

모델 내부적인 처리 데이터도 접근이 가능하다.

자세한건 공식 문서 참조하자

https://ai-sdk.dev/docs/ai-sdk-core/generating-text

Core에서는 MCP 통신이나 Tool Calling 등의 부가적인 도구를 지원하고

임베딩, 응답 데이터 구조화 등 AI 모델 자체와 관련된 동작을 진행한다.

즉 BE 따로 구축한 우리 기본 프로젝트 입장에서는 굳이 관련성이 적긴 하다.

AI SDK UI

프론트엔드의 꽃은 상태 관리다.

복잡한 채팅 스트림 데이터를 어떻게 관리할 것이고,

어떨게 UI에 효율적으로 업데이트 해 줄 것인가.

우리가 Vercel SDK를 가져다 쓰는 가장 큰 목적이 바로 AI SDK UI다.

"아니 아까 UI는 안건든다고 안했나요?"

화면에 그리는게 UI의 전부는 아니다.

좀 더 중요한 것은 UI를 구성하는 데이터를 어떻게 관리하느냐다.

useChat

챗봇 상태 관리의 기본이 되어줄 요소다.

대표적으로는 다음의 기능을 제공한다.

  • 메시지 스트리밍: 실시간 UI로 스트리밍 해줌

  • 상태 관리: 입력, 메시지, 오류 등 포함

const { 
  messages,        // 대화 기록 (UI 렌더링용)
  input,           // 입력창 상태 (value 바인딩용)
  handleInputChange, // 입력창 변경 핸들러
  handleSubmit,    // 폼 제출 핸들러 (FastAPI 호출)
  status,          // 현재 상태 ('streaming', 'ready' 등)
  stop,            // 답변 생성 중단 함수
  reload           // 답변 재생성 함수 (에러 시 유용)
} = useChat({
  api: '/api/chat',
  onError: (error) => {
    console.error("채팅 중 에러 발생:", error);
  },
});

api를 정의하고, 상태 관리 항목들을 정의해서 가져오면 된다.

중요한건 messages, sendMessage, status 등이고,

필요에 따라서 stop, reload 등 부가적인 컨트롤 요소를 가져오면 된다.

결국에는 chat으로 서버 api와 소통을 하는 것인데,

useChat은 다음과 같은 JSON 포멧으로 요청을 보낸다

{
  "messages": [
    {"role": "user", "content": "안녕"},
    {"role": "assistant", "content": "반가워요"},
    {"role": "user", "content": "질문 있어"}
  ]
}

만약 자체적으로 쓰는 id 등 부가적인 정보가 필요하다면

json으로 별도로 첨부해주면 된다.

단순 text가 아닌 stream 방식으로 통신을 하고자 한다면 다른 방식을 사용해야한다.

공식 문서에서는 Standard SSE Format을 기준으로

data: {"type":"start","messageId":"..."}

형태로 type을 지정해서 메시지를 시작하고, Text Parts를 시작해서

text-start, text-delta 형태로 메시지 파이프라인을 처리하는 방식이있다.

다만 처리하는데 무겁기 때문에 경량화 된 형태로 개선된 프로토콜이 있는데

바로 AI Data Stream Protocol이다.

response.headers['x-vercel-ai-data-stream'] = 'v1'

위 형태로 요청 header를 선언하면

vercel에서 성능 최적화를 위해 만든 압축 전송 규격을 사용 할 수 있다.

주요 인덱스(0: text, 2: data, 9:tool call... 등)을 기준으로

0:"안녕"

형태로 간략하게 표현 된 경우다.

공식 문서에서 제공되는 fastAPI에 구현 관련된 내용이 있으니 필요시 참고하길 바란다.

https://github.com/vercel/ai/blob/main/examples/next-fastapi/api/index.py#L31

Tool Usage

커스텀 멀티 에이전트 시스템에서 FE 입장에서 신경써야할 부분이 있다면,

"그래서 서버에서 무슨 일이 일어나는 건데?" 라는 측면이다.

text는 stream으로 잘 도착하지만, 만약에 복잡한 에이전트에서

"내가 지금 ~ 하는 중"이라고 알려주고 싶다면,

서버 입장에서는 어떤 행동을 하는지, 어떤 도구를 쓰는지 알려줘야한다.

이러한 연동을 위해 서버에서는 텍스트 응답인 메시지 객체 안에

toolInvocations이라는 배열을 포함시길 수 있다.

해당 메시지 턴에서 AI가 호출하려고 했거나, 이미 호출한 도구들의 상태 정보를 담을 수 있다는 것이다.

예를 들어 FastAPI는 도구 사용이 필요하니 요청을 다음과 같이 보낸다.

9:{"toolName":"get_tool"}\n

프론트는 메시지 영역인 content는 비어있지만 toolIncocations에 상태를 기준으로 화면을 업데이트 해주는 방식이다.

단순히 상태 감시 뿐만 아니라, 사용자의 개입을 실행 가능하도록 지원하는데,

만약 사용자 개입이 필요하면 FastAPI는 "9:" 형태로 신호를 준다.

UI에서는 [승인]/[거절]에 대한 상태 관리를 진행 할 수 있는 것이다.

마무리

기본적으로 FE에서 AI 처리를 한다는 명목으로 지원되는 라이브러리다 보니 반쪽짜리 내용이 되버린다.

BE 서버가 따로 있는 상황에선 Vercel SDK에 기능 대부분을 사용하기 애매한 환경이다.

하지만 SDK AI가 의미 없다는 것은 아니다.

멀티 에이전트 LangGraph 환경에서는 Stream, Tool/Agent 관련 구현시

FE 상태 관리 및 렌더링 측면에서 직접 구현시 복잡성이 매우 높을 것이다.

또한 추가로 기회가 된다면 나중에 다룰 assistant-ui와의 연계도 가능하다.

현재 ChatUI 일부는 직접 구현했지만(초반부분이라서 빠르게 하려고)

SDK의 상태 관리와 assistant에 UI 컴포넌트는 상호 보완적 구조를 가졌다.

이 부분에 대해서는 나중에 기회가 되면 다루기로 하겠다.

← Previous
AI 음성 기본
Next →
구글 TPU랑 엔비디아