에이전트가 차트를 선택했다면, 데이터는 그럴 자격이 있었을까? TypeScript로 UI 플래너를 구축하다
요약
CopilotKit이 오픈 소스 채팅 인터페이스 [Open Intelligent UI]를 공개했습니다. 이 시스템은 텍스트, 네이티브 컴포넌트, 생성된 인터랙티브 UI 등 다양한 방식으로 답변할 수 있습니다. 본 글에서는 에이전트가 시각화 방식을 결정할 때 데이터의 정확성과 투명성을 확보하는 TypeScript 기반 UI 플래너 구축 과정을 다룹니다.
핵심 포인트
- 에이전트의 표현 방식 선택을 명시적이고 검토 가능하게 만듦.
- 데이터 간극(gap)이나 측정되지 않은 값은 임의로 채우지 않도록 설계함.
- 애플리케이션 레지스트리를 통해 데이터 유형별 적절한 컴포넌트를 선택하는 것이 중요함.
2026년 10월 9일, CopilotKit은 Open Intelligent UI를 공개했습니다. 이는 텍스트, 네이티브 컴포넌트 또는 생성된 인터랙티브 UI로 답변할 수 있는 오픈 소스 채팅 인터페이스입니다.
흥미로운 엔지니어링 결정은 픽셀 이전에 일어납니다. 어떤 표현 방식이 답변에 적합한가?
프로젝트 README에 따르면, 그들의 Jev 라우터는 표현 방식을 선택합니다. 기본적인 표에는 A2UI를 사용하고, 차트나 더 복잡한 시각 자료에는 Open Generative UI를 사용합니다. 기본 설정은 OpenAI 키와 TypeSafe 키가 필요합니다. 저는 발표 내용과 README를 확인했지만, 전체 애플리케이션을 실행하지는 않았습니다.
저는 오늘 이 문제의 작은 부분을 구축하고 싶습니다: 제안된 시각화와 우리 애플리케이션이 실제로 사용할 컴포넌트 사이에 결정론적인 경계를 만드는 것입니다.
측정되지 않은 값은 측정되지 않은 채로 남아 있어야 합니다. 더 예쁜 답변이라고 해서 조용히 추세를 만들어내서는 안 됩니다.

차트는 잘못된 약속을 할 수 있다
에이전트가 3일간의 지연 시간(latency)을 요약하는 상황을 상상해 보세요:
| Date | Value | Unit |
|---|---|---|
| 2026-10-01 | 10 | ms |
| ... | ||
| 이 숫자들은 제품 측정값이 아닌 합성된 더미 데이터입니다. |
알 수 없는 값을 0으로 대체하면 데이터를 변경하게 됩니다. 간극(gap)을 설명하지 않고 알려진 지점들을 연결하면, UI는 우리가 관찰하지 않은 연속성을 제안할 수 있습니다.
차트 렌더러는 간극을 올바르게 표현할 수 있습니다. 이 작은 플래너는 의도적으로 표를 선택합니다. 이는 보수적인 제품 정책이지, 보편적인 시각화 규칙은 아닙니다.
목표는 표현 결정(representation decision)을 명시적이고, 검토 가능하며, 테스트 가능하게 만드는 것입니다.
애플리케이션에 컴포넌트 레지스트리를 제공하라
우리의 레지스트리는 두 가지 이름을 포함하고 있습니다:
- 완전하고 규칙적으로 간격이 떨어진 시계열 데이터에는
line-chart를 사용합니다. - 유효한 행들을 좀 더 문자 그대로 표현해야 할 때는
data-table을 사용합니다.
에이전트는 실행 가능한 HTML을 제공하지 않습니다. 데이터를 제공합니다. 애플리케이션은 소유된 컴포넌트를 선택하고 깨끗하게 정제된(clean) 행들을 그 컴포넌트에 전달합니다.
이 예시는 플랜(plan)을 반환할 뿐입니다. React 컴포넌트를 구현하거나 차트를 그리지는 않습니다.

