본문으로 건너뛰기
채팅 · AI / message-with-sources

MessageWithSources

MessageBubble 확장 — 본문에 출처 인용·신뢰도 배지·토큰 메타·복사 버튼을 합친 RAG 응답 카드.
채팅 · AImessage-with-sourcesStatic specimenmessage with sources출처citationrag
01 · Specimen

먼저 보고, 그다음 계약을 읽습니다

MessageBubble 확장 — 본문에 출처 인용·신뢰도 배지·토큰 메타·복사 버튼을 합친 RAG 응답 카드.

Workbench 불러오는 중…
Component intent의도와 경계 읽기

MessageBubble(텍스트) 위에 신뢰 가능한 AI 응답에 필요한 네 가지를 얹는다: (1) sources <details> 인용 목록, (2) 우상단 confidence 배지(0..1 → red/amber/green band), (3) footer 의 토큰/비용 metabar, (4) 복사 버튼. Cortex RecallChat 의 details+copy+confidence 패턴을 SSOT 로 일반화한 것으로, override 가 아니라 composition 이다 — role/avatar/label 등 MessageBubbleProps 를 그대로 상속(onCopy 만 자체 시그니처로 교체). Streaming-aware: sources/tokens 가 아직 undefined 면 해당 영역이 아예 그려지지 않아 progressive disclosure 가 자연스럽다.

02 · Use

예제

SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.

01RAG 응답 (출처 + 신뢰도 + 토큰)tsxfragment
RAG 응답 (출처 + 신뢰도 + 토큰)
import { MessageWithSources } from "@axe/ui";<MessageWithSources  role="assistant"  confidence={0.82}  tokens={{ input: 1240, output: 320, cost: 0.0089 }}  sources={[    { id: "1", type: "doc", title: "2024 감사보고서", snippet: "매출 142억…", href: "/docs/audit", confidence: 0.9 },    { id: "2", type: "memory", title: "전분기 IC 메모", confidence: 0.6 },  ]}>  2024년 매출은 142억 원으로 전년 대비 18% 증가했습니다.</MessageWithSources>
02최소 (본문 + 복사만)tsxfragment
최소 (본문 + 복사만)
import { MessageWithSources } from "@axe/ui";<MessageWithSources role="assistant" copyText="요약 결과">  요약 결과</MessageWithSources>
03CSS-only 정적 (비-React)htmlfragment
CSS-only 정적 (비-React)
<div class="axe-message axe-message--assistant axe-message-with-sources">  <div class="axe-message__avatar" aria-hidden="true">A</div>  <div class="axe-message__body">    <div class="axe-message__content">      <div class="axe-message-with-sources__head">        <div class="axe-message-with-sources__body-text">2024년 매출은 142억 원…</div>        <div class="axe-message-with-sources__head-actions">          <span class="axe-message-with-sources__confidence axe-message-with-sources__confidence--high">82%</span>        </div>      </div>      <details class="axe-message-with-sources__sources">        <summary class="axe-message-with-sources__sources-summary">출처 1건</summary>        <ul class="axe-message-with-sources__sources-list">          <li class="axe-message-with-sources__source">            <span class="axe-message-with-sources__source-type">doc</span>            <a class="axe-message-with-sources__source-title" href="/docs/audit">2024 감사보고서</a>          </li>        </ul>      </details>    </div>  </div></div>
03 · React

Props

TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.

이름타입필수기본값설명
role"user" | "assistant" | "system"필수MessageBubble 상속 — 아바타/라벨/정렬 결정.
sourcesSourceItem[]인용 목록. undefined 또는 빈 배열이면 <details> 미렌더. SourceItem = { id, title, snippet?, href?, confidence?, type? }.
tokensTokenMeta토큰/비용 메타. footer 에 in·out·cost 로 표시. TokenMeta = { input?, output?, cost? }(cost=USD).
confidencenumber0..1. 우상단 배지로 표시. <0.5 low(red) · <0.8 med(amber) · ≥0.8 high(green).
onCopy(text: string) => void복사 콜백. 미지정 시 navigator.clipboard.writeText 로 fallback.
copyTextstring복사에 넘길 텍스트. 미지정 시 children 이 string 이면 그것, 아니면 빈 문자열.
defaultSourcesOpenbooleanfalsesources <details> 를 처음부터 펼칠지.
footerReact.ReactNode토큰 metabar 옆(또는 대신) 붙는 자유 footer — 예: action 버튼.
childrenReact.ReactNode본문. string 이면 copyText 기본값으로도 쓰인다.
avatar / label / showRoleMessageBubblePropsMessageBubble 상속 props 그대로 통과.
...restOmit<MessageBubbleProps, "onCopy">그 외 MessageBubble/HTMLAttributes 는 루트로 전파.
04 · Any stack

