메인 컨텐츠로 이동
버전: 2.0.1

MDX와 리액트

마크다운에서 JSX 사용하기

도큐사우루스는 MDX v1를 기본 지원합니다. MDX를 기반으로 마크다운 파일 내에 JSX를 작성해서 리액트 컴포넌트를 표현할 수 있습니다.

참고

도큐사우루스는 MDX를 사용해 .md, .mdx 파일을 모두 구문 분석하지만 일부 구문은 서드파티 도구에서 약간 다르게 처리됩니다. 좀 더 정확한 구문 해석과 에디터 지원을 위해 MDX 문법을 포함한 .mdx 파일 확장자를 사용하는 것을 권장합니다.

MDX 문서에서 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_와 같이 사용할 수 있습니다!

리액트 컴포넌트와 마크다운 문법이 어떻게 마크업 코드로 변환되는지 확인할 수 있습니다.

http://localhost:3000
도큐사우루스 초록 페이스북 파랑은 내가 좋아하는 색입니다.

마크다운JSX와 같이 사용할 수 있습니다!

MDX는 JSX입니다

모든 문서 파일은 MDX를 사용해 구문 분석되므로 HTML처럼 보이는 모든 것은 실제로는 JSX입니다. 그래서 컴포넌트를 인라인 스타일로 설정해야 하는 경우 JSX 형식을 따르며 style 오브젝트를 지정해주어야 합니다.

/* 이렇게 쓰지 말고: */
<span style="background-color: red">Foo</span>
/* 이렇게 쓰세요: */
<span style={{backgroundColor: 'red'}}>Foo</span>

이 부분은 도큐사우루스 1과 달라진 점입니다. 자세한 내용은 v1에서 v2로 이전하기를 참고하세요.

MDX는 CommonMark와 100% 호환을 보장하지는 않습니다. MDX playground에서 여러분이 사용하는 문법이 유효한 MDX 구문인지 확인해보세요.

컴포넌트 가져오기

다른 파일에 설정한 사용자 지정 컴포넌트나 npm으로 설치한 서드파티 컴포넌트를 가져올 수도 있습니다.

<!-- 도큐사우루스 테마 컴포넌트 -->
import TOCInline from '@theme/TOCInline';
<!-- 외부 컴포넌트 -->
import Button from '@mui/material/Button';
<!-- 사용자 지정 컴포넌트 -->
import BrowserWindow from '@site/src/components/BrowserWindow';

@site 별칭은 일반적으로 docusaurus.config.js 파일이 있는 웹사이트 디렉터리를 가리킵니다. 상대 경로('../../src/components/BrowserWindow') 대신 별칭을 사용하면 파일을 이동하거나 문서 버전을 관리하고 번역할 때 가져오기 경로를 업데이트하지 않아도 됩니다.

마크다운 내에서 컴포넌트를 선언하는 것은 간단한 경우에는 매우 편리하지만 편집기의 제한된 지원이나 구문 분석 오류 위험, 낮은 재사용성으로 인해 유지 관리가 어려워질 수 있습니다. 컴포넌트에 복잡한 JS 로직이 포함된 경우 별도의 .js 파일을 사용하세요.

src/components/Highlight.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>
);
}
markdown-file.mdx
import Highlight from '@site/src/components/Highlight';

<Highlight color="#25c2a0">도큐사우루스 초록</Highlight>

많은 파일에서 같은 컴포넌트를 사용하는 경우 모든 곳에서 가져올 필요는 없습니다. 전역 스코프에 추가하는 것이 좋습니다. 아래 내용을 참고하세요.

MDX 컴포넌트 스코프

컴포넌트 가져오기컴포넌트 내보내기 외에도 MDX에서 컴포넌트를 사용하는 세 번째 방법은 전역 스코프에 등록하는 것입니다. 그러면 import 구문을 사용하지 않고 모든 MDX 파일에서 자동으로 사용할 수 있습니다.

