MDX 컴포넌트 맵
신뢰할 수 있는 MDX를 Vite에서 컴파일하고 CommonMark와 GFM 출력을 Tinyrack React 컴포넌트 맵으로 렌더링해요.
신뢰 경계부터 정하기
애플리케이션과 함께 검토하고 Vite 빌드에서 컴파일하는 .mdx 파일에 이 연동을 사용하세요. MDX에는 JavaScript와 JSX가 들어갈 수 있으므로 애플리케이션과 같은 권한으로 실행돼요. 원격에서 가져오거나 사용자가 작성한 MDX를 이 설정에 전달하면 안 돼요. 신뢰할 수 없는 콘텐츠에는 실행 기능이 없는 Markdown 파이프라인과 명시적인 정화 정책을 사용하세요. 콘텐츠 출처를 정하기 전에 MDX 보안 안내를 확인하세요.
빌드 도구 설치하기
React 19, Vite, Tailwind CSS 4를 사용하는 애플리케이션에서 시작하세요. Tinyrack은 런타임 의존성으로 설치하고 컴파일러 플러그인은 개발 의존성으로 유지하세요.
pnpm add @tinyrack/ui react@^19 react-dom@^19
pnpm add -D @mdx-js/rollup @tailwindcss/vite @types/mdx @vitejs/plugin-react remark-gfm tailwindcss@^4 vite
Vite 설정하기
MDX 플러그인이 React 플러그인보다 먼저 .mdx를 변환하도록 pre 단계에서 실행하세요. React 플러그인에는 Markdown 확장자를 포함하고, 작업 목록·표·취소선·자동 링크·각주를 사용하려면 remark-gfm을 추가하세요. 컴파일된 컴포넌트에 맵을 직접 전달하므로 @mdx-js/react나 providerImportSource는 필요하지 않아요. 플러그인 순서는 MDX Vite 연동 안내에서 확인할 수 있어요.
import mdx from '@mdx-js/rollup';
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
import remarkGfm from 'remark-gfm';
export default defineConfig({
plugins: [
{
enforce: 'pre',
...mdx({ remarkPlugins: [remarkGfm] }),
},
react({ include: /\.(?:js|jsx|ts|tsx|md|mdx)$/ }),
tailwindcss(),
],
});
Tailwind 진입점을 먼저 불러오고 Tinyrack 코어, MDX, 컴포넌트 맵이 사용하는 컴포넌트 스타일을 이어서 불러오세요.
@import 'tailwindcss';
@import '@tinyrack/ui/core.css';
@import '@tinyrack/ui/mdx.css';
@import '@tinyrack/ui/components/code.css';
@import '@tinyrack/ui/components/code-block.css';
@import '@tinyrack/ui/components/link.css';
@import '@tinyrack/ui/components/table.css';
신뢰할 수 있는 MDX 렌더링하기
컴파일된 .mdx 파일을 불러오고 components 속성으로 tinyrackMdxComponents를 전달하세요. Content는 빌드할 때 만들어지는 React 컴포넌트이며 런타임 렌더러에 넘기는 HTML 문자열이 아니에요.
import Content from './content.mdx';
import { tinyrackMdxComponents } from '@tinyrack/ui/mdx';
import './app.css';
export function MdxArticle() {
return <Content components={tinyrackMdxComponents} />;
}
실제 MDX 파일 미리 보기
미리보기는 현재 언어에 맞는 실제 .mdx 파일을 불러와요. 이 샘플은 Tinyrack 맵이 지원하는 CommonMark와 GFM 요소를 모두 사용해요. 제목, 본문, 인라인 서식, 목록, 이미지, 인용문, 강제 줄바꿈, 수평선, 작업 목록, 표, 코드 블록, 각주를 한 화면에서 확인할 수 있어요.
컴파일된 MDX 출력 고유 링크
MDX 원본과 이 문서에서 사용하는 React 구성을 비교해 보세요.
페이지 랜드마크 선택하기
tinyrackMdxComponents의 기본 wrapper는 <main className="tr-mdx">을 렌더링해요. MDX 문서가 페이지의 주 콘텐츠를 맡을 때 이 기본값을 사용하세요. 애플리케이션에 이미 main 랜드마크가 있다면 새 맵을 만들고 wrapper를 article로 바꾸세요. 공유 본문 스타일이 유지되도록 tr-mdx 클래스는 남겨 두세요.
import type { ComponentPropsWithoutRef } from 'react';
import Content from './content.mdx';
import { createTinyrackMdxComponents } from '@tinyrack/ui/mdx';
import './app.css';
function ArticleWrapper({
children,
className,
...props
}: ComponentPropsWithoutRef<'article'>) {
return (
<article
{...props}
className={['tr-mdx', className].filter(Boolean).join(' ')}
>
{children}
</article>
);
}
const articleComponents = createTinyrackMdxComponents({
components: { wrapper: ArticleWrapper },
});
export function ProductPage() {
return (
<main>
<Content components={articleComponents} />
</main>
);
}
컴포넌트 맵 맞춤 설정하기
createTinyrackMdxComponents({ components })는 모든 기본 키를 담은 새 맵을 만든 뒤 전달받은 항목을 덮어써요. tinyrackMdxComponents를 변경하지 않고 제목, 링크, 래퍼와 다른 매핑 요소를 바꿀 때 사용하세요. 의미 있는 HTML, 전달받은 속성, 접근 가능한 이름, 교체 컴포넌트의 스타일 규약에 필요한 클래스를 유지하세요.
규약과 제한
| MDX 출력 | 기본 담당 | 주요 동작 |
|---|---|---|
| 문서 래퍼 | main.tr-mdx | 기존 main 안에서는 article.tr-mdx로 바꾸세요. |
| 인라인 코드와 코드 블록 | TRCode, TRCodeBlock | 코드 블록에는 Shiki 강조가 점진적으로 적용돼요. |
| 링크 | TRLink | 링크 의미와 목적지는 MDX에서 작성한 값을 유지해요. |
| 표 | TRTable.Root | 표 컨테이너 안에서만 가로로 스크롤해요. |
| 작업 목록 입력 | 네이티브 비활성 체크박스 | 작성된 체크 상태를 유지해요. |
| 그 밖의 본문 | 의미 있는 React 요소 | 제목, 목록, 인용문, 이미지, 각주에 공유 MDX 클래스가 적용돼요. |
이 연동은 런타임에 MDX를 가져오거나 격리하거나 컴파일하지 않아요. Next.js나 Astro 전용 설정도 다루지 않아요.
연동 확인하기
- Vite 프로덕션 빌드를 실행하고 불러온
.mdx모듈이 컴파일되는지 확인하세요. - 페이지의 주
main랜드마크가 하나인지 살펴보세요. 다른main이 이미 있다면article재정의를 사용하세요. - 작업 목록 체크박스가 비활성인지, 링크가 의도한 목적지로 이동하는지, 좁은 화면에서 표가 자체 컨테이너 안에서 스크롤하는지 확인하세요.
- 점진적인 코드 강조가 끝나기 전 상태까지 포함해 인라인 코드와 코드 블록을 밝은 테마와 어두운 테마에서 확인하세요.