MDX와 리액트
Using JSX in Markdown
Docusaurus has built-in support for MDX v1, which allows you to write JSX within your Markdown files and render them as React components.
While Docusaurus parses both .md and .mdx files using MDX, some of the syntaxes are treated slightly differently by third-party tools. For the most accurate parsing and better editor support, we recommend using the .mdx extension for files containing MDX syntax.
Check out the MDX docs to see what other fancy stuff you can do with 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>
This behavior is different from Docusaurus 1. See also Migrating from v1 to v2.
In addition, MDX is not 100% compatible with CommonMark. Use the MDX playground to ensure that your syntax is valid MDX.
컴포넌트 가져오기
다른 파일에서 정의한 자체 컴포넌트나 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 v2+ onward (Docusaurus v3+), lower-case tag names are always rendered as native html elements, and will not use any component mapping you provide.
This feature is powered by a wrapper provider. 리액트 페이지에서 마크다운을 가져오는 경우 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 v2 is using MDX v1, which has a lot of known cases where the content fails to be correctly parsed as Markdown. Use the MDX playground to ensure that your syntax is valid MDX.
Samples of parsing failures
A paragraph starting with a JSX tag will be seen entirely as a JSX string:
- Problem
- Workaround
<span style={{color: 'red'}}>Highlighted text</span> but afterwards _Markdown_ **doesn't work**
Highlighted text but afterwards Markdown doesn't work
Use JSX for the rest of the line, or prefix the line with some plain text:
<span style={{color: 'red'}}>Use JSX for the paragraph</span> to stop <i>worrying about</i> <b>Markdown</b>
​<span style={{color: 'red'}}>← This is a zero-width space</span> and afterwards <i>Markdown</i> <b>works</b>
Use JSX for the paragraph to stop worrying about Markdown
← This is a zero-width space and afterwards Markdown works
Markdown within a JSX tag never works:
- Problem
- Workaround
<span style={{color: 'red'}}>**Bold doesn't work**</span>
Use JSX within JSX tag, or move the Markdown to the outer layer:
<span style={{color: 'red'}}><b>Bold now works</b></span>
**<span style={{color: 'red'}}>Bold now works</span>**
Bold now works
Text immediately below a JSX tag will be seen as JSX text:
- Problem
- Workaround
<div style={{color: 'red'}}>
**Bold still doesn't work**
</div>
Bold still doesn't work
Add an empty new line:
<div style={{color: 'red'}}>
**Bold now works**
</div>
Bold now works
Markdown text indented by four spaces will be seen as a code block:
- Problem
- Workaround
<div style={{color: 'red'}}>
You may think I'm just some text...
</div>
You may think I'm just some text...
Don't indent:
<div style={{color: 'red'}}>
Now I'm actually just text
</div>
Now I'm actually just text
코드 조각 가져오기
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 변경이 있을 수 있습니다.
마크다운 가져오기
마크다운 파일을 컴포넌트로 사용하고 다른 마크다운 파일이나 리액트 페이지에서 가져올 수 있습니다.
관례적으로 파일 이름에 _ 접두사를 사용하면 문서 페이지를 생성하지 않으며, 다른 파일에서 가져와 사용하는 **"부분 파일"**임을 나타냅니다.
<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.
이렇게 하면 여러 페이지에서 콘텐츠를 재사용하고 자료의 중복을 피할 수 있습니다.
Currently, the table of contents does not contain the imported Markdown headings. This is a technical limitation that we are trying to solve (issue).
사용 가능한 내보내기 항목
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": "Using JSX in Markdown",
"id": "using-jsx-in-markdown",
"level": 2
},
{
"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와 리액트