[Next.js] 넥스트의 사전렌더링 - (1) 정적생성
개요
현재 풀스택 프레임워크인 넥스트를 배우는 중인데, 넥스트의 가장 중요한 특징인 사전렌더링에 대해 정리해보고자 합니다. (page-router 기반으로 배우는 중입니다) 작동원리가 헷갈려서 제가 이해한 대로 정리했습니다.
넥스트를 시작해보면 리액트만 하던 분들은 좀 당황하실건데,
index.html 이 없습니다... 바로 넥스트의 특징인 사전렌더링 때문인데요, 그러면 컴포넌트를 어디에 뿌리는가?
바로바로 넥스트가 사전렌더링으로 정적 생성한 html 페이지들이 있는데, 접속한 경로에 맞는 html 파일을 쓰고 이 html 파일을 재활용해 react 컴포넌트가 렌더링되는 것이라고 이해하면 됩니다. (초기 접속 시에만 정적 페이지 사용하고 나머지는 react 작동 방식과 같음)
기본적으로 넥스트는 동적 데이터가 없는 모든 페이지를 빌드 시에 사전 렌더링 합니다.
빌드 시 이렇게 정적 페이지가 몇 개 생성되고 있는지 확인할 수 있고, (404 페이지는 기본적으로 생성된답니다)
빌드 완료 후 .next/pages
확인 시
이렇게 사전 생성된 html 파일들을 확인할 수 있습니다.
next.js의 서버단에서 보여줄 위의 html 컨텐츠를 가져와서 클라이언트에 보내고, react는 번들링된 js 코드를 클라이언트에 전송합니다. 그 후, 클라이언트단에서 Hydrate를 수행하여 이렇게 전송 받은 html과 js 코드를 매칭하게 되고, 정적 페이지가 동적 페이지로 변환되도록 합니다. (이 매칭은 hydrate 함수를 통해 이루어집니다)
기존 react 앱은 CSR 방식이라 브라우저가 처음 로딩하는 콘텐츠는 아무런 데이터가 포함되어 있지 않은 html이기 때문에 데이터 페칭 시 지연이 발생하여 사용자 경험이 최적화되지 않고, seo 가 불가합니다. 이런 넥스트의 작동 방식은 기존 리액트 동작 방식을 보완해줍니다.
기존 리액트 동작 방식에 대해 정리해보면,
요청 전송
브라우저에 빈 html 파일 및 모든 js 코드 번들 정보 전달
브라우저가 js 번들 모두 다운로드 (이 때 유저는 빈 화면을 보게 됨)
js 코드 시 실행 시 스크린에 내용 표시
가 되겠지요.
넥스트는 기본적으로 동적 데이터가 없는 페이지를 정적 페이지로 사전 렌더링 한다고 했습니다. 그렇다면 넥스트는 동적 데이터가 있는 페이지를 정적 생성할 수 없는가?
getStaticProps
빌드 시 외부 데이터를 가져와야 페이지를 생성할 수 있는 경우에는 특수 비동기 함수인 getStaticProps
를 사용해 외부 데이터를 fetching 한 후, 이를 props로 가져와서 외부 데이터를 사용한 페이지는 정적 생성을 통한 사전 렌더링이 가능합니다.
굳이굳이 이렇게 props를 따로 받아와야 하는 이유는 무엇일까요? 빌드 과정 중 페이지를 미리 준비하려면 매개변수로의 액세스가 필요한데, getStaticProps는 사전렌더링을 위한 함수이기 때문에 컴포넌트 함수보다 먼저 시행이 됩니다. 이 덕분에 컴포넌트에 대한 데이터를 준비할 수 있어서 정적 생성이 가능한 것입니다.
export async function getStaticProps(context){
return{props:...} //항상 props 키가 있는 객체를 반환해야 한다. -> 컴포넌트 함수에 대한 props를 준비
}
그런데 여기서 의문이 생길 수 있습니다. getStaticProps를 이용해 외부 데이터가 있는 페이지를 정적 생성해 사전 렌더링 하는 경우에, 새 게시물 추가와 같이 데이터가 변경/추가 되는 경우 빌드를 다시 실행하여 다시 배포해야하는 것일까요?
이 경우를 위해 ISR(incremental static generation) 을 활용합니다.
ISR
getStaticProps 반환 값에 revalidate 라는 키를 추가합니다.
export async function getStaticProps(){
...
return {
props:{
products:data.products
},
revalidate: 10
};
}
revalidate 값으로 재생성까지 기다려야하는 시간(초 단위)을 입력할 수 있습니다. 이를 입력 시 페이지 빌드 할 때 정적 페이지를 한 번만 생성하는 것이 아닌, 배포 후에도 매 X초마다 재생성이 가능합니다. (재빌드 방식이 아닙니다.)
매 10초마다 재생성하는 것이 과부하를 일으키지 않을까 의문이 들었는데, 화면 요청이 들어오지 않으면 재생성은 일어나지 않고, 화면 요청이 들어온 경우에만 재생성 작업을 시작한다고 합니다.
이렇게 넥스트의 정적 생성을 통한 사전 렌더링을 알아보았는데요, 사실 넥스트의 사전 렌더링 방식은 두 가지입니다.
(권장 양식) 정적 양식
서버 사이드렌더링
서버 사이드 렌더링은 배포 후 요청이 서버까지 오는 때에 페이지가 생성이 되며, 요청받을 때마다 페이지를 생성합니다. 서버 사이드 렌더링은 다음번에 정리해보도록 하겠습니다.
지적 환영...
참고자료
[Next.js] Incremental Static Regeneration의 revalidate (re-generation)테스트
edited by 박지은