사전 렌더링이란, Next.js를 대표하는 기능 중 하나로, 브라우저의 요청에 대해 사전에 렌더링이 완료된 HTML을 응답하는 렌더링 방식을 말합니다.
즉, 사용자가 웹 페이지에 접근할 때 이미 HTML이 만들어져 있기 때문에
빠른 로딩 속도와 SEO(Search Engine Optimization)에 유리합니다.
Next.js는 두 가지 방식의 사전 렌더링을 지원합니다.
차이점은 언제 html을 생성하는가 입니다.
Next는 최대한 이 정적 생성 방식을 사용하길 권고합니다.
왜냐하면 페이지가 빌드되어 CDN에 의해 제공이 되어 사용되는 것이 매번 페이지 요청하는 것보다 성능적으로 우수하기 때문입니다.
이런 정적 생성된 페이지는 서버에서 데이터를 자주 받아올 일이 없는 페이지(소개, 포스트ㅡ 각종 문서등)에 주로 사용됩니다. 반대로, 데이터의 업데이트가 많거나 사용자의 요청마다 매번 바뀌는 페이지라면 별로 좋은 선택이 아닐 것입니다.
그러나 몇몇의 페이지들에서 외부에서 데이터를 fetching 해오지 않으면, 렌더링이 안되는 경우가 있습니다. 예를 들어 파일 시스템에 접근하거나, 외부 API를 사용하거나, 데이터베이스에 쿼리를 날릴 때입니다. 넥스트는 이러한 경우(데이터를 사용한 정적 생성)도 지원하고 있습니다.
getStaticProps가 있다면, 빌드 타임에 Next.js가 알아서 한 번 실행하며, 리턴한 props는 해당 페이지 컴포넌트에 전달됩니다.export async function getStaticProps(context) {
return {
props: {},
}
}
function BlogPost({ post }) {
return (
<div>
<h1> {post.title} </h1>
<div> {post.content} </div>
</div>
)
}
export async function getStaticProps() {
const res = await fetch('https://.../posts/1')
const post = await res.json()
return {
props: {
post,
}
}
}
export default BlogPost
getStaticProps에서 데이터베이스로부터 id 값이 1인 해당 포스트 데이터를 불러오고, 그 post 데이터를 props로 리턴한다. 그러면 컴포넌트가 props를 통해 렌더링을 할 수 있게 됩니다.
만약 방금 예시에서 posts의 id값이 1뿐만 아니라 100개가 있고 각각 경로를 따로 설정해줘야 하는 경우에는 어떻게 해야할까요?
100개의 파일을 만들어줘야할까요?
당연히 아닙니다.
이런 경우에 getStaticPaths를 사용하여 데이터에 따라 사전 렌더링할 페이지의 동적 경로를 지정해주면 됩니다.
export async function getStaticPaths() {
return {
paths: [
{ params: { ... } }
],
fallback: ...
};
}
getStaticPaths는 paths를 getStaticProps 로 리턴합니다.
즉
/pages/posts/1.js
/pages/posts/2.js
...
/pages/posts/100.js
각각 생성할 필요 없이, pages/posts/[id].js 파일 하나로 모든 페이지를 생성할 수 있습니다.
function BlogPost({ post }) {
return (
<div>
<h1> {post.title} </h1>
<div> {post.content} </div>
</div>
)
}
export async function getStaticPaths() {
const res = await fetch('http://.../posts')
const posts = await res.json()
const paths = posts.map((post) => ({
params: { id: post.id },
}))
return { paths, fallback: false }
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
return {
props: {
post,
}
}
}
export default BlogPost
getStaticPaths 에서 /posts 에 저장된 모든 블로그 포스팅 데이터를 불러오고, id 값을 파라미터로 리턴합니다.
그러면 getStaticProps 에서는 각 path의 params 값을 받아 id를 통해 블로그 포스트를 불러오고, 그 post를 props로 컴포넌트에 전달합니다.

fallback은 getStaticPaths에서 반환하지 않은 경로에 대해
Next.js가 어떻게 처리할지를 결정하는 옵션입니다.
paths에 정의되지 않은 경로로 요청이 오면 404 페이지를 반환이 함수들은 모두 Next.js의 pages/ 디렉토리 안의 페이지 컴포넌트에서만 사용 가능하다는 제약이 있습니다.
getServerSideProps는 SSG의 getStaticProps와 비슷하지만 SSR을 위한 함수입니다.
페이지를 사용자의 요청이 들어올 때마다 서버에서 HTML을 생성하도록 해줍니다.
getStaticProps 처럼 컴포넌트에 props를 넘겨준다는 공통점이 있지만, 빌드 시가 아닌 매 request마다 실행된다는 차이점이 있습니다.
export async function getServerSideProps(context) {
// 서버 측에서 실행되는 로직
// context.req, context.res 등 접근 가능
return {
props: {},
}
}
export async function getServerSideProps(context) {
const { id } = context.params;
const res = await fetch(`https://api.example.com/posts/${id}`);
const post = await res.json();
return {
props: {
post,
},
};
}
| 속성 | 설명 |
|---|---|
req | Node.js의 HTTP 요청 객체 (IncomingMessage) |
res | Node.js의 HTTP 응답 객체 (ServerResponse) |
params | 동적 라우팅 페이지의 파라미터 |
query | URL 쿼리 스트링 |
resolvedUrl | 현재 요청된 경로 |
locale | (i18n 설정 시) 현재 언어 |
previewData | 프리뷰 모드 관련 데이터 |
보통 일반적인 사용에서는 req.coockies로 인증 정보, 쿠키 등을 확인하고, res는 리다이렉트나 캐시 제어가 필요한 경우에 사용합니다.