MdBin 레벨업: Custom Markdown 파이프라인에서 Streamdown으로

발행: (2026년 1월 17일 오후 12:08 GMT+9)
11 min read
원문: Dev.to

Source: Dev.to

위 링크에 포함된 본문을 번역하려면 해당 텍스트를 제공해 주세요. 텍스트를 주시면 요청하신 대로 한국어로 번역해 드리겠습니다.

Source:

기존 설정: 작동했지만

내 원래 구현은 견고했습니다. 구문 강조를 위해 markdown-it-async@shikijs/markdown-it을 사용했습니다:

import { fromAsyncCodeToHtml } from '@shikijs/markdown-it/async'
import MarkdownItAsync from 'markdown-it-async'
import { codeToHtml } from 'shiki'

const md = MarkdownItAsync({
  html: true,
  xhtmlOut: true,
  linkify: true,
  typographer: true,
  breaks: true,
})

md.use(
  fromAsyncCodeToHtml(codeToHtml, {
    themes: {
      light: 'github-light',
      dark: 'github-dark',
    },
    defaultColor: false,
    cssVariablePrefix: '--shiki-',
  })
)

export async function renderMarkdown(content: string): Promise {
  const html = await md.renderAsync(content)
  return html
}

그 다음 페이지 컴포넌트에서 클래식한 dangerouslySetInnerHTML을 사용해 결과를 렌더링했습니다:

단점

  • 수동 보안 처리dangerouslySetInnerHTML은 이름 그대로 위험합니다.
  • 내장된 제어 기능 부재 — 복사 버튼, 다운로드 기능 등을 직접 구현해야 했습니다.
  • Mermaid는 악몽 — SSR 렌더링이 신뢰성 있게 동작하지 않았습니다.
  • 번들 크기 증가 — 언어마다 하이라이트를 추가할수록 무게가 늘어났습니다.
  • 불완전한 블록 처리 — 형식이 잘못된 마크다운이 전체 렌더링을 깨뜨릴 수 있었습니다.

Streamdown 소개

제가 Streamdown을 발견했을 때, 처음엔 무시했습니다. “AI 스트리밍용이겠지”라고 생각했죠. “MdBin은 정적 콘텐츠를 SSR로 렌더링한다.”

하지만 기능 세트를 자세히 살펴보니:

  • 🎯 코드 구문 강조 with Shiki (이미 사용하고 있던 것)
  • 📈 Mermaid 다이어그램 that actually work SSR
  • 🛡️ 보안‑우선 with rehype-harden
  • 📊 GitHub‑스타일 마크다운 out of the box
  • 🔢 수학 렌더링 via KaTeX
  • 복사, 다운로드, 전체 화면을 위한 built‑in controls

바로 이것이 마크다운‑공유 도구에 필요한 전부입니다.

마이그레이션: 놀라울 정도로 간단함

새 구현이 어떻게 생겼는지 보세요:

import { Streamdown } from 'streamdown'

export default async function PastePage({ params }) {
  const { id } = await params
  const { decompressedContent, createdAt } = await cachedGetPaste(id)

  return (
    <Streamdown mode="static">
      {decompressedContent}
    </Streamdown>
  )
}

그게 전부입니다. 별도의 렌더 함수도 없고, dangerouslySetInnerHTML도 없으며, 수동 보안 정화도 필요 없습니다.

Tailwind 설정은 globals.css에 한 줄만 추가하면 됩니다:

@source "../../node_modules/streamdown/dist/index.js";

왜 v2.0.0이 게임 체인저인가

타이밍이 이보다 좋을 수 없었습니다. Streamdown이 방금 v2.0.0을 출시했으며 대규모 개선이 포함되었습니다:

🚀 CDN을 통한 98 % 번들 크기 감소

이전에는 모든 Shiki 언어 문법과 테마를 번들링하면서 빌드가 부풀어졌습니다. 이제 언어별 하이라이팅과 KaTeX CSS가 CDN에서 필요할 때마다 로드됩니다. 빌드는 가볍게 유지되고, 사용자는 필요한 것만 가져갑니다.

📈 Mermaid SSR이 실제로 작동합니다

마크다운의 Mermaid 다이어그램은 흐름도, 시퀀스 다이어그램, 아키텍처 문서 등 매우 유용합니다—하지만 SSR 렌더링이 깨져 있었습니다. 이제는 아름답게 작동하며, 뷰포트 기반 지연 로딩을 통해 다이어그램이 여러 개 있을 때 페이지가 멈추는 것을 방지합니다.

🛡️ 강화된 보안

rehype-harden + rehype-sanitize 덕분에 악성 마크다운으로 인한 XSS 공격을 걱정할 필요가 없습니다. 컴포넌트가 자동으로 정화를 처리합니다.

✨ 내장된 UX 다듬기

직접 구현해야 했던 모든 컨트롤? 이제 내장되었습니다:

  • 코드 블록 – 복사 버튼, 언어 표시
  • – CSV로 다운로드
  • Mermaid – PNG로 다운로드, SVG 복사, 팬/줌이 가능한 전체 화면 보기

내가 얻은 것

기능
보안dangerouslySetInnerHTML 사용 수동내장 rehype-harden
코드 복사맞춤 CopyButton 컴포넌트✅ 내장
Mermaid SSR❌ 깨짐✅ 작동
표 다운로드❌ 구현되지 않음✅ 내장
수식 렌더링❌ 구현되지 않음✅ KaTeX 내장
번들 크기언어마다 증가필요 시 CDN 로드
불완전한 마크다운렌더링을 깨뜨릴 수 있음우아한 처리

