framework/NextJS

๐Ÿ“˜ Next.js์—์„œ MDX ์‚ฌ์šฉ ๊ฐ€์ด๋“œ

octo54 2025. 5. 26. 10:40
๋ฐ˜์‘ํ˜•

๐Ÿ“˜ Next.js์—์„œ MDX ์‚ฌ์šฉ ๊ฐ€์ด๋“œ

MDX๋Š” Markdown๊ณผ JSX๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ์ •์ ์ธ ์ฝ˜ํ…์ธ ์™€ ๋™์ ์ธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ํฌ๋งท์ž…๋‹ˆ๋‹ค.
Next.js App Router์—์„œ๋„ ์‰ฝ๊ฒŒ MDX๋ฅผ ํ†ตํ•ฉํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โœ… 1. MDX๋ž€?

MDX(Markdown + JSX)๋Š” ์ผ๋ฐ˜์ ์ธ Markdown ํŒŒ์ผ ์•ˆ์— React ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง์ ‘ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์„œ ํฌ๋งท์ž…๋‹ˆ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค:

  • ๋ธ”๋กœ๊ทธ์—์„œ <VideoPlayer />, <CodeBlock /> ์‚ฝ์ž…
  • ๊ธฐ์ˆ ๋ฌธ์„œ์— <Tabs />, <Alert />์™€ ๊ฐ™์€ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ
  • Markdown ๊ธฐ๋ฐ˜ ํฌํŠธํด๋ฆฌ์˜ค ํŽ˜์ด์ง€ ๊ตฌ์ถ•

โœ… 2. ํŒจํ‚ค์ง€ ์„ค์น˜

๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด MDX ํ†ตํ•ฉ์— ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค:

npm install @next/mdx @mdx-js/loader @mdx-js/react

๋˜๋Š”

yarn add @next/mdx @mdx-js/loader @mdx-js/react

โœ… 3. next.config.js ์„ค์ •

MDX ํŒŒ์ผ์„ ํŽ˜์ด์ง€๋กœ ์ธ์‹ํ•˜๊ธฐ ์œ„ํ•ด next.config.js์— ์•„๋ž˜ ์„ค์ •์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

// next.config.js
const withMDX = require('@next/mdx')({
  extension: /\.mdx?$/,
});

module.exports = withMDX({
  pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
});

.mdx ํ™•์žฅ์ž๋ฅผ ํŽ˜์ด์ง€๋กœ ์ธ์‹ํ•˜๋ ค๋ฉด pageExtensions๋ฅผ ๋ฐ˜๋“œ์‹œ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


โœ… 4. MDX ํŒŒ์ผ ์ž‘์„ฑ ๋ฐ ์‚ฌ์šฉ

# ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค

Next.js์—์„œ๋Š” **MDX**๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<CustomButton>ํด๋ฆญํ•˜์„ธ์š”!</CustomButton>

ํ•ด๋‹น ํŒŒ์ผ์„ app/docs/page.mdx์— ์œ„์น˜์‹œ์ผœ ํŽ˜์ด์ง€์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ๋™์ ์œผ๋กœ importํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โœ… 5. ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ ์—ฐ๊ฒฐ

๋ฐ˜์‘ํ˜•

MDX ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// mdx-components.tsx
import CustomButton from './components/CustomButton';

export const components = {
  CustomButton,
};
// app/docs/page.tsx
'use client';
import { MDXProvider } from '@mdx-js/react';
import Content from './page.mdx';
import { components } from '../../mdx-components';

export default function DocsPage() {
  return (
    <MDXProvider components={components}>
      <Content />
    </MDXProvider>
  );
}

โœ… 6. next-mdx-remote๋ฅผ ํ†ตํ•œ ๋™์  ๋กœ๋”ฉ

์™ธ๋ถ€ CMS๋‚˜ ํŒŒ์ผ์‹œ์Šคํ…œ์—์„œ MDX ์ฝ˜ํ…์ธ ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋ ค๋ฉด next-mdx-remote๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค์น˜

npm install next-mdx-remote

์˜ˆ์‹œ

// app/blog/[slug]/page.tsx
import fs from 'fs';
import path from 'path';
import { serialize } from 'next-mdx-remote/serialize';
import { MDXRemote } from 'next-mdx-remote';
import { components } from '../../../mdx-components';

export async function generateStaticParams() {
  return [{ slug: 'hello' }];
}

export default async function BlogPage({ params }: { params: { slug: string } }) {
  const file = fs.readFileSync(path.join('content', `${params.slug}.mdx`), 'utf-8');
  const mdxSource = await serialize(file);
  return <MDXRemote {...mdxSource} components={components} />;
}

โœ… 7. ์ฝ”๋“œ ํ•˜์ด๋ผ์ดํŒ… ์ถ”๊ฐ€ (์˜ต์…˜)

์ฝ”๋“œ ๋ธ”๋ก ํ•˜์ด๋ผ์ดํŒ…์„ ์›ํ•œ๋‹ค๋ฉด rehype-highlight ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค์น˜

npm install rehype-highlight

์„ค์ •

const withMDX = require('@next/mdx')({
  extension: /\.mdx?$/,
  options: {
    rehypePlugins: [require('rehype-highlight')],
  },
});

โœ… 8. App Router์—์„œ MDX ์‚ฌ์šฉ ํŒ

ํ•ญ๋ชฉ ์„ค๋ช…

App Router ์ง€์› ์—ฌ๋ถ€ โœ… .mdx ํŽ˜์ด์ง€ ์ง์ ‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ <Content />๋Š” ๋ฐ˜๋“œ์‹œ 'use client' ์ƒ๋‹จ ์„ ์–ธ
๋ ˆ์ด์•„์›ƒ ๊ณต์œ  .mdx๋Š” ์ผ๋ฐ˜ tsx์™€ ๋™์ผํ•˜๊ฒŒ layout.tsx์™€ ์—ฐ๋™๋จ
์ปดํฌ๋„ŒํŠธ ๋งˆํฌ์—… ์ œํ•œ React ์ „์šฉ ๊ธฐ๋Šฅ (useState, useEffect)์€ .tsx์—์„œ๋งŒ

โœ… ์š”์•ฝ

๊ธฐ๋Šฅ ๋ฐฉ๋ฒ•

MDX ์‚ฌ์šฉ @next/mdx ์„ค์ • ๋ฐ .mdx ํŒŒ์ผ ์ƒ์„ฑ
์ปดํฌ๋„ŒํŠธ ์—ฐ๊ฒฐ @mdx-js/react์˜ MDXProvider ์‚ฌ์šฉ
์ฝ”๋“œ ํ•˜์ด๋ผ์ดํŒ… rehype-highlight ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์น˜ ๋ฐ ์ ์šฉ
์™ธ๋ถ€ ์ฝ˜ํ…์ธ  ๋ Œ๋”๋ง next-mdx-remote ํ™œ์šฉ (serialize, MDXRemote)
App Router ํ˜ธํ™˜ .mdx ํŽ˜์ด์ง€ ์ง์ ‘ ๋ผ์šฐํŒ… ๊ฐ€๋Šฅ

 

Next.js, MDX, Markdown, JSX, ์ •์  ํŽ˜์ด์ง€, ๋ธ”๋กœ๊ทธ, ๊ธฐ์ˆ ๋ฌธ์„œ, ์ปดํฌ๋„ŒํŠธ ์‚ฝ์ž…, next-mdx-remote, rehype-highlight, App Router, SEO ์ตœ์ ํ™”