MDX와 리액트
도큐사우루스는 MDX를 기본 지원하므로 마크다운 파일 안에 JSX를 작성하고 리액트 컴포넌트로 렌더링할 수 있습니다.
MDX로 어떤 멋진 작업을 할 수 있는지 MDX 문서를 살펴보세요.
MDX 형식은 매우 엄격하여 컴파일 오류가 발생할 수 있습니다.
**MDX 플레이그라운드**를 사용해 디버깅하고 구문이 유효한지 확인하세요.
가장 널리 사용되는 포매터인 Prettier는 기존 MDX v1만 지원합니다. 의도하지 않은 서식 결과가 나오면 Prettier가 MDX v3를 제대로 지원할 때까지 문제가 있는 부분 앞에 {/* prettier-ignore */}를 추가하거나 .prettierignore에 *.mdx를 추가할 수 있습니다. MDX의 주요 개발자 중 한 명은 remark-cli와 remark-mdx를 함께 사용할 것을 권장합니다.
컴포넌트 내보내기
MDX 파일 안에서 사용자 정의 컴포넌트를 정의하려면 내보내야 합니다. export로 시작하는 문단만 일반 텍스트 대신 컴포넌트로 파싱됩니다.
export const Highlight = ({children, color}) => (
<span
style={{
backgroundColor: color,
borderRadius: '2px',
color: '#fff',
padding: '0.2rem',
}}>
{children}
</span>
);
<Highlight color="#25c2a0">도큐사우루스 초록색</Highlight>과 <Highlight color="#1877F2">페이스북 파란색</Highlight>은 제가 좋아하는 색입니다.
_JSX_와 함께 **마크다운**도 작성할 수 있습니다!
리액트 컴포넌트의 마크업과 마크다운 구문이 모두 렌더링되는 모습을 확인하세요:
_JSX_와 함께 마크다운도 작성할 수 있습니다!
모든 문서 파일은 MDX로 파싱되므로 HTML처럼 보이는 것도 실제로는 JSX입니다. 따라서 컴포넌트에 인라인 스타일을 지정하려면 JSX 방식에 따라 스타일 객체를 제공하세요.
/* 다음 코드 대신: */
<span style="background-color: red">Foo</span>
/* 이 코드를 사용하세요: */
<span style={{backgroundColor: 'red'}}>Foo</span>
컴포넌트 가져오기
다른 파일에서 정의한 자체 컴포넌트나 npm으로 설치한 외부 컴포넌트를 가져올 수도 있습니다.
<!-- 도큐사우루스 테마 컴포넌트 -->
import TOCInline from '@theme/TOCInline';
<!-- 외부 컴포넌트 -->
import Button from '@mui/material/Button';
<!-- 사용자 정의 컴포넌트 -->
import BrowserWindow from '@site/src/components/BrowserWindow';
단순한 경우에는 마크다운 안에서 컴포넌트를 선언하는 것이 매우 편리하지만, 편집기 지원이 제한적이고 파싱 오류의 위험이 있으며 재사용성이 낮아 유지보수가 어려워집니다. 컴포넌트에 복잡한 JS 로직이 포함된다면 별도의 .js 파일을 사용하세요:
import React from 'react';
export default function Highlight({children, color}) {
return (
<span
style={{
backgroundColor: color,
borderRadius: '2px',
color: '#fff',
padding: '0.2rem',
}}>
{children}
</span>
);
}
import Highlight from '@site/src/components/Highlight';
<Highlight color="#25c2a0">도큐사우루스 초록색</Highlight>
많은 파일에서 같은 컴포넌트를 사용한다면 모든 파일에서 가져올 필요 없이 전역 스코프에 추가하는 것을 고려해 보세요. 아래 내용 참고
MDX 컴포넌트 스코프
컴포넌트 가져오기와 컴포넌트 내보내기 외에 MDX에서 컴포넌트를 사용하는 세 번째 방법은 전역 스코프에 등록하는 것입니다. 이렇게 하면 가져오기 구문 없이도 모든 MDX 파일에서 자동으로 사용할 수 있습니다.
예를 들어 다음과 같은 MDX 파일이 있다고 가정해 보겠습니다:
- 목록
- 항목!
그리고 <Highlight>사용자 정의 마크업</Highlight>도...
이 파일은 ul, li, p, Highlight 요소가 포함된 리액트 컴포넌트로 컴파일됩니다. Highlight는 기본 HTML 요소가 아니므로 이에 해당하는 리액트 컴포넌트를 직접 구현해야 합니다.
도큐사우루스에서 MDX 컴포넌트 스코프는 @theme/MDXComponents 파일로 제공됩니다. @theme/ 별칭에서 내보내는 대부분의 항목과 달리, 이 파일은 그 자체로 리액트 컴포넌트가 아닙니다. Highlight 같은 태그 이름을 해당 리액트 컴포넌트 구현에 연결하는 레코드입니다.
이 컴포넌트를 스위즐링하면 구현된 모든 태그를 확인할 수 있습니다. @theme/MDXComponents/Code(마크다운 코드 블록을 렌더링하는 데 사용)처럼 해당 하위 컴포넌트를 스위즐링하여 구현을 추가로 수정할 수도 있습니다.
위의 \<Highlight> 태그처럼 태그 이름을 추가로 등록하려면 @theme/MDXComponents를 래핑하는 것을 고려하세요. 그러면 기존 매핑을 모두 유지보수할 필요가 없습니다. 스위즐링 CLI는 아직 컴포넌트가 아닌 파일의 래핑을 지원하지 않으므로 래퍼를 직접 만들어야 합니다:
import React from 'react';
// 원본 매퍼 가져오기
import MDXComponents from '@theme-original/MDXComponents';
import Highlight from '@site/src/components/Highlight';
export default {
// 기본 매핑 재사용
...MDXComponents,
// "<Highlight>" 태그를 Highlight 컴포넌트에 매핑
// `Highlight`는 MDX의 `<Highlight>`에 전달된 모든 props를 받습니다
Highlight,
};
이제 가져오기 구문 없이도 모든 페이지에서 \<Highlight>를 자유롭게 사용할 수 있습니다:
어디서나 <Highlight color="#25c2a0">도큐사우루스 초록색</Highlight>을 편리하게 사용할 수 있습니다!
어디서나 도큐사우루스 초록색을 편리하게 사용할 수 있습니다!
Highlight처럼 대문자로 시작하는 태그 이름을 의도적으로 사용합니다.
From MDX v3+ onward (Docusaurus v3+), lower-case tag names are always rendered as native html elements, and will not use any component mapping you provide.
이 기능은 MDXProvider를 기반으로 합니다. 리액트 페이지에서 마크다운을 가져오는 경우 MDXContent 테마 컴포넌트를 통해 이 프로바이더를 직접 제공해야 합니다.
import React from 'react';
import FeatureDisplay from './_featureDisplay.mdx';
import MDXContent from '@theme/MDXContent';
export default function LandingPage() {
return (
<div>
<MDXContent>
<FeatureDisplay />
</MDXContent>
</div>
);
}
가져온 MDX를 MDXContent로 감싸지 않으면 전역 스코프를 사용할 수 없습니다.
마크다운과 JSX 상호 운용성
Docusaurus v3 is using MDX v3.
MDX 구문은 대부분 CommonMark와 호환됩니다. 하지만 .mdx 파일에서 JSX를 사용할 수 있고 실제 리액트 컴포넌트로 컴파일되므로 훨씬 엄격합니다(플레이그라운드 참고).
일부 유효한 CommonMark 기능은 MDX에서 동작하지 않습니다(자세히 보기). 대표적인 예는 다음과 같습니다:
- 들여쓴 코드 블록: 대신 백틱 3개를 사용하세요
- 자동 링크(
\<http://localhost:3000>): 대신 일반 링크 구문([http://localhost:3000](http://localhost:3000))을 사용하세요 - HTML 구문(
\<p style="color: red;">): 대신 JSX(\<p style={{color: 'red'}}>)를 사용하세요 - 이스케이프하지 않은
{와\<: 대신 ``로 이스케이프하세요({와\<)
Docusaurus v3 makes it possible to opt-in for a less strict, standard CommonMark support with the following options:
mdx.format: md프런트 매터.md파일 확장자와siteConfig.markdown.format: "detect"설정의 조합
이 기능은 실험적이며 현재 몇 가지 제한사항이 있습니다.
코드 조각 가져오기
You can not only import a file containing a component definition, but also import any code file as raw text, and then insert it in a code block, thanks to Webpack raw-loader. In order to use raw-loader, you first need to install it in your project:
- npm
- Yarn
- pnpm
- Bun
npm install --save raw-loader
yarn add raw-loader
pnpm add raw-loader
bun add raw-loader
Now you can import code snippets from another file as it is:
import CodeBlock from '@theme/CodeBlock';
import MyComponentSource from '!!raw-loader!./myComponent';
<CodeBlock language="jsx">{MyComponentSource}</CodeBlock>
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {useState} from 'react';
export default function MyComponent() {
const [bool, setBool] = useState(false);
return (
<div>
<p>MyComponent rendered !</p>
<p>bool={bool ? 'true' : 'false'}</p>
<p>
<button onClick={() => setBool((b) => !b)}>toggle bool</button>
</p>
</div>
);
}
\<CodeBlock> 컴포넌트에 대한 자세한 내용은 JSX에서 코드 블록 사용하기를 참고하세요.
마크다운의 백틱 3개 ``` 대신 \<CodeBlock>을 사용해야 합니다. 백틱 안의 내용은 그대로 출력되지만, 여기서는 가져온 텍스트를 보간해야 하기 때문입니다.
이 기능은 실험적이며 향후 호환성을 깨뜨리는 API 변경이 있을 수 있습니다.
마크다운 가져오기
마크다운 파일을 컴포넌트로 사용하고 다른 마크다운 파일이나 리액트 페이지에서 가져올 수 있습니다. 각 MDX 파일은 페이지 콘텐츠를 리액트 컴포넌트로 기본 내보내기합니다. import 구문에서 이 컴포넌트를 원하는 이름으로 기본 가져오기할 수 있지만, 리액트 명명 규칙에 따라 대문자로 시작해야 합니다.
관례적으로 파일 이름에 _ 접두사를 사용하면 문서 페이지를 생성하지 않으며, 다른 파일에서 가져와 사용하는 **"부분 파일"**임을 나타냅니다.
<span>안녕하세요, {props.name}님</span>
이 텍스트는 `_markdown-partial-example.mdx`의 콘텐츠입니다.
import PartialExample from './_markdown-partial-example.mdx';
<PartialExample name="Sebastien" />
This is text some content from _markdown-partial-example.md.
이렇게 하면 여러 페이지에서 콘텐츠를 재사용하고 자료의 중복을 피할 수 있습니다.
사용 가능한 내보내기 항목
MDX 페이지 안에서는 다음 변수를 전역으로 사용할 수 있습니다:
frontMatter: 문자열 키와 값으로 이루어진 레코드 형태의 프런트 매터;toc: 제목 트리 형태의 목차입니다. 구체적인 사용 사례는 인라인 목차도 참고하세요.contentTitle: 마크다운 텍스트에서 첫 번째h1제목인 마크다운 제목입니다. 해당 제목이 없으면(예: 프런트 매터에서 제목 지정)undefined입니다.
import TOCInline from '@theme/TOCInline';
import CodeBlock from '@theme/CodeBlock';
이 페이지의 목차를 직렬화한 결과:
<CodeBlock className="language-json">{JSON.stringify(toc, null, 2)}</CodeBlock>
이 페이지의 프런트 매터:
<ul>
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
</ul>
<p>이 페이지의 제목: <b>{contentTitle}</b></p>
이 페이지의 목차를 직렬화한 결과:
[
{
"value": "컴포넌트 내보내기",
"id": "exporting-components",
"level": 3
},
{
"value": "컴포넌트 가져오기",
"id": "importing-components",
"level": 3
},
{
"value": "MDX 컴포넌트 스코프",
"id": "mdx-component-scope",
"level": 3
},
{
"value": "마크다운과 JSX 상호 운용성",
"id": "markdown-and-jsx-interoperability",
"level": 3
},
{
"value": "코드 조각 가져오기",
"id": "importing-code-snippets",
"level": 2
},
{
"value": "마크다운 가져오기",
"id": "importing-markdown",
"level": 2
},
{
"value": "사용 가능한 내보내기 항목",
"id": "available-exports",
"level": 2
}
]
이 페이지의 프런트 매터:
- id: react
- description: MDX를 사용해 도큐사우루스 마크다운 문서 내에서 리액트의 강력한 기능을 활용할 수 있습니다.
- slug: /markdown-features/react
이 페이지의 제목: MDX와 리액트