next 버전은 13입니다.
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>;
}
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"]'
}
}
여기서 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>
</>
);
}