vercel-labs/json-render — The Generative UI framework
vercel-labs/json-render — 안전한 JSON 기반 Generative UI 프레임워크
json-render는 AI가 자연어 프롬프트를 바탕으로 JSON UI 명세를 생성하고, 개발자가 정의한 컴포넌트와 액션 안에서만 화면을 렌더링하도록 하는 Generative UI 프레임워크입니다. React를 비롯해 Vue, Svelte, Solid, React Native, PDF, 이메일, 비디오, 3D, 터미널 UI까지 같은 카탈로그를 여러 출력 환경에서 활용할 수 있습니다.
- 주제
AI 요약
Vercel Labs의 json-render는 자연어 프롬프트를 UI로 변환하는 Generative UI 프레임워크입니다. 핵심 설계는 AI에게 임의의 코드를 생성하게 하는 대신, 개발자가 허용한 컴포넌트·속성·액션으로 구성된 카탈로그를 먼저 정의하고 AI가 그 범위 안에서 JSON 명세를 생성하게 만드는 방식입니다. 프로젝트는 이를 “guardrailed”, “predictable”, “fast”, “cross-platform”으로 설명합니다. AI가 사용할 수 있는 요소를 카탈로그로 제한하고, 출력은 스키마에 맞는 JSON으로 만들며, 모델 응답이 도착하는 동안 명세를 점진적으로 스트리밍하고 렌더링할 수 있다는 의미입니다.
■ 카탈로그와 타입 안전한 렌더링
기본 구성은 @json-render/core의 defineCatalog로 시작합니다. 예제에서는 React 스키마와 Zod를 사용해 Card, Metric, Button 컴포넌트를 등록합니다. Card는 title 문자열을 받고, Metric은 label·value 문자열과 currency·percent·number·null 중 하나인 format을 받으며, Button은 label과 action 문자열을 받도록 정의합니다. export_report와 refresh_data 같은 액션도 카탈로그에 등록할 수 있습니다. 각 컴포넌트에는 설명이 들어가므로 catalog.prompt()를 호출하면 컴포넌트 설명, props 스키마, 사용 가능한 액션을 포함한 시스템 프롬프트를 생성할 수 있습니다.
defineRegistry는 카탈로그에 정의한 타입과 실제 구현을 연결합니다. React 예제에서 Card는 title과 children을 HTML로 출력하고, Metric은 format 함수로 값을 표시하며, Button은 클릭 시 emit("press")를 호출합니다. 이후 Renderer에 AI가 만든 spec과 registry를 전달하면 JSON 명세를 실제 UI로 렌더링합니다. 즉 AI는 화면 구조와 데이터 표현을 결정하지만, 실행 가능한 컴포넌트 구현과 이벤트 처리 방식은 개발자가 통제합니다.
JSON 명세는 root와 elements를 갖는 평면 구조로 표현할 수 있습니다. root가 최상위 요소의 ID를 가리키고, elements 맵에서 각 요소의 type·props·children을 정의합니다. 예제의 card-1은 Card 타입으로 button-1을 자식으로 포함하고, button-1은 Button 타입으로 label을 지정합니다. 프로젝트는 이 구조를 통해 AI가 생성한 결과를 직접 실행 가능한 코드가 아니라 검증 가능한 데이터로 다루도록 합니다.
■ 상태, 조건부 표현식, 액션
요소의 visible 필드와 props 값에는 상태 기반 표현식을 사용할 수 있습니다. {"$state":"/form/hasError"}처럼 상태 경로를 읽을 수 있고, $cond와 $then·$else를 사용해 조건에 따라 값을 선택할 수 있습니다. 예를 들어 activeTab이 home인지 확인해 아이콘 이름을 home 또는 home-outline으로 바꾸고, 색상도 함께 변경할 수 있습니다. $template은 “Hello, ${/user/name}!”처럼 상태값을 문자열에 삽입하며, $computed는 등록된 함수를 인자와 함께 호출합니다.
setState 액션은 상태 모델을 직접 갱신합니다. Pressable 컴포넌트가 /activeTab 경로를 home으로 설정하면 해당 상태를 참조하는 visible 조건과 동적 props가 다시 평가됩니다. $bindState를 사용하면 Select의 value를 /form/country에 연결할 수 있고, watch 필드로 값 변경에 따른 후속 액션도 정의할 수 있습니다. 예제에서는 국가가 변경될 때 loadCities 액션을 호출하고, 현재 국가를 $state로 전달합니다. watch는 최초 렌더링 시가 아니라 감시 중인 값이 변경될 때 실행됩니다.
■ 스트리밍과 개발 도구
AI 응답을 점진적으로 처리할 때는 @json-render/core의 createSpecStreamCompiler를 사용합니다. 컴파일러에 응답 청크를 push하면 현재 result와 새로 적용된 newPatches를 얻을 수 있으며, result를 setSpec에 넣어 부분적으로 완성된 UI를 즉시 갱신할 수 있습니다. 모든 응답을 받은 뒤에는 getResult()로 최종 명세를 가져옵니다. 따라서 모델이 전체 JSON을 생성할 때까지 기다리지 않고, 도착한 구조에 맞춰 화면을 단계적으로 렌더링하는 흐름을 구성할 수 있습니다.
개발 중에는 React, Vue, Svelte, Solid용 devtools 어댑터를 사용할 수 있습니다. 인스펙터 패널은 spec 트리, 상태 편집기, 액션 로그, 스트림 로그, 카탈로그 브라우저, DOM picker를 제공합니다. React에서는 JsonRenderDevtools를 추가하고 Ctrl/Cmd + Shift + J로 패널을 열 수 있으며, 프로덕션 빌드에서는 tree-shaking을 통해 null로 제거된다고 안내합니다.
■ 여러 실행 환경을 지원하는 패키지 구성
기본 React 설치는 @json-render/core와 @json-render/react를 사용합니다. shadcn/ui 기반의 36개 사전 제작 컴포넌트가 필요하면 @json-render/shadcn을 추가할 수 있으며, shadcn-svelte용 패키지도 별도로 제공합니다. Vue 3, Svelte 5, SolidJS용 렌더러가 있고, React Native에는 25개 이상의 표준 컴포넌트와 표준 액션이 포함됩니다. 같은 카탈로그 개념을 활용해 Remotion 비디오 타임라인, React PDF 문서, React Email HTML·plain-text 이메일, Satori 기반 SVG·PNG 이미지, Ink 터미널 UI도 만들 수 있습니다.
웹 애플리케이션 단위로는 @json-render/next가 JSON으로 routes, layouts, SSR, metadata를 구성하도록 지원하며, TanStack Start용 렌더러도 routes, layouts, SSR, head metadata를 제공합니다. React Three Fiber 렌더러에는 Box, Sphere, 조명, OrbitControls와 GaussianSplat을 포함한 20개 컴포넌트가 준비되어 있습니다. 그 밖에 codegen, Redux·Zustand·Jotai·XState 어댑터, MCP Apps 통합, YAML wire format, 커스텀 디렉티브 패키지도 제공됩니다.
■ 시작 방법과 예제
저장소를 clone한 뒤 pnpm install과 pnpm dev를 실행하면 문서·플레이그라운드, 대시보드 데모, React Email 예제, Remotion 비디오 예제를 확인할 수 있습니다. React Native는 npx expo start로 실행하며, Vue·Svelte·Vite 렌더러와 React Three Fiber Gaussian Splatting 예제도 별도로 제공합니다. 프로젝트의 라이선스는 Apache-2.0입니다. 전체 흐름은 카탈로그로 가드레일을 정의하고, 자연어 프롬프트를 전달하고, AI가 JSON을 생성한 뒤, 각 플랫폼의 Renderer가 해당 명세를 안전하게 출력하는 구조로 정리할 수 있습니다.
원문: GitHub / 번역·요약: Trawling