선언형 생성 UI

선언형 생성 UI (Declarative generative UI)

선언형 생성 UI는 생성 UI 스펙트럼중간에 위치해요. 에이전트가 구조화된 명세(specification) 를 내보내고, 프론트엔드는 사전에 등록해둔 컴포넌트 카탈로그에서 인터페이스를 조합하는 방식이에요. 에이전트의 출력이 채팅 거품 속 텍스트 응답 대신 그 자체가 UI가 됩니다 — 폼, 카드, 대시보드 같은 것들이죠. 어떤 컴포넌트를 쓸 수 있는지(카탈로그)는 여러분이 정하고, 에이전트는 그것들을 유효한 UI 트리로 조합해요. 카탈로그가 가드레일(guardrail) 이 되어 이 접근법을 안전하게 만듭니다. 에이전트는 여러분이 승인한 컴포넌트를 자유롭게 배열·결합할 수 있지만, 그 바깥으로는 나갈 수 없어요. 이는 창의성과 예측 가능성 사이의 균형을 잡아주죠.

여기 긴 꼬리(long tail)가 살아있습니다. 픽셀 단위의 완벽함보다 폭(breadth)을 택하는 방식이라, 정확한 통제보다 유용한 무언가를 보여주는 게 더 중요한 보조 상호작용, 내부 도구, 대시보드에 잘 맞아요. 이 페이지는 json-render로 선언형 생성 UI를 다루는데, json-render는 컴포넌트 카탈로그를 정의하고 AI로 spec을 생성하며 React, Vue, Svelte, Angular 전반에서 안전하게 렌더링하는 생성 UI 프레임워크예요. Google의 A2UI 스펙(CopilotKit으로 통합)은 아래 A2UI 섹션을 참고하세요.

출처: LangChain 공식 문서 — declarative-generative-ui

이 접근법을 언제 쓸까요? (When to use this approach)

제품의 긴 꼬리 부분에 선언형 생성 UI를 쓰세요. 여러분이 승인한 컴포넌트 집합 안에서 에이전트가 완전히 예측하지 못한 레이아웃을 조합할 수 있어야 하는 곳이죠 — 보조 상호작용, 내부 도구, 대시보드 같은 곳입니다. 서페이스가 트래픽이 많거나 브랜드가 중요하고 정확해야 한다면 통제형 생성 UI로 이동하세요. 애플리케이션 밖에서 만들어진 인터페이스를 원한다면 개방형 생성 UI로 이동하면 됩니다.

어떻게 동작하나요? (How it works)

  1. 카탈로그 정의 — AI가 쓸 수 있는 컴포넌트를 타입이 지정된 props와 함께 선언해요.
  2. AI에 프롬프트 — 원하는 UI를 자연어로 설명하죠.
  3. AI가 spec 생성 — 컴포넌트 트리를 설명하는 JSON 문서를 만들어요.
  4. 안전하게 렌더링 — json-render의 Renderer가 여러분의 컴포넌트로 spec을 렌더링합니다.

카탈로그는 가드레일 역할을 해요. AI는 여러분이 정의한 컴포넌트만, 여러분의 스키마에 맞는 props로 쓸 수 있어요. 출력은 항상 예측 가능하고 안전합니다.

컴포넌트 카탈로그 정의 (Define a component catalog)

카탈로그는 AI가 사용할 수 있는 모든 컴포넌트를 기술해요. 각 컴포넌트는 props를 위한 Zod 스키마와, AI가 언제 이 컴포넌트를 써야 하는지 이해하도록 돕는 설명(description)을 가집니다.

컴포넌트 레지스트리 구축 (Build a component registry)

레지스트리는 각 카탈로그 컴포넌트를 실제 렌더링 구현에 매핑해요. defineRegistry를 사용하면 카탈로그 props와 컴포넌트 함수 사이에 타입 안전한 바인딩을 얻을 수 있습니다.

에이전트에 연결 (Connect to the agent)

에이전트는 구조화된 출력(structured output)을 사용해 json-render spec을 반환해요. useStream을 에이전트의 assistant ID로 설정하고, AI 메시지의 tool_calls에서 spec을 추출하면 됩니다.

점진적으로 스트림하고 렌더링 (Stream and render progressively)

스트리밍 동안 spec은 조금씩 쌓여요. 요소가 하나씩 도착하고, 처음에는 type이나 props가 없을 수도 있어요. 완전한 요소만 걸러내고 Rendererloading={true}를 넘기면, 아직 도착하지 않은 자식 요소를 조용히 건너뛰어요. UI가 컴포넌트 하나씩 구성되는 방식이죠.

spec 형식 (The spec format)

AI 에이전트는 root 키가 루트 요소를 가리키고 elements 맵이 모든 컴포넌트를 담는 평면(flat) JSON spec을 생성해요. 각 요소는 자식을 ID로 참조하고, TextInput·Button 같은 리프(leaf) 요소는 빈 children 배열을 가집니다.

A2UI: 대안적 선언형 spec (A2UI: an alternative declarative spec)

인터페이스를 선언형으로 기술하는 한 가지 방법이 json-render라면, A2UI는 또 다른 방법이에요. A2UI는 Google의 선언형·스트리밍 우선 생성 UI 스펙으로, CopilotKit을 통해 통합됩니다. json-render처럼 여러분이 등록한 컴포넌트로 인터페이스를 조합하므로, 에이전트는 여러분이 정의한 가드레일 안에 머물러요. A2UI에는 두 가지 변형이 있습니다.

  • 동적 스키마 (Dynamic schema) — 보조 모델이 대화로부터 스키마·데이터·레이아웃을 포함한 전체 인터페이스를 생성해, 최대 유연성을 제공해요.
  • 고정 스키마 (Fixed schema) — 컴포넌트 트리는 프론트엔드에서 정의하고 에이전트는 데이터만 스트림해, 가장 빠르고 예측 가능한 렌더링을 제공하죠.

자세한 내용은 CopilotKit 문서의 A2UI, dynamic schema, fixed schema를 참고하세요. CopilotKit을 LangGraph 배포에 연결하려면 CopilotKit을 보세요.

모범 사례 (Best practices)

  • 설명적인 컴포넌트 설명 사용 — AI가 각 컴포넌트를 언제 쓸지 이해하는 데 설명이 쓰여요. 명확한 설명이 더 나은 UI 생성을 이끕니다.
  • 렌더링 전 검증 — 스트리밍은 부분 데이터를 전달하므로, Renderer에 넘기기 전에 항상 요소의 type이 유효하고 props가 null이 아닌지 확인하세요.
  • 스트리밍을 위해 설계 — 스트리밍 중 loading={true}를 넘겨 Renderer가 아직 오지 않은 자식을 우아하게 처리하게 하세요. 사용자는 전체 응답을 기다리는 대신 UI가 실시간으로 쌓이는 걸 봅니다.
  • 디자인 토큰으로 스타일링 — CSS 커스텀 프로퍼티를 사용해 렌더링된 컴포넌트가 라이트/다크 테마에 자동으로 적응하게 하세요.
  • JSONUIProvider로 감싸기 — 상태·가시성·액션을 위한 json-render의 내부 컨텍스트에 접근하려면 RendererJSONUIProvider 안에 있어야 해요.

같이 보기 (See also)

더 알아보기 (Learn more)