Nuxt로 배포하기

Nuxt로 배포하기

Nitro 서버 라우트, Vue 컴포저블, 하위 에이전트 인식 채팅 UI를 갖춘 Nuxt 4 앱에 LangChain 딥 에이전트를 배포해요.

이 페이지는 Nuxt 4 프로젝트 안에 LangChain 딥 에이전트를 배포하는 예시 앱을 자세히 설명해요: 스트리밍 채팅 UI, 하위 에이전트 상세 보기, 스레드 기록, reasoning 토큰 스트리밍까지, 모두 Nitro 라우트 핸들러(HTTP + SSE)로 구현된 Agent Streaming Protocol을 기반으로 해요. 별도의 백엔드 프로세스 없음.

소스: 배포 쿡북js-nuxt.

출처: 문서

본문

배포

Vercel

  1. 저장소 가져오기: 아래의 Deploy with Vercel을 클릭하거나, langchain-ai/deployment-cookbook을 수동으로 가져오세요.
  2. 프로젝트 구성: Root Directoryjs-nuxt로 설정하고 프로젝트 설정에 OPENAI_API_KEY를 추가하세요.
  3. 배포: 프로젝트를 배포하세요. Nuxt가 Vercel을 자동으로 감지하고 Agent Streaming Protocol API용 Nitro 서버 라우트를 빌드해요.

Netlify

  1. 저장소 가져오기: 아래의 Deploy to Netlify를 클릭하거나, langchain-ai/deployment-cookbook을 수동으로 가져오세요.
  2. 프로젝트 구성: Base directoryjs-nuxt로 설정하세요. Netlify가 그 하위 디렉터리에서 Nuxt 빌드를 실행해요.
  3. 환경 변수 설정: 첫 빌드가 완료되기 전에 Netlify 배포 설정에 OPENAI_API_KEY를 추가하세요.

Node

  1. 프로덕션 빌드:

    cd js-nuxt
    cp .env.example .env   # set OPENAI_API_KEY for local dev
    pnpm install
    pnpm build
    
  2. 환경 변수 설정: 호스트에서 OPENAI_API_KEY를 내보내세요. Nitro는 런타임에 환경에서 읽어요. 선택적으로 .env.example의 변수를 추가해 LangSmith 추적을 활성화할 수 있어요.

  3. Nitro 서버 시작:

    node .output/server/index.mjs
    

    Node.js 프로세스를 살려 두는 프로세스 매니저나 컨테이너 오케스트레이터 뒤에서 실행하세요.

@langchain/vue는 스트림에서 하위 에이전트를 발견하고 하위 에이전트마다 클릭 가능한 칩을 렌더링해요. 하나를 선택하면 useMessages를 통해 해당 하위 에이전트의 네임스페이스된 messagestools 채널에 바인딩된 범위 지정 채팅 뷰가 열려요. Reasoning 요약은 접을 수 있는 "Thinking" 블록으로 스트리밍되고, 스트리밍 중에는 자동으로 펼쳐져요.

필수 API 엔드포인트

앱은 /api/threads/... 아래에 Agent Streaming Protocol을 노출해요. Nitro 라우트 핸들러는 server/api/threads/에 있어요.

최소 (스트리밍 채팅)

@langchain/vueHttpAgentServerAdapter로 싱글 스레드 스트리밍 채팅을 실행하려면 이 세 엔드포인트로 충분해요:

메서드 경로 목적
POST /api/threads/:threadId/commands 프로토콜 명령(run.start, …)을 받고 에이전트 런을 시작
POST /api/threads/:threadId/stream 런에 대한 프로토콜 이벤트의 SSE 스트림
GET / POST /api/threads/:threadId/state 체크포인트된 스레드 상태 읽기 및 부트스트랩

클라이언트는 GET /state로 스레드를 부트스트랩하고(404면 POST /state) 첫 메시지가 전송되기 전에 하이드레이션이 404가 되지 않도록 해요.

선택 (스레드 사이드바)

이 예시는 스레드 기록 사이드바용 엔드포인트도 구현해요. UI에 멀티 스레드 관리가 필요 없으면 생략해도 돼요:

메서드 경로 목적
GET /api/threads 체크포인터가 아는 스레드 나열
DELETE /api/threads/:threadId 스레드의 세션과 체크포인트 삭제
POST /api/threads/:threadId/history 페이지네이션된 체크포인트 기록 (Agent Protocol)

요청 흐름

%%{init: {"themeVariables": {"lineColor": "#40668D", "primaryColor": "#E5F4FF", "primaryTextColor": "#030710", "primaryBorderColor": "#006DDD"}}}%%
flowchart TB
  subgraph browser["Browser (Vue)"]
    SP["StreamProvider"]
    Adapter["HttpAgentServerAdapter"]
    SP --- Adapter
  end

  subgraph nitro["Nitro route handlers"]
    CMD["POST /api/threads/:id/commands"]
    STR["POST /api/threads/:id/stream (SSE)"]
    STA["GET|POST /api/threads/:id/state"]
  end

  subgraph server["server/utils"]
    SRV["session · threads · runtime"]
  end

  subgraph agent["server/agent"]
    AGT["createDeepAgent + checkpointer"]
  end

  Adapter -->|POST| CMD
  Adapter -->|POST| STR
  Adapter -->|GET / POST| STA
  CMD --> SRV
  STR --> SRV
  STA --> SRV
  SRV --> AGT

  classDef process fill:#E5F4FF,stroke:#006DDD,stroke-width:2px,color:#030710
  classDef trigger fill:#F6FFDB,stroke:#6E8900,stroke-width:2px,color:#2E3900
  classDef output fill:#EBD0F0,stroke:#885270,stroke-width:2px,color:#441E33
  class browser,nitro process
  class server trigger
  class agent output
  1. 스레드 상태 부트스트랩 (GET/POST /state).
  2. 제출 시 SDK는 /commandsrun.start를 보내고 run_id를 받아요.
  3. SDK는 재생 + 라이브 프로토콜 이벤트를 위해 /stream(SSE)을 구독해요.
  4. 하위 에이전트(task) 런은 stream.subagents로 표면화되는 네임스페이스된 이벤트를 방출해요.

