reopt designreopt design
DocsExploreToolsPricingBuilder
Login
Start
Overview
Start
Core Concepts
Component Guide
Rich Parts
Styling
Build & Operate
Tool Approval UI
Custom Parts
Production readiness
Oopt-chat
reopt designreopt design

A design system for the AI era

  • Docs
  • Pricing
  • Releases
  • GitHub
  • Terms of Service
  • Privacy Policy

reopt Inc.Business registration no. 217-88-02453contact@reopt.ai

© 2026 reopt Inc. All rights reserved.

Core Concepts
  1. Docs
  2. /
  3. Core Concepts
  4. /
  5. Component Guide

핵심 컴포넌트

opt-chat의 core 모듈을 구성하는 컴포넌트와 훅의 역할, props, 조합 패턴을 설명합니다.

reopt design · Updated Aug 2, 2026

1. Core 모듈 개요

Core 모듈은 채팅 UI의 뼈대를 담당합니다. * 표시는 필수 컴포넌트를 나타냅니다.

컴포넌트설명주요 Props
Conversation*채팅 로그의 스크롤 컨테이너 + 엔진. 하단 팔로우, 턴 앵커링, prepend 위치 보존을 자체 구현합니다 (외부 스크롤 라이브러리 없음).children, autoScroll, scrollEdgeThreshold, scrollPreviousItemPeek, scrollMargin
ConversationMessage메시지 턴 래퍼. scrollAnchor=true인 턴은 추가 시 하단 점프 대신 뷰포트 상단에 정착합니다 (보통 user 턴에 지정). content-visibility 컨테인먼트도 제공합니다.messageId, scrollAnchor, children
ConversationScrollButton하단에 안 본 메시지가 있을 때 나타나는 '아래로 스크롤' 버튼. 하단에 있을 때는 inert로 tab 순서에서 빠집니다.scrollLabel, className
Message*단일 메시지 렌더러. role에 따라 사용자/어시스턴트 버블을 자동 구분합니다.from, isStreaming, children
PromptInput*메시지 입력 영역. 자동 리사이즈, 파일 첨부, 전역 드롭, 모델 선택을 지원합니다.onSubmit, accept, maxFiles, globalDrop, children
PromptInputAttachmentsPromptInput이 관리하는 첨부 목록을 렌더링하고 제거 액션을 연결합니다.variant, labels, onRemove
MessagePartsAI SDK UIMessage.parts 배열을 파트 타입별로 자동 매핑하여 렌더링합니다.parts, renderPart
Shimmer스트리밍 중 표시되는 타이핑 애니메이션 컴포넌트.className
Suggestion*추천 프롬프트 버튼. 클릭 시 자동으로 메시지를 전송합니다.prompt, label, onClick
useChatSessionAI SDK useChat를 감싸는 훅. PromptInput 첨부 payload를 files 전송으로 연결합니다.transport, messages, onToolCall

2. Compound Component 패턴

opt-chat은 compound component 패턴을 사용합니다. Conversation이 세션 컨텍스트를 제공하고, Message와 PromptInput이 이를 소비합니다. children을 통해 각 단계에서 커스텀 렌더링을 삽입할 수 있습니다.

tsx
// Conversation > ConversationMessage > Message > MessageParts 계층 구조
<Conversation>
  <ConversationContent>
    {session.messages.map((msg) => (
      // scrollAnchor=user 턴 → 전송 시 질문이 상단에 정착
      <ConversationMessage
        key={msg.id}
        messageId={msg.id}
        scrollAnchor={msg.role === "user"}
      >
        <Message from={msg.role}>
          <MessageContent>
            <MessageParts parts={msg.parts} isStreaming={session.isStreaming} />
          </MessageContent>
        </Message>
      </ConversationMessage>
    ))}
  </ConversationContent>
  <ConversationScrollButton />
</Conversation>

