[Next.js] Markdown파일로 post 업데이트 하기

gigi·2023년 9월 14일
0

next 버전은 13입니다.

MDXRemote

next-mdx-remote를 활용하여 markdown 파일을 HTML 코드로 변환해준다.

npm install next-mdx-remote
npm install gray-matter

위의 두개를 설치해주고

먼저, 동적라우팅으로 post 별로 페이지를 렌더링할 수 있도록
app/post/[id]/page.tsx 경로로 폴더와 파일을 만들어주자.

// app/post/[id]/page.tsx

export default function Page({ params }) {
  return <div>My Post</div>;
}

Route Example URL params

app/blog/[id]/page.js	

/blog/1 => { id: '1' }
/blog/2 => { id: '2' }
/blog/3 => { id: '3' }

http://localhost:3000/post/1 로 접속할 경우
params의 id 값은 1

http://localhost:3000/post/2 의 경우
id값은 2가 된다.

--


gray-matter를 사용하면 md파일의 내용을 데이터로 쉽게 변환이 가능하다.


// md파일
---
title: 글제목
date: 2023-09-12
tag: ["md", "gray-matter"]
---
(블로그 글 내용) 




// gray-matter 사용시 데이터
{
  content: '글내용',
  data: { 
    title: '글제목', 
    date: '2023-09-12' 
    tag: '["md", "gray-matter"]' 
  }
}

generateStaticParams

여기서 SSG를 구현하기 위해서는 예전 getStaticPaths 함수 같은 게 필요한데

getStaticPaths처럼 서버사이드 라우팅의 모든 경우의 수를 지정할 필요가 있다.

Next.js 13 버전에서는 generateStaticParams 함수를 사용하면 된다.


위의 내용들을 바탕으로 app/post/[id]/page.tsx를 다시 한번 정리해주면 다음과 같다.

// app/post/[id]/page.tsx

import fs from "fs";
import path from "path";
import matter from "gray-matter";

import { MDXRemote } from "next-mdx-remote/rsc";

// fs모듈을 이용해 최상위 디렉토리의 posts폴더 파일들을 불러와 블로그 경로의 경우를 지정한다.

export async function generateStaticParams() {
  const files = fs.readdirSync(path.join("posts"));

  const paths = files.map((filename) => ({
    id: filename.replace(".mdx", ""),
  }));

  return paths;
}


// params로 받은 post id를 전달하고 md파일내용을 gray-matter로 데이터로 바꾼다
function getPost({ id }: { id: string }) {
  const markdownFile = fs.readFileSync(
    path.join("posts", decodeURIComponent(id) + ".mdx"),
    "utf-8"
  );

  const { data: frontMatter, content } = matter(markdownFile);

  return {
    frontMatter,
    id,
    content,
  };
}

export default function Post({ params }: any) {
  const props = getPost(params);

  return (
    <>
      <head>
        <title>{props.frontMatter.title}</title>
        <meta name="description" content={props.frontMatter.description} />
        <meta name="keyword" content="page keyword" />
      </head>
      <article style={{ color: "#e1e1e1", padding: "20px 0" }}>
        <h1>{props.frontMatter.title}</h1>
        <MDXRemote source={props.content} />
      </article>
    </>
  );
}

폴더경로

0개의 댓글