Next.js 에서 Markdown 파일 렌더링하기
현재 블로그를 만드는데 Next.js 를 구조를 잡고 포스트는 Markdown 파일로 작성하고 있다. 이 때 Next.js 를 이용해 Markdown 파일을 렌더링하는 방법을 정리해봤다.
목차
Markdown 렌더링
Markdown 파일을 Next.js 앱에서 렌더링 하는 방법은 Next.js 공식 문서 에서도 소개하고 있다.
MDX
해당 문서에서는 MDX 를 사용하는데, Markdown 에서 JSX 를 사용할 수 있도록 확장한 것일 뿐이므로 걱정할 필요 없다.
JSX 를 쓸 때 *.js|.ts 파일의 확장자 뒤에 x 만 추가로 붙이는 것처럼, *.md 파일 뒤에 x 만 붙여 *.mdx 파일로 만들어주면 된다.
*.mdx 파일로 만들면 Markdown 안에서 JSX 를 사용할 수 있기 때문에 더 다양한 기능을 사용할 수 있다.
설정
먼저 필요한 라이브러리를 설치한다.
yarn add @next/mdx @mdx-js/loader @mdx-js/react @types/mdx
# 혹은
npm install @next/mdx @mdx-js/loader @mdx-js/react @types/mdx그리고 app/ 디렉토리와 동일한 위치에 mdx-components.tsx 파일을 생성해 다음과 같은 코드를 작성한다.
이 useMDXComponents 를 이용해 Markdown 컴포넌트를 어떻게 렌더링할 지 설정할 수 있는데, 조금 뒤에 설명하겠다.
import type { MDXComponents } from 'mdx/types'
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...components,
}
}그리고 next.config.mjs 파일을 열어 다음과 같이 설정한다.
import withMDX from "@next/mdx";
// ...
/** @type {import('next').NextConfig} */
const nextConfig = {
// ...
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
};
export default withMDX()(nextConfig);pageExtensions 은 Next.js 에서 렌더링할 파일의 확장자를 설정하는데, 여기에 mdx 를 추가해주자.
그리고 withMDX 를 이용해 MDX 를 사용할 수 있도록 설정해주었다.
이렇게 설정하면 app/페이지/경로/page.mdx 파일을 Next.js 가 렌더링 해서 /페이지/경로 에 해당하는 페이지를 만들어준다.
일반적인 page.tsx 파일과 같은 방식으로 사용할 수 있다.
플러그인
JS 라이브러리 중에는 Markdown 렌더링을 도와주는 라이브러리가 많이 있다.
그 중 대표적인 라이브러리로는 remark 와 rehype 가 있다.
remark 는 Markdown 을 HTML 로 파싱하고 rehype 는 파싱된 HTML 을 변환하는데 사용된다.
두 라이브러리는 플러그인을 추가해 기능을 확장시킬 수 있다.
사용법
예를 들어 사용할 플러그인이 remark-frontmatter 라고 가정하자.
그럼 먼저 라이브러리를 설치해주자.
yarn add remark-frontmatter
# 혹은
npm install remark-frontmatter그리고 config 파일을 열어 다음과 같이 설정해주자.
import remarkFrontmatter from "remark-frontmatter";
// ...
export default withMDX({
remarkPlugins: [remarkFrontmatter],
})(nextConfig);이렇게 간단하게 플러그인을 추가할 수 있다!
rehype 도 마찬가지로 rehypePlugins 를 이용해 플러그인을 추가할 수 있다.
추가로 옵션을 설정해야 하는 경우에는 배열로 넘겨주면 된다.
예를 들어 remark-mdx-frontmatter 라는 플러그인을 설정할 때 name: "metadata" 라는 옵션을 주는 경우 다음과 같이 설정할 수 있다.
import remarkMdxFrontmatter from "remark-mdx-frontmatter";
// ...
export default withMDX({
remarkPlugins: [
remarkFrontmatter,
[remarkMdxFrontmatter, { name: "metadata" }],
],
})(nextConfig);내가 사용하는 플러그인
내가 사용한 플러그인의 목록과 간단한 설명을 정리해봤다.
remark-frontmatter
remark-frontmatter는 Markdown 파일의 frontmatter 를 파싱해주는 플러그인이다.
frontmatter 는 Markdown 파일의 맨 위에 --- 로 감싸진 YAML 형식의 메타데이터를 말한다.
Next.js 기본 설정에서는 frontmatter 를 파싱하지 않기 때문에 만약 frontmatter 가 작성된 문서가 하나라도 있다면 이 플러그인을 꼭 사용해야 한다.
remark-mdx-frontmatter
remark-mdx-frontmatter은 상기한 remark-frontmatter 와 함께 사용하는 플러그인이다.
remark-frontmatter 가 파싱해준 frontmatter 를 MDX 문서에서 내보낼 때 사용된다.
위에서 예시로 들었던 것처럼 name 옵션을 이용해 frontmatter 를 어떤 이름으로 내보낼 지 설정할 수 있다.
예시처럼 "metadata" 로 설정하면 export const metadata = { ... } 와 같은 형태로 내보내진다.
이를 Next.js 가 metadata 로 사용할 수 있기 때문에 매우 편리하다.
remark-toc
remark-toc는 목차를 반자동으로 생성해주는 플러그인이다.
Markdown 파일에 ## Contents 와 같은 제목을 추가하면 해당 제목 아래에 목차가 자동으로 생성된다.
heading 옵션에서 목차로 사용할 제목의 정규식을 설정할 수 있고 기본값은 "(table[ -]of[ -])?contents?|toc" 이다.
나는 기본값에 "목차" 를 추가한 "(table[ -]of[ -])?contents?|toc|목차" 로 설정했다.
remark-math
remark-math는 Markdown 파일에서 TeX를 파싱해주는 플러그인이다.
$$ 로 감싸진 TeX 코드를 파싱해주는데, rehype-katex 와 함께 사용하면 수식을 렌더링할 수 있다.
rehype-katex
rehype-katex 는 KaTeX 를 이용해 TeX 수식을 렌더링해주는 플러그인이다.
remark-math 와 함께 사용해야한다.
KaTeX 보다 MathJax 가 더 좋다면 rehype-mathjax 를 사용하면 된다.
rehype-pretty-code
rehype-pretty-code 는 코드 블럭을 예쁘게 만들어주는 플러그인이다.
공식 문서에도 나와 있듯이 shiki 라는 라이브러리를 사용하기 때문에 같이 설치해줘야한다.
단순한 코드 하이라이팅 뿐만이 아니라 다양한 기능을 지원하니 공식 문서를 꼭 읽어보자.
rehype-slug
rehype-slug 는 제목마다 id 값을 자동으로 추가해준다.
제목마다 id 값이 추가되므로 URL 프라그먼트 식별자를 사용해 문서의 제목으로 바로 이동할 수 있는 링크를 만들 수 있다.
rehype-autolink-headings
rehype-autolink-headings 는 제목마다 자동으로 앵커를 추가해준다.
제목을 클릭하면 URL 프라그먼트 식별자로 바로 이동할 수 있고 제목에서 링크를 복사해 해당 제목으로 바로 이동할 수 있는 링크를 가져올 수 있다.
마무리
Next.js 에서 Markdown 파일을 렌더링하는 방법을 정리해봤다. 추후에 다른 플러그인을 사용하게 되면 추가해 놓겠다.