스트리밍

같은 답변을 같은 토큰으로 잘라 렌더러 다섯에 동시에 흘린다. 패널이 화면에 들어오면 시작한다. 눈여겨볼 것은 세 가지다 — 반쪽 마커(**굵, 여는 백틱)가 글자로 비쳤다 사라지는지, 조사 앞에서 끝나는 굵게(**설정(config)**을)가 끝까지 그려지는지, 강조나 표가 닫힐 때까지 멈춰 보이는지.

WASM 빌드를 불러오는 중…

DESIGN.md 는 에이전트가 쓴 한국어 문서 347건으로 이걸 쟀다(Streamdown 2.6.0, react-markdown 10.1.0 + remark-gfm). mdwire 스트리머를 Streamdown 앞에 두면 이미 보인 글이 바뀌는 횟수가 60%쯤 줄고 마커가 글자로 비치는 일이 사라졌다. 확정분만 보여 주는 mdwire html 스트리머에는 둘 다 없었다. 다만 확정분만 보여 주면 중간중간 멈춘다 — 이 샘플을 토큰 간격 60ms 로 흘리면 가장 긴 멈춤이 1,389ms, 미리보기를 켜면 302ms 였다. 미리보기가 기본인 이유다. 자세한 것은 DESIGN.md 의 브릿지 절. 샘플 답변은 합성이지만, 그 안의 모양은 모두 실제 에이전트 출력에서 깨졌던 것이다.

이 데모의 코드
import { Streamer } from "@minjun0219/mdwire";
import { useMarkdownStream } from "@minjun0219/mdwire/react";
import { Streamdown } from "streamdown";

// 브릿지 — 정규화는 mdwire, 그리기는 Streamdown
const s = new Streamer("github-markdown");
let done = "";
for (const token of tokens) {
  done += s.push(token);              // 확정분. 다시 고쳐지지 않는다
  setText(done + s.preview());        // + 붙든 것을 입력이 여기서 끝난 것처럼 그린 꼬리
}
done += s.finish();
setText(done);
// <Streamdown>{text}</Streamdown>

// 또는 React 에서 바로 그린다 — innerHTML 없이
const live = useMarkdownStream();                     // 붙든 것도 먼저 그린다(기본)
const settled = useMarkdownStream({ eager: false });  // 확정된 것만
// tokens → live.push(token) … live.finish();  render {live.elements}

전체 컴포넌트: site/src/components/StreamCompare.tsx. 같은 비교를 독립 Vite 앱으로, WASM 을 싣는 번들러 설정까지: examples/react-streaming.