1. Next SSR
Next js Static Generation, Server Side Rendering 이라는 형태의 렌더링을 제공한다.
이러한 형태의 렌더링 방식은 기존에 자바스크립트를 받아 브라우저에서 그리는 CSR 방식에 비해, 서버에서 HTML을 만들어 제공해 줌으로써 빠른 응답속도를 가지고 SEO 측면에서도 크롤러가 CSR 방식에 비해 잘 크롤링 할 수 있다.
2. Static Generation
첫번째로 알아볼 것은 정적 페이지 생성이다. 블로그의 소개 페이지 등 자주 업데이트 되지 않는 내용들은 첫 빌드타임 때 HTML을 생성 후 요청이 들어오면 추가적인 로직 없이 바로 뿌려주면 된다.
이럴 때 사용하는 것이 Next의 getStaticProps
함수이다.
NextPage
가 getStaicProps
를 export
시키면 Next
는 빌드 타임 때 이 함수를 이용해 미리 페이지를 빌드한다.
export const getStaticProps: GetStaticProps<Props> = async () => {
return {
props: ...,
revalidate: ...,
}
}
리턴 객체는 props
와 revalidate
notFound
등 여러 옵션 값들로 구성되어 있다.
-
props
- 필수로 리턴해줘야 하는 값으로, 이 값이 페이지의 Props로 들어간다. -
revalidate
- Incremental Static Regeneration에 사용되는 값이다. 정적 페이지를 동적으로(?) 만들 때 사용된다.
Next는 빌드 타임에 getStaticProps
함수를 실행시켜 필요한 정보(Props)들을 JSON 형태로 만든 뒤 HTML과 함께 클라이언트에 서빙한다.
Next 공식 Docs에서는 다음과 같을 때 getStaticProps
가 유용하다고 말하고 있다.
- 페이지 렌더링에 필요한 데이터들이 유저에 상관없이(not user specific) 정적일 때 (예를 들어 프로필 페이지는 이런 조건을 만족하지 못한다.)
- SEO 등을 위해 빠르고, 미리 렌더링 해야 하는 페이지
getStaticPaths
페이지가 Dynamic Routes 를 사용하고 있고 getStaticProps
를 사용한다면 빌드 타임 때 생성해야 하는 페이지들을 미리 정의해줘야 한다. 이 때 사용하는 함수가 getStaticPaths
들이다.
getStaticPaths
는 미리 빌드해두어야 할 경로들을 paths
라는 값에 담아 리턴해준다.
예를 들어 pages/posts/[id].js
가 getStaticProps
를 사용하는 정적 페이지 라면
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } }
],
fallback: ...
}
이런 형식으로 paths
를 리턴해준다면 Next는 posts/1
posts/2
라는 페이지들을 빌드타임에 생성할 것이다. 여기서 사용된 params
는 getStaticProps
의 인자 context
로 받아서 사용할 수 있다.
또한 getStaticPaths
는 fallback
도 함께 반환해 주어야 한다.
1. fallback이 false인 경우
getStaticPaths
가 반환하지 않은 경로들은 모두 404페이지로 리다이렉팅 된다. 이는 미리 만들 페이지들이 적고 paths
가 거의 변하지 않을 때 유용하다.
2. true인 경우
getStaticPaths
가 반환한 paths
들은 일단 모두 빌드타임에 만들어 둔다. 이후 빌드된 페이지가 없는 경로로 접근하면
- fallback page를 우선 응답한다.
- Next는 해당 페이지를
getStaticProps
를 이용해 빌드한다. - 이후 빌드된 페이지를 새롭게 렌더링한다.
이런 과정을 거치고 나면 새로운 경로의 페이지가 생성되고, 똑같은 경로로 접근하는 클라이언트들은 이제 위에서 생성된 페이지를 응답받게 된다.
이러한 fallback: true
는 쇼핑몰 상품 페이지 처럼 만들어야 할 정적페이지가 많을 떄 유용하다고 한다. 이런 경우 모든 paths
들을 빌드해두는 것은 시간이 상당히 오래 소요되므로, 페이지를 몇개만 만들어 두고 나머지는 fallback
을 이용하여 페이지를 빌드 및 사용자에게 제공한다.
Incremental Static Regeneration
SSR과 SSG 의 하이브리드 버전으로, Next 9.5 버전 이후부터 제공된다.
SSR의 단점인 요청이 들어왔을 때 빌드를 해 응답시간이 느려진다는 점을 극복했다.
ISR에서는 요청이 들어오면 이미 빌드되어있는 페이지를 서빙한다. 이후 revalidate
만큼 지난 뒤 다시 요청을 하면 Next는 새로운 페이지를 빌드한다. 이제 그 다음 요청부터는 새롭게 빌드된 페이지를 서빙하게 된다.
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every second
revalidate: 1, // In seconds
}
}
이런 식으로 Static 페이지를 계속 제공해주면서 서버에서 새로 빌드하는 방식은, SSR의 단점을 극복하면서 동적으로 페이지를 만들어 준다는 장점이 있다.
Next js 공식문서에서는 다음과 같은 장점이 존재한다고 한다.
- 대기시간이 적음. 페이지는 항상 빠르게 제공된다. (항상 빌드되어 있는 상태임)
- 페이지가 go offline 되지 않는다. 만약
revalidate
에 실패해도 이전 페이지가 존재한다. - 디비 접근이 적다. SSR은 요청마다 접근하지만 ISR은 페이지를 생성할 때 마다 한번씩 접근한다.
3. Server-side Rendering
마지막으로 살펴볼 것은 getServerSideProps
를 이용하는 전통적인 서버사이드 렌더링 방식이다.
매 요청마다 HTML와 JSON을 생성해서 응답한다.
function Page({ data }) {
// Render data...
}
// This gets called on every request
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`https://.../data`)
const data = await res.json()
// Pass data to the page via props
return { props: { data } }
}
export default Page
getServerSideProps
는 유저 프로필 페이지 처럼 들어갈 데이터들이 페이지 렌더링 이전에 가져와야 할 데이터들이 있을 때 사용한다.
또한 getServerSideProps
는 서버사이드에서만 실행된다. 즉 서버에서 함수를 실행한 뒤 결과를 JSON 형태로 담아 클라이언트에 보낸다.
4. 정리
Nextjs에서 페이지를 렌더링 하는 방식은 크게 Static Generation 과 Server Side Rendering이 존재한다.
기본적으로 응답시간을 줄이기 위해서 getStaticProps
를 이용하는 Static Generation을 사용한다. 빌드 타임때 존재하지 않는 페이지들은 fallback
을 이용해서 빌드한 뒤 제공해 줄 수 있다.
또한 동적인 데이터들을 제공해야 할 때는 Incremental Static Regeneration 방식을 사용할 수 있다.
마지막으로 응답시간은 느려지지만 요청마다 데이터를 받아와 클라이언트에 보내주는 Server Side Rendering 방식이 있다.