Cloudflare Agents SDK의 AI SDK v7 업그레이드와 회귀 테스트 개요

Cloudflare Agents SDK를 AI SDK v7로 업그레이드하고 스트리밍·도구 호출 회귀 테스트하기

Cloudflare Agents SDK가 AI SDK v7을 지원한다는 소식만 보면 패키지 버전 올리고 끝인가 싶어요. 근데 여기서 냅다 의존성만 바꾸면 스트림은 나오는데 중간 chunk가 버퍼링되거나, 승인 전 도구가 실행되거나, 재연결 뒤 같은 결과가 두 번 저장되는 식의 애매한 회귀를 놓칠 수 있습니다.

결론부터 말하면 Cloudflare의 호환층과 애플리케이션의 v7 마이그레이션은 별개예요. 패키지 메이저를 한 세트로 맞춘 뒤, 결정론적 mock 테스트와 Workers 런타임 테스트를 같이 돌려야 함. 이 글은 2026년 7월 26일 기준 공식 문서와 공식 저장소에서 확인한 변경점으로 그 순서를 정리합니다.

Cloudflare 호환 패키지, 앱 코드 마이그레이션, 회귀 테스트의 세 갈래 개념도

v7 지원과 v7 네이티브 전환은 같은 말이 아니에요

Cloudflare는 2026년 7월 23일 agents, @cloudflare/ai-chat, @cloudflare/codemode, @cloudflare/think가 AI SDK v6와 v7을 모두 지원한다고 발표했어요. 조합은 딱 두 세트로 보는 게 편합니다.

서버·코어 React UI
ai@^6 @ai-sdk/react@^3
ai@^7 @ai-sdk/react@^4

AI SDK v7로 갈 거라면 Cloudflare 패키지는 최신 호환판으로, ai는 v7로, React 바인딩은 v4로 함께 맞춥니다.

npm i agents@latest @cloudflare/ai-chat@latest \
  @cloudflare/codemode@latest @cloudflare/think@latest \
  ai@^7 @ai-sdk/react@^4

v7 지원이 처음 명시된 릴리스는 agents@0.19.0, @cloudflare/think@0.15.0, @cloudflare/codemode@0.5.0, @cloudflare/ai-chat@0.10.0이에요. 다만 이 숫자는 “지원이 공개된 최초 릴리스”로 봐야 합니다. 조사일의 latest나 실제 설치 시점 버전은 달라질 수 있으니 lockfile에 해석된 버전과 peer 경고를 다시 확인해야 해요.

중요한 건 Cloudflare 호환판이 앱의 deprecated API까지 알아서 현대화해 주는 건 아니라는 점입니다. Cloudflare 내부에서는 v6와 v7에 공통인 이름이나 alias를 사용하고, 서로 다른 도구 완료 payload를 경계에서 정규화해요. 기존 코드를 살려 주는 안전망인 셈.

하지만 앱 코드의 systeminstructions로 바꿀지, 승인 정책을 어디로 옮길지, 다단계 결과를 어떻게 읽을지는 여전히 직접 판단해야 합니다. 호환됨과 마이그레이션 완료됨은 다름. 여기서 한 번 멈춰 체크하는 게 마음 편-안.

관련 근거는 Cloudflare AI 변경 로그Cloudflare Agents 릴리스 노트에서 확인할 수 있습니다.

먼저 Node 22와 ESM부터 맞춰야 합니다

AI SDK v7은 Node.js 22 이상과 ESM을 요구합니다. Worker에서 돌아가는 코드라 해도 로컬 개발 환경, 테스트 runner, CI가 오래된 Node를 쓰면 Vitest나 번들 단계에서 먼저 막힐 수 있어요. Worker만 보고 “런타임 문제없음” 하기엔 앞단이 제법 많단 말이지…

프로젝트 전체를 ESM으로 바꾼다면 package.json"type": "module"을, 개별 파일 단위라면 .mjs 전환을 검토합니다. CommonJS require()는 지원 대상이 아니에요.

