프리렌더링(Pre-rendering)
앞서 공부한 것처럼 Next는 프리렌더링(pre-rendering) 기능을 제공한다.
말 그대로 사전에 미리 html을 렌더링 한다는 뜻이다.
html을 미리 생성하고 최소한의 자바스크립트를 연결시킨 후 클라이언트에서 요청이 들어오면 해당 html을 로드하면서 나머지 자바스크립트를 불러와 화면에 렌더링 시켜주는 것이다.
프리렌더링을 하면 렌더링 성능과 SEO가 향상된다.
Plain React App
Pre-rendering을 하지 않으면, 초기에는 렌더링이 되지 않았다가 자바스크립트가 로드되면 페이지 요소들이 채워진다.
Using Next.js App
Pre-rendering을 한다면 사전에 만들어진 HTML 파일을 보여주고 이후 자바스크립트가 로드되면 Hydration이 실행된다.
*Hydration이란, 브라우저가 모두 로드되었을 때 사용자와 상호작용할 수 있는 상태를 의미한다.
Pre-rendering의 종류
Pre-rendering은 Static Generation과 Server-side Rendering 두 가지 종류가 있다.
둘의 차이점은 "언제 HTML 파일이만들어지는가?" 이다.
HTML 생성 시점
Static Generation | 빌드 시점에 |
Server-side Rendering | 매 요청마다 |
Static Generation
사용자의 요청과는 별개로 페이지를 미리 만들어 놓고,한 번 만들어놓으면 CDN을 통해 재사용하기 때문에 서버에서 매번 요청하는 것보다 빠르다.
공식 문서에 나와있는 Static Generation 페이지 사용 예시
- Marketing pages - 마케팅 페이지
- Blog posts - 블로그 포스트
- E-commerce product listings - 제품 목록
- Help and documentation - 도움말, 문서
Server Side Rendering
페이지 로딩 속도는 느릴 수 있지만 매번 서버에 요청을 하여 렌더링 하기 때문에 해당 페이지는 항상 최신 상태를 유지할 수 있다.
Next는 기존에 data fetching에 있어 getInitialProps를 사용하였지만 9.3 버전부터는 getStaticProps, getStaticPaths, getServerSideProp 세 가지로 나뉘었다.
getServerSideProps / getStaticProps / getStaticPaths
getStaticProps
- 빌드 시에만 서버에서 데이터를 가져와 html과 json 파일을 미리 만든다.
- 이후에 서버에서 데이터가 바뀌어도 다시 통신을 하지 않기 때문에 데이터가 실시간으로 업데이트 되지 않는다는 것을 주의해야한다.
- html, json 파일 모두 퍼포먼스 향상을 위해 CDN에 캐싱한다.
const Detail = ({ data }) => {
return <></>;
};
export async function getStaticProps(context) {
const data = await fetch('--');
return {
props: { data }, // 페이지 컴포넌트에 props로 넘길 것
};
}
export default Detail;
getStaticPaths
- getStaticProps와 동일하게 빌드 시에 서버에서 데이터를 받아온다.
- 차이점이 있다면 getStaticPaths는 Dynamic Routes에서 사용된다.
const Detail = ({ data }) => {
return <></>;
};
export async function getStaticPaths() {
return {
paths: [
{ params: { id: '100' } },
{ params: { id: '200' } },
{ params: { id: '300' } }
],
fallback: true, // false or 'blocking'
};
}
export async function getStaticProps(context) {
const data = await fetch('--');
return {
props: { data }, // 페이지 컴포넌트에 props로 넘길 것
};
}
export default Detail;
getStaticProps와 반드시 같이 사용해야하며 getServerSideProps와는 같이 사용할 수 없다.
예시 설명
- path로 설정된 경로들은 빌드 시 미리 만들어진다.
- id값이 100, 200, 300인 페이지를 미리 생성한다.
- fallback이 false일 경우 path에서 설정하지 않은 경로들은 대응하지 않는다. 즉 404페이지가 나온다.
- fallback이 true일 경우에는 백그라운드에서 정적 파일로 htm과 json을 생성하여 pre-render목록에 추가한다.
- 따라서 처음 페이지가 로드될 때는 느리며 이후부터는 빠르게 로드된다.
getServerSideProps
- 서버 측에서 프리렌더를 하여 반환 데이터를 getServerSideProps로 페이지에 전달한다.
- 빌드와 상관없이 매 요청마다 서버에서 데이터를 가져온다.
- 서버에서 계속 데이터를 가져오기 때문에 정보들은 항상 최신 상태로 유지된다.
- 따라서 제품 상세 페이지, 관리자 페이지와 같은 곳들에서 사용된다.
const Detail = ({ data }) => {
return <></>;
};
export async function getServerSideProps(context) {
const data = await fetch('url');
return {
props: { data }, // 페이지 컴포넌트에 props로 넘길 것
};
}
export default Detail;
🔄 Return
returngetServerSideProps는 세 가지의 반환 값을 가진다.
props | 컴포넌트로 리턴할 값 |
redirect | 페이지 접속 시 지정한 경로로 리디렉션 시키기 위해 사용되는 값 |
{destination : string, permanent : boolean} 의 형태 | |
status 코드가 필요하거나 변경해야 할 때는 permanent 대신 statusCode를 사용한다. | |
notFound | boolean 값, true일 경우 404 status와 에러 페이지를 보여준다. |
데이터 통신에 실패했을 때 사용한다. |
ℹ️ Context
contextcontext 객체를 인자로 받으며 아래 정보들을 담고 있다.
params | 다이나믹 라우트 페이지면 해당 데이터를 가져온다. |
req | Request 정보 |
res | Response 정보 |
query | 쿼리 스트링 |
preview | preview mode 사용 유무 |
previewData | preview mode 사용 시 전달된 데이터 |
resolvedUrl | 짧은 URL |
예) http://localhost:3000/detail/100 ➡️ /detail/100 | |
locale | 현재 locale 정보 |
locales | 지원되는 모든 locale 정보 |
defaultLocale | 기본 locale 정보 |
언제 getServerSideProps를 사용해야 하는가?
request time에 반드시 데이터를 fetch해야 하는 페이지를 pre-render해야 하는 경우에만 getServerSideProps를 사용해야한다.
데이터를 pre-render할 필요가 없다면 클라이언트에서 데이터를 가져오는 것을 고려해야한다.
클라이언트 측에서 데이터 가져오는 과정 (Fetching data on the client side)
페이지에 자주 업데이트되는 데이터가 포함되어 있고 데이터를 pre-render할 필요가 없는 경우 사용한다.
- 데이터가 없는 페이지를 즉시 표시한다.
- 페이지의 일부는 Static Generation을 사용해 pre-render할 수 있습니다.
- 빈 데이터를 위해 Loading 상태를 표시할 수 있다.
- 클라이언트 측에서 데이터를 가져와 준비가 되면 브라우저에 표시한다.
getServerSideProps가 오류 페이지를 렌더링 할 수 있는가?
- getServerSideProps 내부에서 오류가 발생하면 pages/500.js 파일이 표시된다.
- 500 page(서버 렌더링 오류 페이지)는 사용자가 커스터 마이징 할 수 있다.
- 개발 중에는 이 파일이 사용되지 않고 개발 오버레이가 표시된다.