<PromptInput onSubmit={session.handleSubmit}>
  <PromptInputAttachments />
  <PromptInputTextarea />
  <PromptInputFooter>
    <PromptInputActionAddAttachment />
    <PromptInputSubmit />
  </PromptInputFooter>
</PromptInput>

3. MessageParts 자동 매핑

Message 컴포넌트는 내부적으로 MessageParts를 사용하여 메시지의 content 배열을 파트 타입별로 자동 렌더링합니다. 기본 매핑 규칙과 커스텀 renderPart 콜백을 설명합니다.

tsx
// MessageParts의 자동 매핑 규칙
// AI SDK UIMessage.parts 배열의 type에 따라 렌더러가 결정됩니다:

// type: "text"         → MessageResponse (마크다운 렌더링)
// type: "reasoning"    → Reasoning (사고 과정 접기/펼치기)
// type: "tool-*"       → Tool (도구 호출 + 상태 배지)
// type: "source-url"   → Sources (접을 수 있는 출처 목록)
// type: "file"         → ChatImage (image/*) 또는 null

// 커스텀 파트 타입은 renderPart 콜백으로 처리합니다
<MessageParts
  parts={message.parts}
  renderPart={(part) => {
    if (part.type === "chart") return <MyChart data={part.data} />;
    return null; // null 반환 시 기본 렌더러 사용
  }}
/>

4. 스크롤 엔진과 턴 앵커링

Conversation은 외부 스크롤 라이브러리 없이 자체 스크롤 엔진을 내장합니다. 세 가지 동작이 자동으로 맞물립니다.

  • 하단 팔로우 — 독자가 하단에 있을 때만 스트리밍을 따라 스크롤합니다. 위로 스크롤하면 팔로우가 해제되고 읽던 위치가 보존됩니다. 하단으로 돌아오면 다시 팔로우가 재개됩니다.
  • 턴 앵커링 — ConversationMessage에 scrollAnchor를 지정한 턴(보통 user 메시지)은 추가될 때 하단으로 튀는 대신 뷰포트 상단 근처(scrollPreviousItemPeek, 기본 64px 아래)에 정착합니다. 이전 대화가 살짝 보여 문맥이 유지되고, 응답이 스트리밍 으로 자라도 앵커 위치가 고정됩니다.
  • prepend 위치 보존 — 히스토리 페이지네이션으로 위쪽에 메시지가 추가돼도 현재 스크롤 위치가 유지됩니다.

접근성: 뷰포트는 role="region" + tabIndex=0(키보드 스크롤)이고, 메시지 목록은 role="log" + aria-relevant="additions"로 신규 메시지를 스크린리더에 알립니다. 프로그래매틱 스크롤이 필요하면 useConversationScroller()(scrollToEnd/scrollToStart/ scrollToMessage), 스크롤 상태 구독은 useConversationScrollable()를 사용합니다.

tsx
// 프로그래매틱 스크롤 — 전송 직후 하단으로 이동
import { useConversationScroller } from "@reopt-ai/opt-chat";

function SendButton() {
  const { scrollToEnd, scrollToMessage } = useConversationScroller();
  // scrollToEnd({ behavior: "smooth" })
  // scrollToMessage(messageId, { behavior: "smooth" })
}

// 스크롤 옵션 튜닝 (기본값 표시)
<Conversation
  autoScroll                    // 하단에 있을 때 스트리밍 팔로우
  scrollEdgeThreshold={8}       // 상/하단 판정 여유(px)
  scrollPreviousItemPeek={64}   // 앵커 위로 보여줄 이전 대화(px)
>
  ...
</Conversation>
PreviousStart패키지 설치, useChatSession 연결, 첫 채팅 UI 렌더링까지의 빠른 시작 가이드Start
Go to Start
NextRich PartsReasoning, Tool, CodeBlock, Sources, Artifact 등 AI 출력 전용 파트 컴포넌트Core Concepts