드디어 Next.js를 학습하고자 했던 가장 중요한 이유 중 하나인 Pre-rendering 개념이 등장했다.
기본적으로 Next.js는 모든 페이지를 Pre-render하는데 이는 React에서 학습했던 CSR와 비교하자면 각 페이지에 대해서 미리 HTML을 만들어 사용자에게 전달하는 것을 의미한다.
React로 만들었던 서비스 Pre-rendering 테스트
크롬의 개발자도구를 켜고 Command+Shift+P (Mac) 누른 뒤 javascript을 입력 후 javascript를 disable 시킨 다음 사이트에 접속하면 다음과 같이 보이게 되는데 React는 클라이언트 측에서 js를 사용해서 화면을 보여주기 때문이다.
Pre-rendering vs No Pre-rendering
Next.js 에서는 2가지 형태의 Pre-Rendering을 사용한다.
SSG를 사용하더라도 data와 함께 사용이 가능하지만 최신 데이터임을 보장해줄 수는 없다. (옵션을 추가적으로 설정하여 해결할수도 있긴 하다)
const Home = ({posts}: PostsProps) => {
return (
<div>
<main>
<section>
<h2>Blog</h2>
<ul>
{posts && posts.map(({ id, userId, title, body }) => (
<Post key={id} userId={userId} title={title} body={body} />
))}
</ul>
</section>
</main>
</div>
)
}
export default Home;
export async function getStaticProps() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const allPostsData = await res.json();
return {
props: {
posts: allPostsData
}
}
}
개발모드 (npm run dev)에서는 SSG를 사용한 페이지여도 리퀘스트가 일어날 때 마다 생성한다고 한다.
해당 코드를 빌드해보면 다음과 같이 미리 HTML을 만들어 놓은 것을 볼 수 있다.
리퀘스트 시점마다 데이터를 fetch하기 위해서는 getServerSideProps
을 사용하면 된다.
위에서 사용했던 jsonPlaceholder api를 사용하여 테스트를 해보았다.
interface Props {
postData: PostProps;
}
function PostDetail({ postData }: Props) {
const { userId, title, body } = postData;
return (
<ul>
<Post userId={userId} title={title} body={body} />
</ul>
);
}
export default PostDetail;
export const getServerSideProps: GetServerSideProps = async (context) => {
const { id } = context.query;
const res = await fetch(`${JSONPLACEHOLDER_URL}/posts/${id}`);
const postData = await res.json();
if (res.status === STATUS_CODES.NOT_FOUND) {
return {
redirect: {
permanent: false,
destination: '/',
},
};
}
return {
props: {
postData,
},
};
};
여기서 context에서 반환되는 값이 어떤 것인지 궁금했는데 여러 키를 가지고 있는 객체라고 한다.
하나를 예시로 들면 이전의 포스트에서 다이나믹 라우팅을 위해 /pages/post/[id].tsx
를 생성했다면 params key 값에 라우터 파라미터가 포함되어 있다. 그리고 쿼리 문자열을 가져올 수 있는 query key도 존재한다.
예를 들어 http://localhost:3000/post/1?str=135135
을 검색하여 페이지 이동을 하게되면 params에는 { id: '1' }
그리고 query에는 { str: '135135', id: '1' }
이 담겨지게 된다.
그래서 위의 코드에서 context. query를 통해 id 값을 가져올 수 있었던 것이다.
그 밖에도 다양한 key값이 존재하는데 https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props 를 참고하면 좋을 것 같다.
그렇다면 어떤 상황에서 SSG를 사용하고 SSR을 사용해야 할지 궁금할텐데 공식문서에서는 자주 변경될 여지가 있는 데이터를 요청하는 경우가 아니면 가능한 SSG를 사용하는 것을 추천한다고 한다.