.axe-* 클래스 계약

React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.

클래스안정성용도
.axe-message-with-sourcesstable루트 modifier(axe-message 위). content 를 세로 flex 로 재배치.
.axe-message-with-sources__headstable본문 텍스트 + 우상단 액션(confidence/copy)을 나누는 상단 행.
.axe-message-with-sources__body-textstable본문 텍스트 영역(pre-wrap, break-word).
.axe-message-with-sources__head-actionsstable우상단 confidence 배지 + 복사 버튼 그룹.
.axe-message-with-sources__confidencestableconfidence 배지. --low/--med/--high 변형이 band 색(danger/warning/success-soft)을 결정.
.axe-message-with-sources__copystable복사 버튼(ghost, focus-visible ring).
.axe-message-with-sources__sourcesstable출처 <details> 컨테이너(상단 구분선).
.axe-message-with-sources__sources-summarystable<summary> '출처 N건' 토글(▸ 마커 회전).
.axe-message-with-sources__sources-liststable출처 항목 <ul>.
.axe-message-with-sources__sourcestable개별 출처 <li>(type|title|conf 3열 grid).
.axe-message-with-sources__source-typestable출처 분류 칩(doc/memory/web 등).
.axe-message-with-sources__source-titlestable출처 제목 — href 있으면 <a target=_blank>, 없으면 <span>.
.axe-message-with-sources__source-snippetstable출처 발췌문(italic, 전 열 span).
.axe-message-with-sources__source-confstable출처별 신뢰도 배지. --low/--med/--high band 색.
.axe-message-with-sources__footerstable토큰 metabar + 자유 footer 를 담는 하단 행(파선 구분).
.axe-message-with-sources__tokensstablein·out·cost 토큰 metabar(mono).
.axe-message-with-sources__tokenstable토큰 항목 하나(label + val).
.axe-message-with-sources__token-labelstable토큰 라벨(in/out/cost, uppercase muted).
.axe-message-with-sources__token-valstable토큰 값(axe-tabular-nums 로 자릿수 정렬).
비-React 소비 노트
대부분 CSS-only 로 재현 가능하다: 출처는 네이티브 <details>, confidence/source-conf band 는 --low/--med/--high 변형 클래스, 토큰 metabar 는 정적 마크업이면 충분하다. 다만 복사 버튼의 클립보드 쓰기·'복사됨' 토글·live region 고지는 JS 동작이므로 CSS-only 로는 정적 버튼만 남는다. 루트는 반드시 axe-message + axe-message--<role> 위에 axe-message-with-sources 를 함께 얹는다.
05 · Inclusive

접근성

키보드, ARIA, 구현 노트를 함께 검토합니다.

Keyboard
  • Enter / Space — sources <summary> 펼침/접힘(네이티브 <details>)
  • Enter / Space — 복사 버튼 실행(네이티브 <button>)
  • Tab — 출처 링크(<a>)로 순차 이동
ARIA

출처는 네이티브 <details>/<summary> 라 펼침 상태를 스스로 고지한다(수동 aria-expanded 불요). confidence 배지는 aria-label·title 로 'confidence NN%' 를 노출해 색 band 에만 의존하지 않는다. 복사 버튼은 aria-label="복사" 이며, 복사 완료 고지는 버튼과 분리된 별도 visually-hidden span(role="status" aria-live="polite")이 담당한다 — 버튼 자체에 aria-live 를 박으면 hover/focus 마다 잡음이 생기므로 의도적으로 분리했다.

Notes

출처 링크는 target="_blank" 에 rel="noopener noreferrer" 가 붙는다. sources/tokens 가 undefined 면 해당 영역이 렌더되지 않아, 스트리밍 도중 메타가 늦게 도착해도 레이아웃이 점진적으로 채워진다.

06 · Judgment

권장 · 지양

권장
  • children 이 문자열이면 copyText 를 생략해도 복사가 그 텍스트를 쓴다 — 노드면 copyText 를 명시한다.
  • confidence 는 모델의 self-reported certainty 를 넘겨 환각 방어 신호로 쓴다.
  • source.type 로 doc/memory/web 을 구분해 인용 출처의 성격을 드러낸다.
지양
  • children 이 ReactNode 인데 copyText 를 안 주면 복사가 빈 문자열이 된다 — 잊지 말 것.
  • onCopy 미지정 시 클립보드 fallback 은 브라우저 환경 전제 — SSR 단독 경로에서 복사 동작을 기대하지 말 것.
검색창을 열면 컴포넌트 인덱스를 불러옵니다.