규칙은 의도적으로 좁습니다. 차트를 그리려면 최소 세 개의 행, 하나의 정확한 단위 문자열(unit string), 유한한 숫자 값(finite numeric values), 엄격하게 증가하는 날짜(strictly increasing dates), 그리고 동일한 간격이 필요합니다. 이러한 차트 규칙 중 하나라도 충족하지 못하는 유효 데이터는 테이블이 됩니다. 형식이 잘못된 입력은 두 컴포넌트 중 어느 곳에도 들어가지 않고 오류를 발생시킵니다.
음수 값과 0은 유효한 숫자입니다. null은 누락을 의미합니다. 이들은 서로 다른 상태입니다.
플래너 구축하기 (Build the planner)
전체 소스 코드와 18가지 검사(checks)는 공개 저장소에 있습니다.
다음은 런타임 유효성 검사가 모든 행이 실제 달력 날짜, 비어있지 않은 단위, 그리고 유한한 숫자 또는 null을 가지고 있다고 확립한 후의 핵심 결정입니다:
const table = (reason: string): View => ({
component: "data-table", reason, rows: clean
});
...
이 코드가 무엇을 하지 않는지 주목하십시오. 빈 공간을 채우거나(fill gaps), 관측치를 재정렬하거나(reorder observations), 단위를 변환하거나(convert units), 값을 평활화하지 않습니다(smooth values). 제공된 순서와 값들을 그대로 유지합니다.
이것이 폴백(fallback) 설명 가능성을 높여줍니다. 프론트엔드는 다음과 같이 보여줄 수 있습니다: “측정값 하나가 누락되었기 때문에 테이블을 표시하고 있습니다.”
전체 함수는 unknown 타입을 받아 엔벨로프(envelope)와 모든 행을 검사하고, 입력을 100개 행으로 제한하며, 오직 date, value, 그리고 unit만을 복사합니다. 추가적인 html 필드는 렌더링 지침이 되지 않습니다.
선택된 필드를 복사하는 것은 이 경계를 넘는 데이터의 양을 줄일 뿐입니다. 이것이 임의의 문자열을 HTML에 주입해도 안전하게 만든다는 의미는 아닙니다. 렌더러(Renderers)는 여전히 일반적인 이스케이핑(escaping) 처리가 필요합니다.
API 키 없이 실행하기
전제 조건: Node.js 22.20 이상. Node의 타입 스트리핑(type stripping)은 의존성 설치나 컴파일 단계 없이 이 TypeScript 파일을 실행합니다. 이는 파일에 대한 타입 검사(type-check)를 수행하지는 않습니다.
git clone https://github.com/bobbyhalljr/generative-ui-planner.git
cd generative-ui-planner
node --experimental-strip-types test.ts
테스트 실행의 마지막 세 줄은 다음과 같습니다:
18/18 checks passed
complete: line-chart (complete-regular-series)
missing: data-table (missing-values)
이 검사들은 0, 음수 값, 누락된 값(missing values), 혼합 단위(mixed units), 중복 및 내림차순 날짜, 불규칙한 간격(irregular spacing), 불가능한 달력 날짜, NaN, 무한대(infinity), 비어 있거나 너무 큰 입력, 잘못 구성된 엔벨로프(malformed envelopes), 빈 단위(blank units), 제외된 추가 마크업(excluded extra markup), 그리고 원본 입력을 보존하는 경우를 다룹니다.
이것들은 로컬 정책에 대한 결정론적 검사일 뿐입니다. 모델 정확도, CopilotKit 라우팅 또는 생성된 UI 품질의 벤치마크는 아닙니다.
이것이 멈추는 지점
이것은 단일 시계열(time series)을 위한 작은 플래너입니다. 어떤 측정 항목이 신뢰할 만한지, 그 출처가 최신인지, 또는 연결된 점들이 인과적으로 의미가 있는지 여부를 결정하지 않습니다. 동일 간격으로 배치하는 것은 통계적 유효성의 증거가 아니라 선택된 적합성 규칙(eligibility rule)입니다.
또한 생성된 코드에 대한 iframe 샌드박스(sandbox), CSP, 인증 시스템 또는 안전한 인터프리터를 제공하지도 않습니다. CopilotKit의 발표는 격리된 iframe 실행과 오픈 UI 경로를 위한 승인된 CDN 목록을 설명합니다. 저는 이러한 제어 장치들을 감사(audit)하지 않았습니다.
실제 서비스(production UI)에서는 접근성 컴포넌트, 보이는 단위(visible units), 출처(provenance), 차트 간격 의미론(chart gap semantics), 정직한 축(honest axes) 그리고 애플리케이션이 제안하는 표현을 변경할 때 사용자가 검사할 수 있는 이유를 추가할 것입니다.
엔지니어링 관점에서 얻은 교훈은 작습니다. 에이전트가 경험을 제안하게 하고, 애플리케이션이 데이터 표현의 규칙을 소유하도록 하라는 것입니다.
제가 Roster를 구축하면서 신경 쓰는 경계가 바로 이런 종류입니다: 사람들이 검사하고 사용할 수 있는 결과물을 내놓는 실제 업무를 수행하는 AI 직원들입니다.
주요 참고 자료
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기