“스트리밍” 부분

당신은 “정적 콘텐츠에 스트리밍 최적화 컴포넌트를 왜 사용하나요?” 라고 궁금할 수 있습니다. 답은 간단합니다—Streamdown의 스트리밍 모드는 점진적인 렌더링을 제공하기 때문입니다. 마크다운이 파싱되어 도착하는 대로 DOM에 스트리밍되므로 다음과 같은 이점이 있습니다:

  • 첫 번째 의미 있는 콘텐츠가 표시되는 시간(Time‑to‑First‑Contentful‑Paint)이 빨라집니다(특히 큰 포스트의 경우).
  • 무거운 다이어그램이나 코드 블록이 처리되는 동안 UI가 계속 반응합니다.
  • 정적 SSR과 실시간 AI‑생성 스트림 모두에 동일하게 적용되어 향후 기능에 대한 유연성을 제공합니다.

요약하면, 더 깔끔한 코드베이스, 향상된 보안, 현저히 작은 번들, 그리고 풍부한 사용자 경험을 거의 마이그레이션 노력 없이 얻을 수 있었습니다.

MdBin 레벨업 커버 이미지: 커스텀 마크다운 파이프라인에서 Streamdown으로

“정적 콘텐츠용 ed 라이브러리?”

공정한 질문입니다. mode="streaming"isAnimating={false} 프롭은 Streamdown에게 이것이 사전 렌더링된 콘텐츠임을 알려줍니다—타이핑 효과도 없고, 점진적 표시도 없습니다. 하지만 다른 모든 이점은 그대로 적용됩니다:

  • parseIncompleteMarkdown – 사용자가 잘못된 마크다운(닫히지 않은 코드 블록, 불완전한 테이블 등)을 붙여넣을 때 발생하는 예외 상황을 처리합니다. 충돌하거나 잡다한 내용이 표시되는 대신, 부드럽게 렌더링됩니다.
  • 메모이제이션된 렌더링 – 스트리밍이 없더라도, 성능 최적화가 재렌더링 시 도움이 됩니다.

Vercel 팀에게 감사 인사

Streamdown 팀은 복잡하고 여러 라이브러리를 조합해야 할 상황을 하나의 잘 설계된 컴포넌트로 깔끔하게 패키징하는 놀라운 작업을 해냈습니다. 이 컴포넌트는 그들의 AI Elements Message 컴포넌트를 구동하지만, 마크다운 렌더링이 필요한 모든 경우에 실제로 유용합니다.

  • 문서가 탄탄합니다.
  • 기본값이 합리적입니다.
  • 그냥 바로 동작합니다.

직접 사용해 보기

위로 이동하여 마크다운을 붙여넣으세요. 시도해 보세요:

  • 코드 블록을 모든 언어로—복사 버튼과 언어 배지를 확인하세요.
  • Mermaid 다이어그램—이제 실제로 렌더링됩니다! 전체 화면 + 팬/줌을 시도해 보세요.
  • —다운로드 버튼을 확인하세요.
  • 수학 방정식—LaTeX가 바로 작동합니다.

붙여넣을 간단한 Mermaid 예시

graph TD
    A[Paste Markdown] --> B[Streamdown Renders]
    B --> C{What type?}
    C -->|Code| D[Shiki Highlighting]
    C -->|Diagram| E[Mermaid SVG]
    C -->|Math| F[KaTeX Render]
    D --> G[Beautiful Output]
    E --> G
    F --> G
  • 전체 화면 모드 진입
  • 전체 화면 모드 종료

다음 단계

렌더링 레이어가 이제 Streamdown으로 처리되면서, 사용자가 실제로 원하는 기능에 집중할 수 있게 되었습니다:

  • 만료 옵션 – 1시간, 1일, 1주 또는 영구.
  • 비밀번호 보호 – 민감한 콘텐츠용.
  • 편집 링크 – 새로 만들지 않고 기존 붙여넣기를 업데이트.
  • 맞춤 테마 – 라이트/다크 모드 외의 옵션.

기반은 견고합니다. 이제 구축할 차례입니다.

TL;DR: MdBin을 markdown-it + Shiki에서 Vercel의 Streamdown으로 마이그레이션했습니다. 내장 코드 복사, 실제 SSR에서 동작하는 Mermaid 렌더링, 수학 지원, 강화된 보안, 그리고 98 % 더 작은 번들 크기를 하나의 컴포넌트만으로 구현했습니다. Vercel 팀이 이 작업을 완벽히 해냈습니다.

업그레이드를 확인해 보세요 그리고 Streamdown repo.

Back to Blog

관련 글

더 보기 »

이 문서 인프라에 대하여

문서 구조 모든 문서는 GitHub 저장소의 ./documentation 디렉터리에 Markdown 파일로 저장됩니다. 이는 유일한 진실의 출처입니다.

첫 네 개

Raku Resolutions에 대한 후속 보고 https://dev.to/lizmat/raku-resolutions-17g7 첫 번째 회의는 제안된 시간과 날짜에 따라 진행되었습니다: 2026년 1월 17일 19:00 UT.

LuxDev Markdown 언어 클래스

마크다운 언어를 사용하여 작성하는 방법 헤더 - # 기호는 텍스트를 제목으로 만든다 두 개의 # 기호는 텍스트를 부제목으로 만든다 세 개의 # 기호는 텍스트를 하위 섹션으로 만든다.