본문 바로가기
Q&A2026년 6월 4일2분 읽기

Vercel AI SDK 6 streamUI — RSC 안에서 tool generate가 두 번 실행

노
노련한백엔드
조회 422댓글 5

AI SDK 6의 streamUI로 챗봇 만들고 있는데 tool의 generate가 두 번 실행됩니다.

const result = await streamUI({
  model: anthropic('sonnet-4-9'),
  prompt: query,
  tools: {
    search: {
      description: '검색',
      parameters: z.object({ q: z.string() }),
      generate: async ({ q }) => {
        console.log('search called:', q)  // 같은 query에 2번 로그
        const results = await db.search(q)
        return <Results data={results} />
      },
    },
  },
})

console.log에 같은 query 2번 출력. DB query도 2번 실행. 비용 부담 + 부작용 우려.

댓글 5

김김영삼4개월 전

AI SDK 6의 streamUI는 server에서 generate 1번, client에서 hydration 시 1번 (RSC 특성). 의도된 동작이지만 부작용 있는 경우 패턴이 있습니다.


해결 — generate 결과 캐시


같은 입력에 같은 결과 반환되도록 cache로 감싸기:


import { cache } from 'react'

const cachedSearch = cache(async (q: string) => {
return await db.search(q)
})

const result = await streamUI({
tools: {
search: {
generate: async ({ q }) => {
const results = await cachedSearch(q) // 같은 q에 1번만
return <Results data={results} />
},
},
},
})

React cache가 같은 request 안에서 1번만 실행 보장. server·client hydration 동일 결과.


또는 — generate 안에서 일부만


tool의 generate를 두 단계로 분리:


tools: {
search: {
execute: async ({ q }) => { // 1번만 호출
return await db.search(q)
},
generate: async ({ q, result }) => { // hydration 시 result만 사용
return <Results data={result} />
},
},
},

execute는 server에서 1번, generate는 UI만 만듦. side effect 분리.


주의 — server-only 함수


generate가 server-only 코드 (e.g., DB query) 포함 시 'use server' 명시 또는 별도 server module로 분리:


// server/search.ts
'use server'
export const search = cache(async (q: string) => {
return await db.search(q)
})

저희 운영


tool마다 execute로 side effect 1번 처리, generate는 UI만. cache 활용으로 같은 입력에 자동 dedupe. DB query 비용 50% 절감.

풀풀스택지훈4개월 전

AI SDK 6의 streamUI는 RSC + Suspense + streaming 다 결합되어 디버깅 어렵습니다. tool execute 단계와 UI render 단계 분리하는 게 정착 패턴.

rrsc_dev(guest)4개월 전
RSC에서 fetch dedupe도 자동인데 generate는 React component 단위라 자동 dedupe 안 됩니다. cache 명시 추천.
주주말프로젝트(guest)4개월 전
운영 6개월 경험인데 위에 적힌 함정 모두 거쳤습니다. 처음부터 정착 패턴 알았으면 좋았을 텐데...
한한지민(guest)4개월 전
위 패턴 적용하면서 한 가지 더 알게 된 — 캐시 invalidation 정책이 처음 생각보다 복잡합니다. 별도로 관리 필요.
Ctrl+Enter로 등록