
누가 표면(Surface)을 소유하는가?
요약
생성형 UI의 본질이 단순한 컴포넌트 렌더링을 넘어 에이전트와 UI 간의 결합 방식에 있음을 설명합니다. 에이전트가 제품의 부가 기능이 아닌 제품의 중심이 되는 '역전' 현상과 표면의 예측 가능성에 따른 세 가지 패턴을 다룹니다.
핵심 포인트
- 생성형 UI는 단순 렌더링이 아닌 에이전트와 UI의 결합 체계(Taxonomy) 문제임
- 에이전트가 제품의 중심이 되어 UI가 에이전트를 위해 존재하는 '역전' 현상 발생
- 표면의 예측 가능성에 따라 Catalog, Vocabulary, Sandbox의 세 가지 패턴으로 구분됨
- 에이전트가 언제, 어떤 UI를 사용자에게 제시할지가 핵심 디자인 질문임
제가 대화해 본 대부분의 사람들은 생성형 UI (Generative UI)가 모델이 React 컴포넌트를 즉석에서 렌더링하게 하는 것이라고 생각합니다. 그것은 이 아이디어의 가장 좋지 않은 버전이며, 만약 당신이 그것을 출시하고 있다면 당신은 이미 패배한 것입니다.
실제 이야기는 분류 체계 (Taxonomy)에 관한 것입니다. 에이전트 (Agent)와 UI가 어떻게 결합되는지에 대한 세 가지 패턴이 있으며, 이는 각각 다른 종류의 표면 (Surface)에 적합하도록 멱법칙 (Power law)에 따라 분포되어 있습니다. 그리고 이 분류 체계 아래에는 우리가 관심을 가질 만한 더 조용한 싸움이 있습니다. 바로 모델과 픽셀 (Pixels) 사이의 레이어를 누가 통제하느냐 하는 문제입니다.
그 내용을 살펴보겠습니다.
역전 (The Inversion)
"우리는 AI 어시스턴트를 출시했다"와 "우리는 풀스택 에이전트 애플리케이션 (Fullstack agentic application)을 구축했다" 사이에는 실질적인 차이가 있으며, 이는 마케팅과는 아무런 관련이 없습니다.
사이드바에 있는 어시스턴트 (Assistant-on-the-side) 버전에서는, 에이전트가 화면에 무엇이 있는지 모르고, 사용자가 방금 무엇을 클릭했는지 모르며, 사이드바에 텍스트를 반환하는 것 외에는 아무것도 할 수 없습니다. 그 아래의 애플리케이션은 전혀 상관하지 않습니다. 에이전트는 스티커와 같습니다.
풀스택 (Fullstack) 버전에서는, 에이전트가 앱과 상태 (State)를 공유하고, UI를 구동하며, 사용자의 곁으로 이동합니다. 앱이 끝나는 지점과 에이전트가 시작되는 지점 사이에 깔끔한 선을 그을 수 없습니다. 에이전트는 제품 옆에 주차된 기능이 아니라, 제품이 작동하는 방식의 일부입니다.
이것이 바로 역전입니다. 에이전트는 제품 내의 기능이기를 멈춥니다. 제품이 에이전트를 중심으로 휘어지기 시작합니다. UI는 에이전트가 작동할 수 있는 표면 (Surfaces)을 제공하기 위해 존재합니다.
이것은 디자인 질문을 완전히 뒤바꿉니다. 더 이상 "사용자가 어떻게 컴포넌트를 프롬프트(Prompt)하는가"가 아닙니다. 질문은 다음과 같습니다: 에이전트가 사용자 앞에 어떤 UI를 놓아야 할지, 언제 그것을 놓아야 할지, 그리고 어떻게 신뢰를 깨뜨리지 않고 그것을 수행할지를 어떻게 알 수 있는가?
이 질문은 표면 (Surface)이 얼마나 예측 가능한지에 따라 세 가지 답변으로 나뉩니다.
세 가지 패턴, 하나의 멱법칙 (Three Patterns, One Power Law)
제가 본 가장 깔끔한 프레임워크는 이를 빈도 분포 (frequency distribution)로 정의하는 것입니다. 실제 제품 내의 대부분의 표면 (surfaces)은 예측 가능합니다. 그것들이 어떻게 보여야 하는지 알고 있으며, 이미 설계를 마친 상태입니다. 일부 표면은 형태가 대략적으로 알려져 있지만 가변적입니다. 그리고 극소수는 진정으로 개방적 (open-ended)입니다.
저는 이를 각각 에이전트 (agent)에게 실제로 전달하는 것에 따라 카탈로그 (Catalog), 어휘 (Vocabulary), 그리고 **샌드박스 (Sandbox)**라고 부르겠습니다. 사전 구축된 컴포넌트 (components)의 카탈로그, 에이전트가 조합하여 사용하는 기본 요소 (primitives)의 어휘, 그리고 제3자 표면 (third-party surfaces)이 실행되는 샌드박스입니다.
이들 사이의 선택은 미적인 문제가 아닙니다. 이는 예측 가능성, 신뢰, 그리고 모델에 얼마나 많은 제어권을 넘겨줄 것인지와 얼마나 많은 제어권을 유지할 것인지에 대한 결정입니다.
각각의 패턴을 자세히 살펴보겠습니다.
패턴 1: 카탈로그 (The Catalog)
이것은 대부분의 팀이 시작해야 할 지점이며, 현재 프로덕션 환경에서 실제로 운영되는 대부분의 에이전트 기반 앱 (agentic apps)이 존재하는 방식입니다.
그 형태는 다음과 같습니다: 여러분은 고정된 컴포넌트 카탈로그(막대 그래프, 파이 차트, 컨텍스트 카드, 버튼 등 디자인 시스템에 이미 포함된 것들)를 선언하며, 각 컴포넌트에는 명칭, 기능, 그리고 필요한 인자 (arguments)가 주석으로 달립니다. 미들웨어 (middleware) 레이어가 이 카탈로그를 에이전트가 볼 수 있는 도구 정의 (tool definitions)로 변환합니다. 에이전트는 실행되어 등록된 컴포넌트 중 하나가 정답이라고 판단하면, 그에 해당하는 도구를 호출합니다. 프론트엔드 도구 호출 (frontend tool call)은 백엔드 실행을 일시 중지하고 제어권을 클라이언트 (client)로 넘기며, SDK는 해당 호출을 컴포넌트에 매핑하고, 속성 (props)을 채운 뒤, 이를 마운트 (mount)합니다.
이 패턴을 중심으로 형성되고 있는 오픈 프로토콜은 AG-UI입니다. 이는 CopilotKit 내에서 LangGraph 및 CrewAI와 함께 시작된 MIT 라이선스 기반의 이벤트 프로토콜(event protocol)로, 현재 Mastra, Microsoft의 Agent Framework, AG2, Agno, 그리고 LlamaIndex 전반에 걸쳐 구현되어 있습니다. 설계 단계부터 프레임워크에 구애받지 않습니다 (Framework-agnostic).
여기서 주목해야 할 점은 모델이 UI 코드를 절대 생성하지 않는다는 것입니다. 대신 모델은 사용자가 이미 설계하고, 테스트하고, 승인한 메뉴 중에서 선택합니다. '생성적 (generative)'인 부분은 선택과 데이터 바인딩 (data binding)이지, 마크업 (markup), 레이아웃 (layout), 또는 스타일링 (styling)이 아닙니다.
이것이 바로 예측 가능해야 하는 표면 (surfaces), 즉 여러분 제품의 대부분이 원하는 방식입니다. 대시보드, 카드, 인라인 답변, 액션 버튼 등이 이에 해당합니다. 막대그래프가 여러분의 디자인 시스템을 망가뜨리는 3D 회전 파형으로 나타나 깜짝 놀라게 하는 일은 없을 것입니다. 그것은 여러분의 막대그래프입니다. 에이전트는 단지 그것을 사용하기로 결정했을 뿐입니다. Grafana Assistant는 이에 대한 깔끔한 프로덕션 사례입니다. 이는 자유 형식의 텍스트나 마크업만 사용하는 대신, Grafana의 기존 컴포넌트 어휘 (panels, plots, queries, tables)를 사용하여 응답하는 사이드바 채팅입니다. 컴포넌트는 미리 정의되어 있습니다. 에이전트의 역할은 대화에 적합한 컴포넌트를 선택하고 이를 올바른 데이터에 연결 (wire)하는 것입니다.
만약 이러한 패턴 중 하나를 구축한다면, 바로 이 패턴을 구축하십시오. 이는 실제 제품의 표면 영역 대부분을 커버하며, 런타임 리스크 (runtime risk)가 진정으로 제한되는 유일한 방식입니다.
패턴 2: 어휘 (The Vocabulary)
때로는 가능한 모든 컴포넌트를 미리 등록할 수 없는 경우도 있습니다. 에이전트가 여러분이 예상하지 못한 레이아웃을 구성해야 할 수도 있고, 데이터 형태 (data shape)가 매번 다를 수도 있습니다. 표면이 여러분의 카탈로그에 맞지 않는 요청에 응답해야 할 때도 있습니다.
그 지점에서 선언적 접근 방식 (declarative approach)의 가치가 드러납니다. 여기서의 오픈 스펙은 a2ui.org에 있는 A2UI (Agent-to-UI)로, Google이 CopilotKit과 협력하여 오픈 소스로 공개했습니다. 핵심 아이디어는 간단합니다.
에이전트는 코드를 보내지 않습니다. 고정된 메뉴에서 선택하지도 않습니다. 대신 의도에 대한 선언적 기술(declarative description, 구조화된 작업)을 방출하며, 클라이언트의 렌더러(renderer)가 해당 작업들을 귀하의 디자인 시스템(design system)에 기반한 네이티브 UI 컴포넌트로 구체화합니다.
React를 내부적으로 다뤄본 적이 있다면 이 방식이 익숙하게 느껴질 것입니다. 이는 리컨실러(reconciler)와 유사한 형태이지만, 컴포넌트 트리(component tree) 대신 에이전트가 신뢰할 수 있는 단일 원천(source of truth) 역할을 합니다. 에이전트는 "이 제목, 이 본문, 이 세 가지 액션을 가진 카드를 보여줘"라고 말합니다. 그러면 렌더러가 이를 귀하의 디자인 시스템에 매핑합니다. 모델은 결코 <div>를 건드리지 않으며, Tailwind 클래스를 작성하지도, 간격(spacing)을 결정하지도 않습니다.
Notion AI는 실제 사례로서 이를 보여주는 깔끔한 예시입니다. 구조화된 페이지 초안을 작성해 달라고 요청하면, Notion AI는 마크업(markup)을 생성하는 대신 Notion의 기존 블록 어휘(headings, tables, callouts, toggles, databases)를 사용하여 구성합니다. 실제 UI는 Notion의 렌더러가 처리합니다.
A2UI에는 처음 보기에 생각보다 중요한 두 가지 방식이 있습니다:
- 고정 스키마 (Fixed schema): 레이아웃을 사전에 구축합니다. 에이전트는 런타임(runtime)에 데이터를 채워 넣습니다. 예측 가능한 구조와 동적인 콘텐츠가 특징입니다.
- 동적 스키마 (Dynamic schema): 두 번째 모델 패스(model pass)가 실제 대화 내용에 맞춰 레이아웃 자체를 생성합니다. 여전히 사양 수준의 제약 조건은 유지되지만, 구조는 실행 중에 결정됩니다.
고정 스키마는 더 안전한 기본값이며, 아마도 이 패턴을 사용할 때 대부분의 경우 원하는 방식일 것입니다. 동적 스키마는 형태를 사전에 열거할 수 없는 경우에 사용합니다. 설령 그렇다 하더라도, 사양(spec)은 모델을 귀하가 정의한 샌드박스(sandbox) 안에 머물게 합니다.
어떤 방식이든, 모델과 픽셀(pixels) 사이의 계층은 바로 _귀하의 것_입니다. 그것이 바로 중요한 부분입니다.
패턴 3: 샌드박스 (The Sandbox)
곡선의 저 먼 끝단입니다. 정답이 "컴포넌트를 렌더링(render a component)하라" 또는 "레이아웃을 구성(compose a layout)하라"가 아닐 때 당신이 갈구하게 되는 것입니다. 그것은 바로 "내 앱 안에 이 다른 앱 전체를 열어라"입니다.
여기서 오픈 표준은 MCP Apps입니다. 이는 더 넓은 범위의 Model Context Protocol (MCP)의 일부로, MCP-UI와 OpenAI의 이전 작업들을 하나의 사양(specification)으로 통합한 것입니다. 세 가지 구성 요소가 존재하며, 이들 사이의 경계가 핵심적인 역할을 수행합니다.
사양(spec) 상태에 대해 짚고 넘어갈 가치가 있습니다: MCP Apps는 이미 존재하며 실제 운영 환경에서 사용되고 있지만, 다가오는 MCP 2026-07-28 사양 개정(현재 출시 후보(release candidate) 상태이며, 5월 21일에 확정되어 7월 28일에 최종 출시 예정)을 통해 전용 라이프사이클(lifecycle)을 가진 일급 확장(first-class extension)으로 공식화됩니다. 패턴은 안정적이며, 이를 둘러싼 표면(surface)은 통합되고 있습니다.
**서버 (Server)**는 도구(tools)와 UI 표면(UI surfaces) 자체를 모두 게시합니다. 각 도구는 임베드 가능한(embeddable) 앱을 가리키는 URI를 포함합니다. **호스트 (Host)**는 귀하의 프론트엔드 앱입니다. 호스트는 임베드된 표면을 샌드박스 처리된 iframe 내에 마운트(mount)하고, 에이전트(agent)와 임베드된 앱 사이의 메시지를 중개합니다. **뷰 (View)**는 샌드박스 처리된 iframe 내에서 실행되는 표면 그 자체입니다. 뷰는 귀하의 DOM에 접근할 수 없습니다. 귀하의 쿠키를 읽을 수 없습니다. postMessage를 통해 응답하는 것 외에는 아무것도 할 수 없습니다.
서버와 호스트 간의 도구 호출(Tool calls). 호스트와 뷰 간의 postMessage 및 JSON-RPC. 세 개의 경계, 세 개의 신뢰 구역(trust zones), 그리고 이들 사이에는 공유된 상태(shared state)가 없습니다.
이것은 플랫폼 형태의 무언가, 즉 제3자(third-party) 경험을 오케스트레이션(orchestrate)하는 '호스트들의 호스트(host-of-hosts)'를 구축할 때 적합한 패턴입니다. 에이전트가 어떤 임베드된 표면을 열지 선택합니다. 개발자는 통합(integration)을 미리 연결해 두었습니다. 사용자는 에이전트의 표면 바로 안에서 실행되는 제3자 앱을 보게 되며, 에이전트는 그 앱을 제어할 수 있습니다.
Claude와 ChatGPT 모두 현재 프로덕션 환경에서 이 패턴의 변형을 출시하여 제공하고 있습니다. 두 모델 모두 에이전트의 제품 내부에 임베디드(embedded)된 제3자 UI 표면(연결된 도구, MCP 서버 앱)을 호스팅할 수 있으며, 호스트(host)와 뷰(View) 사이를 중개하는 샌드박스 처리된 iframe을 사용합니다.
이는 가장 강력한 패턴인 동시에 가장 위험한 패턴입니다. 당신은 소유하지 않은 코드를 임베디드하고 있는 것입니다. iframe 샌드박스는 단순한 장식이 아닙니다. 그것은 하중을 견디는 핵심 요소(load-bearing)입니다. 이 아키텍처의 핵심 목적은 뷰(View)가 내부로 침투할 수 없고, 외부로 읽어낼 수 없으며, 당신이 열어둔 채널을 통해서 대화하는 것 외에는 아무것도 할 수 없도록 만드는 것입니다. 이 경계를 엄격하게 다루지 않을 것이라면, 이 패턴을 아예 출시하지 마십시오.
그렇다면 각 패턴은 어디에 적합한가?
암묵적인 전략을 명시적으로 드러내 보자면:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기

