Next.js
의 Dynamic Routing은 react-router-dom
을 사용하지 않고도 아주 아주 손쉽게 라우팅을 프로젝트에 적용할 수 있다. src 디렉토리에서 page 폴더에 js 파일만 넣어놓으면 알아서 라우팅되기 때문에 next.js를 입문하는 뉴비 개발자들에게 가장 널리 알려진 기능이기도 하다.
하지만 Dynamic Routing만 이용하기 위해 Next.js
를 이용한다는 것은 Next.js
의 본질을 제대로 이해하지 못한 것이다.
Next.js
는 서버 사이드 랜더링을 구현하기 위함이지, 손쉽게 라우팅을 구현하기 위한 것이 아니다!
하여, 본 포스팅에서는 Next.js
의 주요한 기능인 getStaticProps와 getServerSideProps에 대해 다뤄보려고 한다.
아주 짧게 요약하면, 이 두 가지 기능을 사용하는 이유는 PreRendering을 적용하기 위함이다.
프리랜더링이란 SSR(ServerSideProps)
를 구현하는 Next.js의 가장 큰 특징이다. React로 구성된 웹/앱은 CSR(Client Side Rendering)
방식을 사용한다. CSR은 초기 랜더링 시 자바스크립트 파일을 모두 로드해오기 때문에, 초기 렌더링의 사용자 경험이 SSR에 비해 좋지 못하다.
때문에 사용자 반응이 중요하고, 검색엔진 최적화(search engine optimization, SEO)가 중요한 도메인에서는 서버 사이드 랜더링이 줄 수 있는 이점이 중요하다.
SSR은 미리 서버에서 HTML파일을 랜더링해 클라이언트로 전송해주기 때문에 초기랜더링 속도가 빠르다. 하지만 매번 서버에 요청을 보내서 화면을 받아오기 때문에, 화면 깜빡임이 많아지는 단점 또한 존재한다.
여기서, 프리 랜더링이 빛을 발휘하게 된다. Next.js는 필요한 화면만큼을 렌더링하고 나머지는 차차 자바스크립트 파일을 받아와 클라이언트 측에 랜더링을 맡기는 절충의 형태를 가지고 있다.
보다 쉽게 표현하자면, 처음에는 SSR을 나중에는 CSR 방식을 사용한다는 것이다. 문자 그대로 이해하자! 미리 랜더링하는 것!
Next.js는 프리랜더링을 위해 정적 생성 방식과 서버사이드 랜더링 방식을 제공하고, 각각의 경우에 따라 사용할 것을 권장하고 있다.
정적 생성 방식은 페이지의 콘텐츠가 외부 데이터에 연동될 때 사용할 수 있는데, 대략 마케팅 페이지, 블로그 포스트, E-커머스의 상품 페이지, term 같은 정적 텍스트가 주가 되는 페이지를 랜더링할때 유용하게 사용할 수 있다.
내 경우에는 프로젝트에서 "규정"과 관련된 텍스트들을 랜더링할때 사용할 수 있었다.
import Term from "src/constants/terms/Term";
import { Grid } from "@mui/material";
import { serialize } from "next-mdx-remote/serialize";
import { MDXRemote } from "next-mdx-remote";
const ServiceTerms = ({ source }) => ( // <--- 이 부분을 주목하시라
<Grid container direction="column" flexWrap="nowrap">
<Grid container direction="row">
<MDXRemote {...source} />
</Grid>
</Grid>
);
export async function getStaticProps() {
// MDX text - can be from a local file, database, anywhere
const source = serviceTerm;
const mdxSource = await serialize(source);
return { props: { source: mdxSource } };
}
export default ServiceTerms;
자주 바뀌지 않는 규정 텍스트 뭉치를 상수 폴더 안에서 보관하고 있었는데, 이에 대해 마크다운 문법까지 적용해 프리랜더링 하기 위해 Next.js의 공식문서에서 사용하기를 권장하고 있는 next-mdx-remote
라이브러리를 사용했다.
mdxSource
로 정의한 변수를 props의 벨류로 적용 후, 상단의 JSX 함수의 매개변수로 전달해주면 프리랜더링이 아주 간단하게 적용된다.
getStaticProps
함수는 params를 받아 그에 해당하는 경로(path)도 받아오는데, 캐싱까지 지원되기 때문에 페이지를 이동할 때 굉장히 빠른 렌더링 속도를 보여준다. 만일 데이터를 적용할 필요없이 단순히, path만 얻고 싶다면, getStaticPath
를 사용할 수 있다. 하지만 대게는, 경로 뿐만 아니라 이에 연동된 데이터까지 적용하기 때문에 주로 getStaticProps를 사용하게 될 것이다.
const SamplerPost ({ post}) => {
...
}
export async function getStaticPaths() {
const res = await fetch('https://.../posts');
const posts = await res.json();
// 원하는 post로 구성된 paths를 pre rendering할 수 있다.
const paths = posts.map((post) => ({
params: {id: post.id}
}));
// { fallback : false }는 이외 다른 경로를 404에러 처리한다는 것을 의미한다.
return { paths, fallback: false }
}
export async function getStaticProps({params}) {
const res = await fetch('https://.../popst/${params.id}');
const post = await res.json();
return { props: {post}}
}
export default SamplePost;