reopt designreopt design
DocsExploreToolsPricingBuilder
시작하기
개요
시작하기
핵심 개념
컴포넌트 가이드
Rich Parts
스타일링
구축·운영
Tool 승인 UI
커스텀 파트
Production readiness
Oopt-chat
reopt designreopt design

AI 시대를 위한 디자인 시스템

  • 문서
  • 가격
  • 릴리즈 노트
  • GitHub
  • 서비스 약관
  • 개인정보처리방침

© 2026 reopt-ai. All rights reserved.

구축·운영
  1. 문서
  2. /
  3. 구축·운영
  4. /
  5. 커스텀 파트 렌더러

커스텀 파트

MessageParts의 renderPart 콜백을 사용하여 기본 제공되지 않는 메시지 파트 타입에 대한 맞춤 렌더러를 작성하는 방법을 설명합니다.

reopt design · 업데이트 2026년 6월 26일

1. renderPart API

MessageParts의 renderPart 콜백은 각 파트에 대해 호출됩니다. undefined를 반환하면 기본 렌더러가 사용되고, ReactNode를 반환하면 해당 렌더러를 완전히 대체합니다.

tsx
import type { UIMessage } from "ai";
import { MessageParts } from "@reopt-ai/opt-chat";

// renderPart 콜백 시그니처
type RenderPart = (
  part: UIMessage["parts"][number],
  index: number,
) => React.ReactNode | undefined;

// undefined를 반환하면 해당 파트에 기본 렌더러가 적용됩니다.
// ReactNode를 반환하면 기본 렌더러를 완전히 대체합니다.

<MessageParts
  parts={message.parts}
  renderPart={(part) => {
    // 커스텀 타입만 처리하고, 나머지는 기본 렌더러에 위임
    switch (part.type) {
      case "chart":
        return <MyChartRenderer data={part.data} />;
      case "approval":
        return <MyApprovalCard request={part.request} />;
      default:
        return undefined; // 기본 렌더러 사용
    }
  }}
/>

2. 예제: 차트 파트 렌더러

AI 응답에 차트 데이터가 포함된 경우, 커스텀 "chart" 파트 렌더러를 만들어 opt-ui의 BarChart로 시각화하는 전체 예제입니다.

tsx
"use client";

import { DefaultChatTransport, type UIMessage } from "ai";
import {
  useChatSession,
  Conversation,
  ConversationContent,
  Message,
  MessageContent,
  MessageParts,
  PromptInput,
  PromptInputFooter,
  PromptInputSubmit,
  PromptInputTextarea,
} from "@reopt-ai/opt-chat";
import { BarChart } from "@reopt-ai/opt-charts";

// 커스텀 차트 파트 타입 정의
interface ChartPart {
  type: "chart";
  data: Array<{ name: string; value: number }>;
  title: string;
  chartType: "bar" | "line" | "pie";
}

function ChartPartRenderer({ part }: { part: ChartPart }) {
  return (
    <div className="border-border my-2 rounded-lg border p-4">
      <h4 className="text-text-primary mb-3 text-sm font-semibold">
        {part.title}
      </h4>
      <BarChart
        data={part.data}
        series={[{ dataKey: "value", name: "값" }]}
        height={200}
      />
    </div>
  );
}

export default function ChatWithCustomParts() {
  const session = useChatSession({
    transport: new DefaultChatTransport({ api: "/api/chat" }),
  });

  return (
    <div className="flex h-dvh flex-col">
      <Conversation>
        <ConversationContent>
          {session.messages.map((msg) => (
            <Message key={msg.id} from={msg.role}>
              <MessageContent>
                <MessageParts
                  parts={msg.parts}
                  renderPart={(part: UIMessage["parts"][number]) => {
                    if (part.type === "chart") {
                      return <ChartPartRenderer part={part as ChartPart} />;
                    }
                    return undefined;
                  }}
                />
              </MessageContent>
            </Message>
          ))}
        </ConversationContent>
      </Conversation>
      <PromptInput onSubmit={session.handleSubmit} isLoading={session.isLoading}>
        <PromptInputTextarea />
        <PromptInputFooter>
          <div className="flex-1" />
          <PromptInputSubmit />
        </PromptInputFooter>
      </PromptInput>
    </div>
  );
}

3. 여러 커스텀 파트 등록

커스텀 파트가 여러 개인 경우, 레지스트리 패턴으로 renderPart 콜백을 깔끔하게 관리할 수 있습니다.

tsx
// 여러 커스텀 파트를 등록하는 패턴
const customRenderers: Record<string, (part: any) => React.ReactNode> = {
  chart: (part) => <ChartPartRenderer part={part} />,
  kanban: (part) => <KanbanPartRenderer part={part} />,
  form: (part) => <FormPartRenderer part={part} />,
  diff: (part) => <DiffPartRenderer part={part} />,
};

<MessageParts
  parts={msg.parts}
  renderPart={(part) => {
    const renderer = customRenderers[part.type];
    return renderer ? renderer(part) : undefined;
  }}
/>
PreviousTool 승인 UIAI SDK 도구 호출 승인/거부 흐름과 Confirmation 컴포넌트 사용법구축·운영
Tool 승인 UI 페이지로 이동
NextProduction readinessinstall smoke, browser matrix, streaming soak, release ops를 묶은 opt-chat 배포 직전 체크리스트구축·운영