예를 들어 이런 MDX 파일이 주어진다면

- a
- list!

And some <Highlight>custom markup</Highlight>...

ul, li, p, Highlight 요소를 포함하는 리액트 컴포넌트로 컴파일됩니다. Highlight는 네이티브 HTML 요소가 아니므로 여러분이 리액트 컴포넌트를 구현해야 합니다.

도큐사우루스에서 MDX 컴포넌트 스코프는 @theme/MDXComponents 파일에 의해 제공됩니다. @theme/ 별칭으로 내보내는 대부분 다른 것들과 다르게 그 자체만 보면 리액트 컴포넌트가 아닙니다. 하지만 Highlight와 같은 태그 이름에서 사용자가 구현한 리액트 컴포넌트까지의 기록이라 할 수 있습니다.

컴포넌트를 스위즐링하면 구현된 모든 태그를 찾을 수 있으며 (마크다운 코드 블록을 렌더링하는 데 사용되는) @theme/MDXComponents/Code와 같은 각 하위 컴포넌트를 스위즐링해서 구현체를 추가적으로 커스터마이징할 수 있습니다.

추가적인 태그 이름(위에서 <Highlight> 태그와 같은)을 등록하려면 @theme/MDXComponents를 감싸는 것 형식으로 처리할 수 있으며 기존 매핑을 모두 유지할 필요는 없습니다. swizzle CLI는 컴포넌트가 아닌 파일을 감싸는 것을 허용하지 않으므로 수작업으로 래퍼를 생성해야 합니다.

src/theme/MDXComponents.js
import React from 'react';
// 원본 mapper 가져오기
import MDXComponents from '@theme-original/MDXComponents';
import Highlight from '@site/src/components/Highlight';

export default {
// 기본 mapping 재사용
...MDXComponents,
// "<Highlight>" 태그를 여러분이 만든 Highlight 컴포넌트에 매핑하세요.
// `Highlight`는 MDX에서 `<Highlight>`로 전달된 모든 속성을 수신합니다.
Highlight,
};

이제 import 구문을 사용하지 않고 모든 페이지에서 <Highlight>를 자유롭게 사용할 수 있습니다.

I can conveniently use <Highlight color="#25c2a0">Docusaurus green</Highlight> everywhere!
http://localhost:3000

I can conveniently use Docusaurus green everywhere!

warning

우리는 의도적으로 Highlight와 같은 대문자로 시작하는 태그 이름을 사용합니다.

MDX v2 이상(도큐사우루스 v3 이상)부터 소문자로 시작하는 태그 이름은 항상 기본 HTML 요소로 렌더링되며 사용자가 제공하는 컴포넌트 매핑이 적용되지 않습니다.

주의

이 기능은 wrapper provider에서 지원하는 기능입니다. 리액트 페이지에서 마크다운을 가져오는 경우 MDXContent 테마 컴포넌트를 통해 해당 provider를 직접 제공해주어야 합니다.

src/pages/index.js
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 상호 운용성

도큐사우루스 v2는 MDX v1을 사용하고 있는데 콘텐츠가 마크다운으로 적절하게 구문 분석되지 못하는 경우가 있습니다. MDX playground에서 여러분이 사용하는 문법이 유효한 MDX 구문인지 확인해보세요.

구문 분석 실패 예시

JSX 태그로 시작하는 단락은 완전히 JSX 문자열로 표시됩니다.

<span style={{color: 'red'}}>Highlighted text</span> but afterwards _Markdown_ **doesn't work**
http://localhost:3000
Highlighted text but afterwards _Markdown_ **doesn't work**

JSX 태그 내에서 마크다운은 작동하지 않습니다.

<span style={{color: 'red'}}>**Bold doesn't work**</span>
http://localhost:3000
**Bold doesn't work**

JSX 태그 바로 아래에 있는 텍스트는 JSX 텍스트로 표시됩니다.