Nitro 백엔드 설계

관심사 구현
프론트엔드 app/의 Vue 컴포넌트 (SSE용 <ClientOnly>로 래핑)
API 계층 server/api/threads/의 Nitro 라우트 핸들러
런타임 Node.js (Nitro preset은 배포 대상에 따라 다름)
SSE 재생 프로세스 로컬 LocalThreadSession (server/utils/session.ts)
에이전트 런 같은 Nitro 프로세스; 이벤트는 LangGraph StreamChannel에 버퍼링됨
스레드 저장 인메모리 MemorySaver 체크포인터 (server/agent/index.ts)
시크릿 로컬에서는 .env; 프로덕션에서는 호스트 환경 변수

에이전트의 체크포인터가 스레드의 단일 진실 소스예요. 클라이언트 측 캐시가 없어서 사이드바는 항상 서버에서 가져오고, 서버를 재시작하면 모든 스레드가 지워져요.

프로덕션 영속성

기본적으로 에이전트는 인메모리 MemorySaver 체크포인터(server/agent/index.ts)와 프로세스 로컬 세션 맵(server/utils/runtime.ts)을 사용해요. 이는 로컬 개발과 단일 인스턴스 서버에는 작동하지만, 서버리스 또는 멀티 인스턴스 호스트에서는 콜드 스타트나 레플리카 간에 대화 상태가 영구적이지 않아요.

프로덕션의 경우 내구성 있는 체크포인터를 교체하세요:

패키지 백엔드
@langchain/langgraph-checkpoint-redis Redis (RedisSaver)
@langchain/langgraph-checkpoint-postgres Postgres (PostgresSaver)
@langchain/langgraph-checkpoint-sqlite SQLite (SqliteSaver)

server/agent/index.tsMemorySaver를 교체하고 새 체크포인터를 createDeepAgent에 전달하세요. Nitro 라우트 핸들러와 server/utils/threads.ts 헬퍼는 그대로 유지돼요.

또한 서버리스 호출 간에 SSE 재연결이 작동하도록 server/utils/runtime.ts에 공유 세션/재생 스토어를 원할 거예요.

자세한 내용은 체크포인터 라이브러리메모리/영속성 추가를 참고하세요.

로컬 개발

cp .env.example .env   # set OPENAI_API_KEY
pnpm install
pnpm dev

http://localhost:3000을 여세요. 하위 에이전트에 위임하는 프롬프트를 보내고 그들의 작업이 전용 카드로 스트리밍되는 것을 보세요.

pnpm build      # production build
pnpm preview    # preview the production build
pnpm typecheck  # vue-tsc over the project

프로젝트 구조

프로젝트 구조

  • server/agent/researchermath-whiz 하위 에이전트, mock 도구, stripReasoningReplay 미들웨어가 있는 딥 에이전트(createDeepAgent).
  • server/utils/ — 프로토콜 서버 로직: session.ts (SSE 런), threads.ts (체크포인터 기반 상태), serialize.ts, runtime.ts.
  • server/api/threads/ — 위 프로토콜 엔드포인트용 Nitro 라우트 핸들러.
  • app/components/@langchain/vue를 사용하는 Vue 채팅 UI (ChatApp, Chat, ThreadHistory, SubagentList, MessageReasoning, …).
  • app/utils/threads.ts — 서버 구동 스레드 헬퍼와 LangGraph SDK 부트스트랩.

백엔드 세부 사항

  • server/agent/index.ts — 코디네이터는 Responses API를 통해 reasoning 모델을 사용하고, 도구 사용 하위 에이전트는 chat-completions를 사용해요 (체크포인터를 통한 reasoning 항목 재생 방지).
  • server/agent/middleware.tscontent + tool_calls에서 이전 어시스턴트 메시지를 재구성해서 오래된 reasoning id가 Responses API에 재생되지 않게 해요.
  • server/utils/session.tsLocalThreadSession은 프로토콜 이벤트를 버퍼링하고 matchesSubscription을 통해 일치하는 프레임을 SSE로 팬아웃해요.
  • server/api/threads/index.get.tsGET /api/threads, 체크포인터 기반 스레드 목록.
  • server/api/threads/[threadId]/…commands, stream, state (GET/POST), history, DELETE용 핸들러.

프론트엔드 세부 사항

  • app/components/ChatThread.vueHttpAgentServerAdapter를 만들고 provideStream({ transport, threadId })를 호출해요.
  • app/components/Chat.vue — 컴포저와 하위 에이전트별 상세 뷰(breadcrumb 포함)가 있는 메시지 뷰.
  • app/components/SubagentList.vue / SubagentDetail.vue — 인라인 하위 에이전트 카드와 범위 지정 하위 에이전트 채팅(네임스페이스에 바인딩된 useMessages).
  • app/components/MessageReasoning.vue — reasoning 요약용 접을 수 있는 "Thinking" 블록.

더 알아보기

더 알아보기 (Learn more)