원티드 프리온보딩 챌린지의 2차 과제로 아래와 같은 과제를 받았다.
💡 Next.js로 마크다운으로 작성한 블로그를 정적 페이지(SSG)로 작성해주세요.
우선 로컬에 있는 마크다운 파일을 불러와서 그걸 html로 잘 구워 삶아서 넣어줘야 했다. 로직만 생각하면 금방 할 수 있을거라고 생각했는데 front-matter
grey-matter
remark
remark-html
등 여러가지 라이브러리를 새롭게 사용하다보니 좀 헷갈렸다. 답답하게 나아가지 않는 부분들에 대해서는 아래의 블로그를 참고했다.
이번 과제를 하면서 왜 html로 변환한 파일을 또 string으로 변환해서 return 하는가?
왜 serializable한 데이터 타입을 넣으라는 에러가 뜨는가...?
하는 의문이 들었지만 과제 구현이 급급해 일단 넘어갔었다. 그런데 강의시간에 멘토님께서 준비된 강의자료로 의문을 풀어주셨다.
📍 마크다운을 HTML 파일로 바꾸는 코드
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";
import rehypeSanitize from "rehype-sanitize";
export const convertMarkdownToHtml = async (markdown: string) => {
const file = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeSanitize)
.use(rehypeStringify)
.process(markdown);
return String(file);
};
보면 file을 string으로 변환해서 return 하고 있다.
(다르게 html로 변환하는 방법도 있던데 일단 remark github의 readme를 참고했다)
📍 getStaticProps
export async function getPostDetail(id: string) {
const detailPath = path.join(postsDirectory, `${id}.md`);
const content = fs.readFileSync(detailPath, "utf-8");
const matterData = matter(content);
const htmlContent = await convertMarkdownToHtml(matterData.content);
return {
id,
htmlContent,
...matterData.data,
};
}
export async function getStaticProps({ params }: PathParams) {
const postData = await getPostDetail(params.id);
return {
props: {
postData,
},
};
}
getStaticProps
는 서버에서 실행되는 함수이다.
즉 HTTP 통신을 통해 postData라는 값을 가지고 서버로 가야한다. 따라서 직렬화 가능한 형태의 값만 return 해야 하는 것이다.
+) file을 그냥 return하면 이러한 에러를 볼 수 있다.
error - SerializableError: Error serializing `.postData.htmlContent` returned from `getStaticProps` in "/[id]".
Reason: `object` ("[object Object]") cannot be serialized as JSON. Please only return JSON serializable data types.
= serializable 한 데이터 타입을 넣어라~
서버에서 실행이 되기 때문에 당연히 console
이나 document
등의 객체도 호출할 수 없다.
나도 처음에 저기서 콘솔로그 찍어보고 읭 안나오네 했던거 안비밀......
이러한 메서드를 페이지 컴포넌트 내부에서만 호출이 가능한 이유도 리액트가 페이지가 렌더되기전에 필요로하는 모든 데이터를 가져야하기 때문이다.
SSR을 공부하면서 CSR과의 차이, 장점 이런것에 대해서 공부하고 정작 server side에서 rendering 된다는 것이 어떤 의미인지 정확하게 알아보려고 하지 않았던 것 같다. 강의를 들으면서 코드를 더 타고 타고 들어가서 더 깊이 알아보는게 공부가 많이 된다는 점을 깨닫고 있다.
build 하면 터미널에 다음과 같이 보인다.
잘 만들어졌다 😉
No Next.js version could be detected in your project. Make sure "next"
is installed in "dependencies" or "devDependencies" 라는 에러가 보인다.
들어가서 확인해보면 "next"
가 잘 install 되어있다.
있는데????있잖아!!!!!!
아니?????
vercel로 배포하는 법을 찾아보면 모두 다 너무 간단하고 쉽다고 적혀있는데 나는 몇 시간동안 문서와 구글을 헤맸다.
여러가지 글들을 찾아서 읽었고 나의 문제점을 찾을 수 있었다.
배포하고자 하는 클라이언트 코드가 최상위 루트가 아닌 client 같은 폴더 안에 있다면 Root Directory를 해당 디렉터리로 바꿔주는 정도만 해주시면 됩니다.
출처: https://mingeesuh.tistory.com/entry/NEXTjs-넥스트-JS를-배워보자-5편-배포하기-feat-Varcel
나는 하염없이 프로젝트 상위폴더를 배포하고 있었던 것....
Root Directory를 md-blog로 바꿔주고나니 바로 배포되었다.
배포 === 어려운 것, 에러가 많이 나는 것
이라고 인식하고 있어서 그런지 당연히 내 프로젝트의 코드나 package에 문제가 있다고 생각했다.
아무튼 vercel로 배포를 성공했다 🎉
참고자료
원티드 프리온보딩 챌린지 10월 Notion 강의 자료
https://hong-devbox.tistory.com/13