← Resources
TUTORIAL · 2026-03-26
Vercel AI SDK에서 BYOK 셀프 호스팅 스택으로 마이그레이션
Vercel AI SDK는 포터블 키, 커스텀 라우팅, Vercel이 아닌 배포 타깃이 필요해지기 전까지는 괜찮습니다. 본 가이드는 모든 프리미티브를 셀프 호스팅 가능한 BYOK 스택으로 매핑하고 1주일 듀얼 라이트 컷오버를 제공합니다.
팀이 Vercel AI Gateway를 졸업하는 이유
AI SDK는 빠르게 출시됩니다. `streamText`, `generateText`, `generateObject`는 대부분의 프로덕션 요구를 단일 TypeScript 표면으로 다룹니다. 마찰은 나중에 보통 세 곳에서 드러납니다.
첫째, 런타임이 Vercel에 편향되어 있습니다. Edge 런타임 특이성, Next.js에 맞춰진 스트리밍 프리미티브, 권장 라우터로서의 AI Gateway가 모두 프로덕션 타깃이 Vercel이라고 가정합니다.
둘째, AI Gateway는 BYOK에서도 요청 경로에 위치합니다. 2026년 5월 기준 Vercel의 공식 AI Gateway 가격에 따르면 BYOK는 0% 토큰 마크업으로 실행되지만, 실패한 BYOK 요청이 Vercel의 시스템 자격 증명에 대해 재시도되므로 팀은 AI Gateway 크레딧을 항상 충전된 상태로 유지해야 합니다. 컴플라이언스나 VPC 라우팅이 들어오면 이 결합이 중요해집니다.
셋째, 테넌트별 정책이 앱 코드에 살고 있습니다. SDK에는 테넌트, 모델 화이트리스트, 예산 상한의 네이티브 개념이 없습니다. 멀티테넌트 SaaS를 운영하는 팀은 첫 번째 게이트웨이 위에 두 번째 미니 게이트웨이를 작성하게 됩니다.
Vercel 프리미티브를 BYOK 스택에 매핑하기
좋은 소식: AI SDK의 공개 표면은 작습니다. 대부분의 호출은 세 함수와 프로바이더 객체로 귀결됩니다. 다음과 같이 매핑하십시오.
- `streamText`와 `generateText`는 OpenAI SDK의 `chat.completions.create`에 `stream: true` 또는 `false`로 직접 매핑됩니다. 모든 OpenAI 호환 엔드포인트는 `baseURL`로 작동하며, 이는 llama.cpp, vLLM, LiteLLM, 또는 테넌트 인식 프록시 뒤의 호스팅 프로바이더를 의미합니다.
- `generateObject`는 OpenAI 호환 서버의 `response_format: { type: 'json_schema' }`에 매핑되며, 다른 스키마를 사용하는 프로바이더(Anthropic 도구, Gemini JSON 모드)에는 구조화 출력 어댑터에 매핑됩니다.
- 프로바이더 객체(`openai('gpt-4o')`, `anthropic('claude-...')`)는 게이트웨이를 가리키는 단일 클라이언트가 되며, 모델 ID는 문자열로 전달됩니다. 라우팅은 import 문에 새겨지는 대신 서버 사이드에서 발생합니다.
기존 React 훅을 유지하십시오. `useChat`과 `useCompletion`은 동일한 형태의 Server-Sent Events 스트림을 반환하는 라우트만 있으면 됩니다.
락인 없는 스트리밍, 도구 호출, 구조화 출력
OpenAI 호환 게이트웨이를 선택하면 세 기능 모두 마이그레이션에서 살아남습니다. 동일한 호출의 전과 후입니다.
전, Vercel AI SDK 사용:
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
const result = await streamText({
model: openai('gpt-4o'),
messages,
tools: { search: searchTool },
});
return result.toDataStreamResponse();
```
후, 자체 게이트웨이를 가리키는 OpenAI SDK 사용:
import OpenAI from 'openai';
const client = new OpenAI({ baseURL: process.env.GATEWAY_URL, apiKey: tenantKey });
const stream = await client.chat.completions.create({
model: 'gpt-4o',
messages,
tools: [searchToolSchema],
stream: true,
});
```
도구 호출은 `delta.tool_calls`로 도착합니다. 구조화 출력은 `response_format`을 사용합니다. 둘 다 LiteLLM, vLLM, 대부분의 매니지드 프로바이더가 존중하는 표준 OpenAI 스펙 필드입니다.
키, 쿼터, 테넌트별 라우팅
여기가 얇은 SDK가 보상받는 지점입니다. 요청이 제어 가능한 하나의 OpenAI 호환 엔드포인트를 통해 흐르기 시작하면, 모든 횡단 관심사가 앱 코드에서 빠져나갑니다.
LiteLLM 같은 셀프 호스팅 게이트웨이는 테넌트별 가상 키를 발급하고, RPM과 TPM 상한을 설정하며, 예산을 첨부하고, 모델 별칭으로 라우팅하게 해줍니다. `model: 'fast'`에 대한 요청은 한 테넌트에서는 Groq Llama로, 다른 테넌트에서는 로컬 llama.cpp 서버로 해석될 수 있으며, Next.js 앱에서 코드 변경 없이 가능합니다.
osFoundry는 동일한 순수 패스스루 BYOK 자세를 취하며 테넌트별 라우팅 규칙, 스트리밍, 도구 호출, 구조화 출력을 셀프 호스팅 가능한 단일 런타임에 추가합니다. 동시 언급: LiteLLM은 명백한 오픈소스 베이스라인이며 많은 팀에 올바른 선택입니다. 운영 모델에 맞는 것을 선택하십시오.
핵심 결정은 키와 쿼터를 앱이 아니라 게이트웨이가 소유하게 하는 것입니다. 모델 교체를 포함한 모든 것이 설정 변경이 됩니다.
셀프 호스팅 또는 하이브리드: 비용과 운영
세 가지 배포 형태가 대부분 팀을 커버합니다.
1. 완전 셀프 호스팅. VPC 내 게이트웨이, BYOK로 프로바이더 연결, 선택적으로 GPU 박스의 로컬 모델. 마크업 0, 전체 감사 추적, 온콜은 직접. 컴플라이언스 또는 데이터 거주가 결정을 주도할 때 최적.
2. 하이브리드. 라우팅과 정책용 셀프 호스팅 게이트웨이, 추론용 매니지드 프로바이더, 저렴하거나 사적인 워크로드용 로컬 모델. 이것이 일반적인 안정 상태입니다.
3. 매니지드 게이트웨이, 자체 키. BYOK 패스스루를 지원하는 호스팅 OpenAI 호환 프록시를 사용하십시오. 요청 경로에 대한 통제를 일부 포기하고, 또 다른 서비스를 운영하지 않는 이점을 얻습니다.
옵션 1의 운영 비용은 실재합니다. 작은 컨테이너 하나, 키와 지출용 Postgres, 로그 수송, 업그레이드 주기. 월 수억 토큰 미만의 대부분 팀에서, 마크업 기반 게이트웨이 대비 절감은 이를 두고 논쟁하는 시간보다 작습니다. 푼돈이 아니라 통제력을 기준으로 선택하십시오.
컷오버 스크립트: 일주일 듀얼 라이트
한 PR에서 import를 뒤집지 마십시오. 7일간 듀얼 라이트하고, 비교한 뒤 컷오버하십시오.
Day 0: 피처 플래그 뒤에서 새 게이트웨이 클라이언트를 추가합니다. 각 요청에 대해 기존 `streamText` 경로를 실행하고, 동시에 동일한 메시지로 새 `chat.completions` 호출을 발사합니다. 두 번째 응답은 폐기하지만 지연, 토큰 수, 종료 사유, 도구 호출 형태 불일치를 기록합니다.
Day 1-3: 트래픽의 100%를 섀도잉합니다. 구조화 출력과 도구 호출 인자 JSON을 디프합니다. 대부분의 회귀는 스키마 관련입니다. Anthropic은 약간 다른 stop 사유를 반환하고, Gemini는 JSON을 다르게 감쌉니다. 앱이 아니라 게이트웨이에서 수정하십시오.
Day 4-6: 읽기 전용 경로(채팅, 요약)의 10%, 그다음 50%, 그다음 100%를 전환합니다. 쓰기 또는 에이전틱 경로는 디프가 24시간 동안 깨끗할 때까지 기존 경로에 유지하십시오.
Day 7: `ai`와 `@ai-sdk/*` 패키지를 제거하고, AI Gateway 환경 변수를 삭제하며, 플래그를 아카이브합니다.
마이그레이션 후: 캐싱, 관찰성, 평가
요청 경로 소유는 SDK 내부에서 어색했던 세 가지를 해제합니다.
캐싱: 게이트웨이는 `(model, messages, tools, response_format)`으로 해싱하여 동일한 요청을 Redis에서 서비스할 수 있습니다. 반복되는 시스템 프롬프트가 있는 RAG와 에이전트 루프에는, 프로바이더 수준(Anthropic, OpenAI)의 프롬프트 접두사 캐싱이 그 위에 겹쳐집니다. 둘 다 연결하면 캐시 적중은 지연 p50에서 즉시 나타납니다.
관찰성: 테넌트 ID, 모델, 프롬프트 토큰, 완성 토큰, 도구 호출 수, 종료 사유, 업스트림 지연을 포함한 요청당 하나의 구조화 로그를 내보내십시오. 이미 사용 중인 것에 전달하십시오. 모델이 무엇을 했는지 보기 위해 더 이상 벤더별 트레이싱 통합이 필요하지 않습니다.
평가: 모든 트래픽이 하나의 엔드포인트로 흐르면, 평가 집합을 위한 샘플링은 SQL 쿼리입니다. `model` 필드를 바꿔 새 모델에 대해 재생하십시오. 이것이 게이트웨이를 소유하는 장기적 이유입니다. 모델 선택이 분기별 마이그레이션이 아니라 주간 실험이 됩니다.
Frequently asked questions
- Vercel AI SDK를 버리면 useChat과 React 스트리밍 훅을 잃나요?
- 아니요. 훅은 API 라우트가 훅이 기대하는 형태의 Server-Sent Events 스트림을 반환하는 한 서버 런타임과 분리되어 있습니다. `ai` 패키지의 `useChat`과 `useCompletion`을 유지하고 OpenAI 호환 스트리밍 응답을 프록시하는 라우트를 가리킬 수 있습니다. 많은 팀이 마이그레이션 첫 달에는 React 측을 건드리지 않고 서버 핸들러만 교체합니다. 결국 `ai` 의존성을 완전히 제거하고 싶다면, 얇은 SSE 파서는 약 30줄의 TypeScript입니다.
- LiteLLM이 진짜 대안인가요, 임시방편인가요?
- 진짜 대안이며 프로덕션에 광범위하게 배포되어 있습니다. LiteLLM은 140개 이상의 프로바이더를 앞단에 두고 가상 키, 키별 예산, RPM과 TPM 상한, 로드 밸런싱을 지원하는 오픈소스 OpenAI 호환 프록시입니다. Postgres를 갖춘 단일 Docker 컨테이너로 실행됩니다. 더 완전한 오케스트레이션 런타임 대비 트레이드오프는 주로 에이전트 루프, 프로바이더 전반에 걸친 구조화 출력 정규화, 키와 예산을 넘어선 테넌트 범위 정책에 있습니다. 순수 라우팅과 BYOK 사용 사례라면, LiteLLM이 종종 그 자체로 올바른 답입니다.
- 마이그레이션 후 프로바이더 전반에 걸쳐 구조화 출력을 어떻게 유지하나요?
- 앱이 아니라 게이트웨이에서 정규화하십시오. OpenAI와 OpenAI 호환 서버는 `response_format: { type: 'json_schema', json_schema: {...} }`을 받아들입니다. Anthropic은 스키마를 강제하기 위해 도구 호출 패턴을 사용합니다. Gemini는 `responseMimeType`과 `responseSchema`를 사용합니다. 게이트웨이의 작은 어댑터 계층이 하나의 정규 요청 형태를 디스패치 대상 프로바이더로 번역하고, 반환된 JSON을 응답하기 전에 검증합니다. 이렇게 하면 애플리케이션 코드가 단일 함수를 호출하면서 스키마 처리 로직을 건드리지 않고 모델을 교체할 수 있게 됩니다.
- 지연은 어떤가요? 셀프 호스팅 게이트웨이는 또 다른 홉처럼 들립니다.
- 실무에서 추가되는 지연은 게이트웨이가 앱과 같은 리전에 있다면 한 자리 수 밀리초이며, 이는 모델 추론 시간(수백 ms에서 수 초)에 의해 무색해집니다. 더 큰 지연 승리는 캐시 측에 있습니다. 게이트웨이는 반복된 프롬프트를 Redis에서 5 ms 미만에 서비스할 수 있으며, 모든 요청이 프로바이더로 직접 가는 경우 이는 불가능합니다. 전후 p50과 p95를 측정하십시오. 팀은 보통 캐싱이 켜진 후 중립 또는 개선된 숫자를 보게 됩니다.
Sources