그다음 기존 v6 동작을 회귀 테스트로 먼저 고정하고 아래 순서로 진행하면 됩니다.

  1. v6 기준 동작과 실패 경로를 테스트로 고정합니다.
  2. Node.js 22 이상과 ESM 조건을 충족합니다.
  3. Cloudflare 패키지, ai, 모든 @ai-sdk/* 패키지를 호환 메이저로 함께 맞춥니다.
  4. npx @ai-sdk/codemod v7을 실행하고 diff를 검토합니다.
  5. codemod가 판단하지 못하는 의미 변경을 수동으로 수정합니다.
  6. 같은 회귀 테스트를 v7 의존성 해석에서 다시 실행합니다.

codemod는 import와 rename 정리에 도움이 되지만 만능은 아니에요. runtime/tool context 분리, 승인 정책 위치, stream helper, 다단계 결과 형상은 사람이 봐야 합니다. 자동 변환 돌렸으니 끝! 했다가 테스트에서 총체적난국 가능.

v6 테스트 고정부터 v7 재검증까지 이어지는 6단계 업그레이드 순서도

이름 변경보다 의미 변경을 더 유심히 봐야 해요

대표적인 v6 표현과 v7 방향은 다음과 같습니다.

v6에서 익숙한 표현 v7 방향 놓치기 쉬운 회귀
system instructions system message 처리 조건 변화
onFinish onEnd callback 횟수와 payload assertion 실패
fullStream stream consumer와 fixture 불일치
experimental_telemetry telemetry 관측 설정 누락
tool({ needsApproval }) 호출·agent 레벨 toolApproval 승인 없는 자동 실행
result.toUIMessageStreamResponse() top-level createUIMessageStreamResponse HTTP 응답 생성 경로 차이

여기서 system이나 결과 객체의 stream response 메서드를 곧바로 “삭제돼서 깨지는 API”라고 부르면 부정확합니다. 조사일 현재 Cloudflare Chat 문서는 호환 가능한 기존 형태의 예제를 계속 제공하고 있고, AI SDK v7 쪽에서는 새 이름과 top-level helper를 권장해요.

즉 지금 작동할 수는 있지만 v7 네이티브 정리 대상이라는 뜻입니다. deprecated와 removed를 한 바구니에 넣지 않기.

다단계 결과도 꼭 봐야 해요. v7의 top-level content, tool calls/results, files, sources, warnings, usage는 마지막 step만 보여 주는 게 아니라 전체 run의 결과를 누적합니다. 마지막 step만 필요하면 finalStep을 사용해야 해요.

기존 테스트가 result.toolCalls.length === 1처럼 마지막 단계라고 암묵적으로 가정했다면 v7에서 전체 호출 수를 세게 됩니다. 테스트가 실패하면 그나마 다행이고, 우연히 통과하면 더 곤란함. 전체 run assertion과 finalStep assertion을 따로 두는 게 안전합니다.

AI SDK v7 변경 방향은 Vercel의 AI SDK 7 발표, Cloudflare의 현재 사용 형태는 Chat agents 문서에서 비교할 수 있어요.

스트리밍 테스트는 최종 문자열만 보면 부족합니다

스트리밍 테스트에서 완성된 답변만 비교하면 사실상 generate 테스트와 크게 다르지 않아요. 중간 delta가 한꺼번에 몰려오는 buffering 회귀도 최종 문자열은 멀쩡할 수 있거든요.

AI SDK 공식 테스트 API의 MockLanguageModelV3simulateReadableStream을 사용하면 실제 모델 호출 없이 text-start → 여러 text-deltatext-end → finish 순서를 결정론적으로 만들 수 있습니다. 네트워크 비용과 모델의 비결정성을 빼고 프로토콜 자체를 검사하는 1차 방어선.

기본 suite에는 적어도 아래 항목을 넣는 게 좋아요.

  • 첫 delta가 전체 완료 전에 관찰되는지
  • text-start, 동일 ID의 delta, text-end 순서가 맞는지
  • finish chunk 없이 provider stream이 끝나면 오류가 되는지
  • 도구 실행 실패는 tool-error, 일반 오류는 error part로 나오는지
  • 중간 abort 뒤 새 delta가 전달되지 않고 자원이 정리되는지
  • provider metadata가 text, UI stream, tool invocation과 다음 turn까지 보존되는지
  • 내부 오류가 UI용 안전한 오류 문자열로 바뀌고 상세 내용은 노출되지 않는지

Cloudflare AIChatAgent 통합 테스트는 HTTP stream에서 끝내면 안 됩니다. this.messagesUIMessage[]는 SQLite에서 읽히고 interaction 뒤 자동 저장되므로, 완료 후 저장된 message parts까지 확인해야 해요.

한 turn의 여러 chunk가 assistant message 하나로 저장되는지, 연결이 끊긴 뒤 resume cursor로 이어 받아도 delta와 message가 중복되지 않는지 체크합니다. 사용자가 stop을 눌렀을 때 CF_AGENT_CHAT_REQUEST_CANCELoptions.abortSignal로 전파되고, 앱이 그 signal을 streamText({ abortSignal })에 넘기는지도 필수.

UI 상태 계약도 같이 고정해 둡니다.

  • 정상 흐름: "submitted""streaming""ready"
  • 오류 흐름: 최종 상태 "error"
  • durable recovery: isRecovering은 true지만 아직 token이 없을 수 있음
  • busy 판단: isStreaming || isRecovering
  • server stream·active client tool: isServerStreaming 유지
  • tool result·approval 뒤 자동 continuation: isToolContinuation 확인

로딩 표시 정도로 보이지만 이 플래그들이 중복 submit과 continuation 분기에 직접 쓰여요. 영원히 "streaming"에 갇힌 UI… 보기만 해도 아찔함.

text-start와 delta부터 종료, 저장, UI 상태 전이까지의 스트리밍 회귀 테스트 타임라인

도구 호출은 실행 전후와 재연결까지 한 묶음입니다

Cloudflare AIChatAgent의 도구 패턴은 서버, 클라이언트, 승인 도구로 나눌 수 있습니다.

패턴 실행 위치 핵심 검사
서버 도구 Worker/server의 execute schema, 1회 실행, 결과 part, 다음 step
클라이언트 도구 브라우저 onToolCall 대기 상태, 동일 toolCallId, 결과 뒤 continuation
승인 도구 승인 뒤 server 실행 승인·거절 전 미실행, 승인 뒤 1회

서버 도구는 이름과 입력 snapshot만 맞는다고 끝이 아니에요. “도구 호출 생성 → schema 검증 → execute → tool result → 모델의 최종 text” 전체 흐름을 검사해야 합니다. 반복 호출에는 stopWhen: stepCountIs(n) 같은 loop 상한도 필요하고요.

회귀 matrix는 이렇게 잡을 수 있습니다.

  1. 정상 입력은 정확한 tool name/input으로 execute가 한 번만 실행되고 output part와 최종 답변까지 이어집니다.
  2. schema 위반은 InvalidToolInputError 또는 stream 오류 part로 나타나며 execute 횟수는 0입니다.
  3. 없는 도구는 NoSuchToolError로 처리되고 UI에는 안전한 오류 문자열만 전달됩니다.
  4. 도구 내부 실패는 tool-error로 끝나며 loading 상태가 풀리고 같은 도구가 무한 반복되지 않습니다.
  5. 다단계·병렬 호출은 전체 run 누적 결과와 finalStep 결과를 따로 검증합니다.
  6. 모델이 계속 도구를 요청해도 stepCountIs(n)에서 종료됩니다.
  7. 클라이언트 도구는 output 전에는 이어지지 않고, 같은 call ID의 output 뒤 정확히 한 번 continuation 됩니다.
  8. 승인 전과 거절 뒤 side effect는 0회, 승인 뒤는 1회여야 합니다.
  9. replay나 reconnect 뒤에도 승인 도구가 두 번 실행되지 않습니다.
  10. v7에서는 needsApproval에 기대지 않고 호출·agent 레벨 toolApproval이 실제 정책을 적용하는지 확인합니다.

특히 8번과 9번은 보안과 데이터 중복 문제라서 그냥 “도구 호출 성공” 테스트로 대체하기 어렵습니다. 승인 버튼 보이니까 됐겠지? 안 됨. 실제 side effect count가 계약이에요.

Cloudflare 호환층의 관측 callback도 한 가지 함정이 있습니다. v6 도구 완료 이벤트와 v7 이벤트를 ToolCallResultContext로 정규화하지만, v7 이벤트에는 stepNumber가 없어 정규화된 context에서도 undefined예요. 로깅 코드가 이를 필수 숫자로 가정하지 않는지, 완료 callback은 딱 한 번 발생하는지 확인해야 합니다.

Workers 런타임까지 통과해야 업그레이드 완료

mock 단위 테스트가 프로토콜을 빠르게 잡아 준다면 Workers pool 테스트는 실제 Worker와 Durable Object 실행 경계를 확인합니다. Cloudflare 공식 구성은 vitest@^4.1.0, @cloudflare/vitest-pool-workers, 그리고 cloudflareTest plugin을 사용해요.

import { cloudflareTest } from "@cloudflare/vitest-pool-workers";
import { defineConfig } from "vitest/config";

export default defineConfig({
  plugins: [
    cloudflareTest({
      wrangler: { configPath: "./wrangler.jsonc" },
    }),
  ],
});

테스트에서는 cloudflare:workersenv, exportscloudflare:testcreateExecutionContext, waitOnExecutionContext를 사용해 실제 Worker route를 호출할 수 있습니다.

최종 게이트는 아래처럼 층을 나누면 확인하기 편해요.

  • lockfile에서 ai@7, @ai-sdk/react@4, provider 호환 메이저가 하나씩 해석되는지 확인
  • TypeScript typecheck
  • Worker bundle과 ESM import 검사
  • AI SDK mock 단위 테스트
  • Workers pool 통합 테스트
  • 브라우저·WebSocket 환경의 재연결, 취소, 클라이언트 도구, 승인 E2E 테스트
  • 실제 provider smoke test는 기본 mock suite와 분리

Cloudflare는 소비자 CI에서도 v6와 v7 resolution을 각각 테스트하라고 권고합니다. 다만 앱이 v7 전용 API로 완전히 전환했다면 v6 job이 계속 제품 요구사항인지는 별도로 판단해야 해요. Cloudflare 라이브러리의 dual-major 지원 검증과 소비자 앱의 v7-only 검증을 섞지 않는 것, 은근 중요함.

typecheck와 번들부터 실제 provider smoke test까지의 층별 테스트 피라미드

합격 기준은 프로토콜과 실행 횟수로 잡아요

이 글에서 제안하는 기준은 제품 SLA가 아니라 업그레이드 회귀 계약입니다.

  • Node.js 22 이상과 ESM 조건에서 typecheck와 Worker bundle 성공
  • 2개 이상 delta fixture에서 첫 delta를 완료 전에 관찰하고 최종 조합 문자열 일치
  • toolCallId에 call 1개와 terminal output 또는 error 1개만 존재
  • 승인 전·거절 뒤 side effect 0회, 승인 뒤 1회
  • reconnect·resume 뒤 assistant message와 tool output 중복 없음
  • cancel 뒤 새 delta와 새 tool 실행 없음
  • error·abort·approval·recovery 뒤 UI가 영구 "streaming" 상태로 남지 않음
  • 전체 run 결과와 finalStep 결과가 각각 기대값과 일치
  • v7의 stepNumber === undefined를 허용하면서 callback은 한 번만 실행

실제 provider smoke test에서는 생성 문장 자체보다 protocol invariant, tool schema, 상태 전이를 보는 편이 낫습니다. 기본 회귀 suite는 mock으로 결정론적으로 유지하고요. 모델 답변까지 글자 단위로 맞추려 들면 테스트가 먼저 지침 ㅋㅋㅋ

마지막으로 2026년 7월 23일 릴리스 노트에는 provider 관련 시점성 제한도 기록돼 있습니다. 당시 workers-ai-provider는 AI SDK v7용 v4로 고정돼 있었고, chat@4.31.0ai@^6 peer만 선언한 상태였어요. 7월 26일 이후 패치로 달라졌을 수 있으니 설치 시점의 lockfile과 peer 경고를 다시 보는 게 맞습니다.

Cloudflare Agents SDK의 AI SDK v7 지원은 업그레이드 문턱을 낮춰 주지만, 앱 코드의 의미 변화와 회귀 테스트까지 없애 주진 않아요. 최종 문자열 하나 대신 chunk 순서, 실행 횟수, 승인 전 side effect, 재연결 중복까지 계약으로 잡으면 훨씬 든든합니다. 패키지는 한 번 올리고 끝나도 테스트는 경계를 봐야 함.

CloudflareAgents #AISDKv7 #CloudflareWorkers #AIChatAgent #스트리밍테스트 #도구호출 #회귀테스트 #Vitest

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다