<div style={{color: 'red'}}>
**Bold still doesn't work**
</div>
http://localhost:3000
**Bold still doesn't work**

4개의 공백문자로 들여쓴 마크다운 텍스트는 코드 블록으로 표시됩니다.

<div style={{color: 'red'}}>

You may think I'm just some text...

</div>
http://localhost:3000
You may think I'm just some text...

코드 스니펫 가져오기

Webpack raw-loader 덕분에 컴포넌트 정의가 포함된 파일을 가져올 수 있을 뿐 아니라 모든 코드 파일을 텍스트 형태로 가져와서 코드 블록에 삽입할 수 있습니다. raw-loader를 사용하기 위해서 먼저 여러분의 프로젝트에 설치해주어야 합니다.

npm install --save raw-loader

이제 아래와 같은 형태로 다른 파일에서 코드 스니펫을 가져올 수 있습니다.

myMarkdownFile.mdx
import CodeBlock from '@theme/CodeBlock';
import MyComponentSource from '!!raw-loader!./myComponent';

<CodeBlock language="jsx">{MyComponentSource}</CodeBlock>
http://localhost:3000
/**
* 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 React, {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>을 사용해야 합니다. 억음부호를 사용하면 그 내용을 그대로 보여주는데 우리는 가져온 텍스트를 여기에 삽입하기를 원하기 때문입니다.

warning

이 기능은 아직 실험중이며 향후 API 변경 사항이 적용될 수 있습니다.

마크다운 가져오기

마크다운 파일을 컴포넌트처럼 사용할 수 있습니다. 마크다운 파일 또는 리액트 페이지로 가져오기를 할 수 있습니다.

규칙에 따라 _ 파일명 접두사를 사용할 때 문서 페이지가 생성되지 않는다면 마크다운 파일이 다른 파일에서 가져온 "일부분"임을 의미합니다.

_markdown-partial-example.mdx
<span>Hello {props.name}</span>

This is text some content from `_markdown-partial-example.mdx`.
someOtherDoc.mdx
import PartialExample from './_markdown-partial-example.mdx';

<PartialExample name="Sebastien" />
http://localhost:3000
안녕하세요 Sebastien

_markdown-partial-example.md에서 가져온 텍스트입니다.

이렇게 하면 여러 페이지에서 콘텐츠를 재사용할 수 있으며 자료의 중복을 방지할 수 있습니다.

주의

현재는 가져온 마크다운 파일의 제목이 목차에 포함되지 않습니다. 기술적인 제약이며 해결하기 위해 노력하고 있습니다(관련 이슈를 참고하세요).

사용 가능한 내보내기 형식

MDX 페이지 내에서는 다음 변수를 전역으로 사용할 수 있습니다.

  • frontMatter: 문자열 키와 값으로 구성된 프런트 매터
  • toc: 트리 형태의 제목 목록인 목차. 좀 더 구체적인 사용 사례는 인라인 TOC을 참고하세요.
  • contentTitle: 마크다운 텍스트의 첫 번째 h1 제목. 항목이 없는 경우(예를 들어 프런트 매터에서 title 항목이 없는 경우) undefined로 처리됩니다.
import TOCInline from '@theme/TOCInline';
import CodeBlock from '@theme/CodeBlock';

The table of contents for this page, serialized:

<CodeBlock className="language-json">{JSON.stringify(toc, null, 2)}</CodeBlock>

The front matter of this page:

<ul>
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
</ul>

<p>The title of this page is: <b>{contentTitle}</b></p>
http://localhost:3000

The table of contents for this page, serialized:

[
{
"value": "마크다운에서 JSX 사용하기",
"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
}
]

The front matter of this page:

  • id: react
  • description: MDX를 사용해 도큐사우루스 마크다운 문서 내에서 리액트의 강력한 기능을 활용할 수 있습니다.
  • slug: /markdown-features/react

The title of this page is: MDX와 리액트