0.1 → 0.2 마이그레이션
@reopt-ai/opt-chat 0.2.0 릴리스의 변경 사항. 대부분 호환 shim이 적용되어 즉시 마이그레이션은 필수가 아닙니다.
reopt design업데이트
1. 한눈에 보기
0.2.0은 회귀 수정, 누락 컴포넌트 13개 포팅, 인프라 개선이 묶인 릴리스 입니다. 대부분의 breaking 변경은 호환 shim 또는 deprecation 경고로 처리되었습니다. 이후 1.1에서 Conversation 스크롤 엔진이 교체되며 유일한 props breaking 변경이 있습니다 (아래 2번 섹션).
| 영역 | Before | After | 분류 | 메모 |
|---|---|---|---|---|
| MessageBranchContent | <MessageBranchContent>{a}{b}{c}</MessageBranchContent> | <MessageBranchContent branches={[a, b, c]} /> | deprecated (호환) | children API는 유지되지만 dev 환경에서 1회 console.warn. branches prop이 우선. |
| MessageBranch.totalBranches | <MessageBranch totalBranches={3}> | <MessageBranch> // 자동 감지 | 옵셔널화 | 명시 prop이 우선이지만 미지정 시 MessageBranchContent의 children 개수로 자동 감지. |
| Tool.Output 렌더링 | <pre>{JSON.stringify(output)}</pre> | <CodeBlock language="json" code={...} /> | 회귀 복원 | 객체 / 문자열 출력 모두 CodeBlock으로 렌더링. 시각적 변경. |
| ToolHeader.type 타입 | ComponentProps<"button"> & { type?: string } | Omit<ComponentProps<"button">, "type"> & { type?: string } | 타입 fix | HTML button.type ("submit"|"reset"|"button")과의 충돌 해소. 사용자 타입 호환. |
| Shimmer 키프레임 | opt-ui 글로벌 CSS에만 정의 | @reopt-ai/opt-chat/styles.css에서도 정의 | 호환 추가 | opt-ui 미사용 컨슈머는 import "@reopt-ai/opt-chat/styles.css" 필요. |
| PromptInput 헬퍼 | (없음) | captureScreenshot, convertBlobUrlToDataUrl, attachmentsToFileUIParts 직접 export | 신규 추가 | PromptInput 외부에서도 사용 가능. PromptInputModelSelector / PromptInputAttachments 슬롯 신규. |
| PromptInput.onSubmit | (message: string) => void | (message, { attachments, fileParts }) => void | 호환 확장 | 기존 1-인자 콜백은 그대로 호환. 첨부 전용 메시지와 AI SDK FileUIPart 전송을 지원. |
| ModelSelector / VoiceSelector | 커스텀 dropdown | PopoverRoot + listbox semantics | 접근성 개선 | outside click, Escape 닫기, Arrow/Home/End 키보드 이동, aria-selected를 공통 지원. |
| 신규 컴포넌트 13개 | (없음) | Task, Commit, PackageInfo, JSXPreview, Sandbox, WebPreview, OpenIn, MicSelector + flow/{Canvas,...} | 신규 추가 | @reopt-ai/opt-chat/flow는 별도 subpath. @xyflow/react optional peer 필요. |
| Conversation 스크롤 (1.1) | <Conversation initial="smooth" resize="smooth"> | <Conversation autoScroll scrollPreviousItemPeek={64}> | breaking (props) | use-stick-to-bottom 제거, 자체 엔진으로 교체. ConversationProps가 자체 props로 변경. 턴 앵커링은 ConversationMessage scrollAnchor로 opt-in. 아래 2번 섹션 참고. |
2. Conversation 스크롤 엔진 교체 (1.1)
Conversation이 use-stick-to-bottom 의존성을 제거하고 자체 스크롤 엔진으로 교체됐습니다. 하단 팔로우, 턴 앵커링, prepend 위치 보존을 내장합니다. Conversation/ConversationContent/ConversationScrollButton 조합 API는 그대로지만, ConversationProps가 StickToBottom props에서 자체 props로 바뀌었 습니다. initial/resize prop을 쓰던 코드는 제거하고, 필요하면 autoScroll/scrollEdgeThreshold/scrollPreviousItemPeek/scrollMargin으로 대체합니다. 턴 앵커링을 쓰려면 각 메시지를 ConversationMessage로 감싸고 user 턴에 scrollAnchor를 지정합니다 (선택 사항).
// Before — StickToBottom props (initial / resize)
<Conversation initial="smooth" resize="smooth">
<ConversationContent>
{messages.map((msg) => (
<Message key={msg.id} from={msg.role}>...</Message>
))}
</ConversationContent>
</Conversation>
// After — 자체 엔진 props + 턴 앵커링
<Conversation autoScroll scrollPreviousItemPeek={64}>
<ConversationContent>
{messages.map((msg) => (
// user 턴을 앵커로 지정하면 전송 시 상단에 정착
<ConversationMessage
key={msg.id}
messageId={msg.id}
scrollAnchor={msg.role === "user"}
>
<Message from={msg.role}>...</Message>
</ConversationMessage>
))}
</ConversationContent>
<ConversationScrollButton />
</Conversation>3. styles.css 임포트
opt-ui와 함께 사용하지 않는 컨슈머는 시머 keyframe과 collapsible 트랜지션을 위해 styles.css를 명시적으로 import해야 합니다. opt-ui 글로벌 CSS와 동일한 정의가 들어 있습니다.
// app/layout.tsx (또는 globals.css)
import "@reopt-ai/opt-chat/styles.css";4. MessageBranch API 변경
children에서 자식을 자동 추적하던 패턴을 branches prop으로 명시화했습니다. children API는 호환 shim으로 유지되지만 deprecated이며, dev 환경에서 한 번 경고를 출력합니다.
// Before (0.1) — children 자동 감지 (deprecated)
<MessageBranch totalBranches={messages.length}>
<MessageBranchContent>
{messages.map((m) => <MessageBubble key={m.id}>{m.text}</MessageBubble>)}
</MessageBranchContent>
<MessageBranchSelector />
</MessageBranch>
// After (0.2) — branches prop으로 명시
<MessageBranch> {/* totalBranches 자동 감지 */}
<MessageBranchContent
branches={messages.map((m) => (
<MessageBubble key={m.id}>{m.text}</MessageBubble>
))}
/>
<MessageBranchSelector />
</MessageBranch>5. flow subpath (xyflow)
에이전트 그래프 시각화는 @reopt-ai/opt-chat/flow 별도 subpath로 분리되어 메인 번들 사이즈에 영향을 주지 않습니다. @xyflow/react는 optional peer로, 사용할 때만 설치하면 됩니다.
// 에이전트 그래프가 필요한 페이지에서만
import { Canvas, Node, Edge, Controls } from "@reopt-ai/opt-chat/flow";
// peer 의존성 설치
// bun add @xyflow/react6. 내부 primitive 통합
Tool / Reasoning / ChainOfThought / Plan / Sources / Agent / Queue 등 기존 collapsible 컴포넌트들이 모두 단일 Collapsible primitive 위에서 동작하도록 마이그레이션됐습니다. 외부 API는 호환되며 내부 코드 중복이 제거되었습니다. OpenIn / MicSelector는 @reopt-ai/opt-ui-primitives의 PopoverRoot를 사용하여 floating-ui 기반 위치 계산, outside click, Escape 처리를 자동으로 받습니다.
7. i18n 라벨 추가
신규 컴포넌트 8개 (Task, Commit, PackageInfo, Sandbox, WebPreview, OpenIn, MicSelector, JSXPreview)에 labels prop이 추가 되었습니다. 한국어 기본값은 그대로 유지하되 영어/다국어 컨슈머가 라벨을 override 가능합니다.