Next.js는 페이지를 어떻게 렌더링할까? Data fetching을 할 때, 사용에 따라 다양한 방식으로 렌더링할 수 있다.
Next.js는 기본적으로 모든 page를 pre-render한다.
즉, 각 페이지의 HTML을 미리 만들어놓는다. (SEO에 유리하다.)
브라우저에 페이지가 로드되면 그때 JavaScript 코드를 실행해서 interactive해진다.(hydration)
Pre-rendering의 2가지 양상
Client-side data fetching
Q. 유저가 요청하기 전에 페이지를 pre-render할 수 있는가?
빌드타임(next build
)에 HTML 페이지가 생성된다.
Static Generation without fetching data
Static Generation with fetching data
getStaticProps
: 페이지 content가 외부 데이터에 의존getStaticpaths
: 페이지 path가 외부 데이터에 의존. 보통 getStaticProps
와 함께 사용된다.가능하면 항상 쓰자. 페이지가 단 한번만 생성되고 CDN에서 받을 수 있어서 서버가 매 요청마다 렌더링하게 하는 것보다 빠르다.
ex. 블로그 포스트, 상품 목록 등
데이터가 너무 자주 바뀌고, 매 요청마다 바뀐다면 다음을 사용하는 것을 고려해보자
Q. 페이지가 너무 많이 바뀌는 데이터를 필요로 하는가?
page가 Server-side 렌더링을 한다면, HTML 페이지는 매 요청마다 생성된다.
getServerSideProps
를 export해야 한다.
Next.js에서 Data fetching을 할 때, 사용에 따라 다양한 방식으로 콘텐츠를 렌더링할 수 있다.
페이지에서 getServerSideProps를 export하면 페이지는 server side rendering 된다.
export async function getServerSideProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
Request directly : 페이지 요청 하는 시점에 실행된다. 페이지는 리턴된 props로 pre-render된다.
Client-side transitions : next/link
, next/router
를 통해 서버로 API 요청을 보내면 그 때 실행된다.
JSON을 반환하고, 반환된 props는 page를 pre-render하는데 사용된다.
페이지에서만 사용할 수 있다.
반드시 standalone function으로 export해야 한다.
export async function getServerSideProps({ req, res }) {
res.setHeader(
'Cache-Control',
'public, s-maxage=10, stale-while-revalidate=59'
)
return {
props: {},
}
}
페이지에서 getStaticProps를 export하면 페이지는 빌드 시 pre-render된다.
export async function getStaticProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
server에서만 실행된다.
next build
중에 실행된다.
fallback: true
사용 시 백그라운드에서 실행된다.
fallback: blocking
사용 시 초기 렌더 이전에 호출된다.
revalidate
사용 시 백그라운드에서 실행된다.
revalidate()
사용 시 호출할 때 백그라운드에서 실행된다.
ISR(Increment Static Regeneration)과 결합되면 stale한 페이지가 fresh한 페이지로 갱신될 때 백그라운드에서 실행된다.
정적 HTML을 생성할 때 query parameter나 HTTP 헤더 등의 요청에 접근할 수 없다. 접근하고 싶다면 미들웨어를 사용하는 것을 고려해야 한다.
getStaticProps()
내에서 데이터를 패치하고, 결과를 props로 전달한다.getStaticProps
실행 결과를 JSON 파일로 생성해 저장해둔다.next/link
또는 next/router
을 통한 client-side 라우팅 시 사용된다. getStaticProps를 사용해 pre-render된 페이지로 이동할 때, Next.js는 빌드타임에 생성된 이 JSON파일을 fetch해 page 컴포넌트의 props로 사용한다. 즉, client-side 페이지 이동이 getStaticProps를 호출하지 않으며 export된 JSON을 사용한다는 뜻이다._app
이나 _document
혹은 _error
에서는 export할 수 없다. 왜냐면 React가 페이지를 렌더하기 전에 필요한 모든 데이터를 가지고 있어야 하기 때문next dev
)에서는 매 요청마다 호출된다.페이지가 Dynamic Routes를 갖고 있고,
getStaticProps
를 사용하고 있다면 정적으로 생성할 path의 목록을 미리 정의해줘야 한다.
export async function getStaticPaths() {
return {
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
fallback: false, // can also be true or 'blocking'
}
}
getStaticPaths
가 명시한 모든 path에 대해 pre-render한다.getStaticProps
는 HTML과 JSON 파일을 생성해 CDN에 캐시되어 성능을 높여줄 것이다.getStaticProps
는 next build
때 빌드에서 리턴된 path로 실행된다.getStaticProps
는 fallback: true
일 때 백그라운드에서 실행된다.getStaticProps
는 fallback: blocking
일 때 초기 렌더링 전에 호출된다.getStaticPaths
는 getStaticProps
와 함께 사용되야 한다.getStaticPaths
는 getServerSideProps
와 함께 사용할 수 없다.next dev
)에서는 매 요청마다 호출된다.Next.js는 빌드 후에 정적 페이지를 생성하거나 갱신할 수 있게 해준다.
ISR이 페이지 기반으로 전체를 다시 빌드하지 않고도 정적 생성이 가능하도록 해준다.
ISR로 페이지가 많아도 정적인 페이지가 주는 이점을 누릴 수 있다.
experimental-edge 런타임과 호환되지 않는다. cache-control 헤더를 수동으로 설정해 stale-while-revalidate를 활용할 수 있다.
ISR을 사용하기 위해 getStaticProps
에 revalidate
prop을 추가하면 된다.
빌드 타임에 pre-render된 페이지를 만드는 요청이 오면, 일단 캐시된 페이지를 보여준다.
getStaticProps
내부에서 revalidate를 특정하지 않아도 된다. revalidate를 제거하면 Next.js는 기본값(false, no revalidation)을 사용하고, revalidate()호출 시에만 revalidate한다.getStaticProps
내에서 백그라운드 재생성 에러, 혹은 수동으로 설정한 에러가 발생하면 마지막으로 성공적으로 생성된 페이지를 보여준다. 차후 요청에서는 getStaticProps
를 재시도한다..next
폴더의 캐시도 공유되고 재사용된다. isrMemoryCacheSize를 0으로 주면 되며, 이 경우 다중 pod이 동시에 같은 캐시를 갱신하려고 할 때 race condition에 유의해야 한다.page가 SEO를 필요로 하지 않을 때, 혹은 페이지가 자주 갱신될 때 유용하다.
SSR과 다르게 컴포넌트 레벨에서 데이터를 패칭할 수 있다.
페이지 레벨에서, 런타임에 데이터가 패치되고 페이지 콘텐츠는 데이터가 변함에 따라 갱신된다.
컴포넌트 레벨에서, 데이터는 컴포넌트가 마운트될 때 패치되고 컴포넌트 콘텐츠는 데이터가 변함에 따라 갱신된다.
client-side 데이터는 페이지 로드 속도와 어플리케이션 성능에 영향을 미친다. 데이터는 캐시되지 않으며, 컴포넌트나 페이지가 마운트될 때 패치되기 때문이다.
방법
필요했던 게 다 있어요! 너무 맛있어요!