어떠한 설정도 하지 않은 모든 페이지들은 Static 방식으로 pre-rendering이 진행됩니다.
Static 방식은 pre-rendering이 빌드(build)시 서버에서 실행됩니다. 즉, pre-rendering을 위한 어떠한 설정도 하지 않은 페이지 컴포넌트들은 기본적으로 빌드시에 pre-rendering하여 HTML 문서를 생성합니다.
이는 명시적으로 빌드를 하지 않는다면 기존 생성한 HTML 문서를 계속 사용한다는 의미이며, 새로운 HTML 문서 생성을 원한다면 개발자가 명시적으로 빌드를 해야 합니다.
빌드시 서버측에서 pre-rendering하여 생성한 HTML 문서를 클라이언트에게 전달합니다.
클라이언트측에서는 pre-rendering된 HTML 문서를 즉시 렌더링합니다.
이후 Hydrate 과정으로 해당 페이지 컴포넌트 함수를 실행하여 리렌더링됩니다.
빌드시 서버측에서 pre-rendering하여 생성한 Fallback 버전 HTML 문서를 클라이언트에게 전달합니다.
클라이언트측에서는 Fallback 버전 HTML 문서를 즉시 렌더링합니다.
이후 Hydrate 과정에서 실행되는 해당 페이지 컴포넌트 함수는 query 객체가 빈 객체인 상태로 실행되어 리렌더링합니다.
NextJS가 해당 페이지 컴포넌트를 한 번 더 실행하는데 이때 실행되는 페이지 컴포넌트 함수는 query 객체에 경로 파라미터에 대한 정보를 가진 상태로 실행하여 리렌더링합니다.
Static 방식처럼 SSG 방식도 Pre-rendering이 "빌드시 서버"에서 진행됩니다. 즉, 개발자가 애플리케이션 배포를 위해 "build 명령어를 실행할 때 Node 환경에서" pre-rendering을 실행하여 HTML 문서를 생성합니다.
Static과 SSG의 차이점은 pre-rendering으로 HTML 문서를 생성할 때 초기 렌더링에 필요한 데이터를 props 객체의 프로퍼티로 페이지 컴포넌트에게 전달하여 실행한 결과를 콘텐츠로 갖는 HTML 문서를 pre-rendering하게 됩니다.
Static과 SSG 방식 모두 빌드를 했을 때 이미 HTML 문서가 생성되어 있고, 생성된 HTML 문서를 배포한 이후에는 바뀌지 않습니다. 즉, 서버측에서 데이터가 변경되었다 하더라도 개발자가 명시적으로 새롭게 빌드하여 배포하지 않는 이상에는 기존 HTML 문서를 계속 사용하게 됩니다.
Static-site Generation(SSG)방식을 사용하기 위해서는 해당 방식을 사용할 페이지 컴포넌트 파일 내부에 특수한 비동기 함수인 "getStaticProps
함수"를 export 해주어야 합니다.
반드시 pages 폴더 내 존재하는 페이지 컴포넌트 파일 내 정의해야하며, getStaticProps
라는 함수 이름을 사용해야 합니다.
빌드시 서버에서 pre-rendering될 때 먼저 getStaticProps
함수를 실행하여 렌더링에 필요한 데이터를 가져온 뒤 가져온 데이터를 페이지 컴포넌트 함수의 인수로 전달되는 props 객체의 프로퍼티로 전달하여 실행한 결과를 콘텐츠로서 갖는 HTML 문서를 생성합니다.
export async function getStaticProps(context) {
// fething data && backend api,,,
context.params;
return {
props: {
key: value,
,,,
},
revalidate: number,
notFound: false | true,
redirect: {
destination: '/경로'
}
};
};
getStaticProps
함수는 Node 환경에서 실행되기 때문에 함수 내부에 "백엔드 코드"를 작성할 수 있습니다. 즉, 클라이언트 사이드 코드로만 제한되지 않고 서버 사이드 코드도 실행할 수 있습니다.
getStaticPorps
는 클라이언트에게 전송되는 자바스크립트 파일에 포함되지 않습니다. 즉, 해당 함수 내 작성된 코드는 클라이언트측에서 확인할 수 없습니다.
또한 getStaticProps
함수에서 사용되는 패키지를 import 한 것도 클라이언트측에 전달되지 않아 확인할 수 없습니다.
참고로 NextJS가 fetch API를 제공하기 때문에 서버에서 실행되는
getStaticProps
함수 내부에서 fetch API를 사용할 수 있습니다.
빌드시 서버측에서 getStaticProps
함수를 실행할 때 JSON 파일을 생성하는데 이때 생성되는 JSON 파일은 "getStaticProps
함수의 결과"를 나타내는 파일이며 클라이언트 측에서 사용되는 파일입니다.
클라이언트측에서 SSG 방식을 사용하는 페이지에 접근하는 경우 서버측에서는 JSON 파일도 함께 응답으로 전달해주며, 해당 페이지 컴포넌트 함수를 실행할 때 props 객체로 전달받은 JSON 파일을 사용하여 실행하게 됩니다.
즉, 클라이언트측에서 Hydrate 과정에서 실행되는 페이지 컴포넌트 함수나 링크로 접근하여 실행되는 페이지 컴포넌트 함수는 서버가 전달해준 JSON 파일을 props 객체로 사용하여 실행하게 됩니다.
getStaticProps
함수는 인수로 "context 객체"를 전달받아 호출됩니다. 전달받은 context 객체에는 다음과 같은 프로퍼티들이 존재합니다.
userRouter
훅이 반환하는 객체의 query 프로퍼티에도 context.params 객체와 동일한 구조의 객체를 갖고 있지만 useRouter
는 리액트 훅이므로 getStaticProps 함수 내부에서는 사용이 불가능합니다.getStaticProps
함수의 반환값으로는 반드시 객체를 작성해야 하며, 객체에 작성 가능한 프로퍼티는 아래와 같습니다.
"props 프로퍼티"에는 객체를 작성합니다. 객체에는 페이지 컴포넌트에게 전달할 초기 렌더링 데이터를 프로퍼티로 작성합니다.
각 프로퍼티들은 페이지 컴포넌트 함수의 인수로 전달되는 props 객체의 프로퍼티가 됩니다.
실제 동작은 props 프로퍼티에 작성된 객체가 _app.js 파일의 MyApp 컴포넌트가 전달받는 props.pageProps 값이 되어 페이지 컴포넌트(props.Component)에게 props 객체로 전달하여 실행한 결과를 HTML 콘텐츠로서 생성하게 됩니다.
간단하게 getStaticProps
함수의 반환값에 작성된 객체의 props 프로퍼티에 바인딩된 객체가 바로 페이지 컴포넌트 함수의 인수로 전달될 props 객체로 볼 수 있습니다.
"revalidate 프로퍼티" 값으로는 초단위 시간을 숫자값으로 작성해줍니다.
revalidate 프로퍼티 값으로 작성된 시간이 지난 후 SSG 페이지에 접근하는 경우에 서버측에서는 새롭게 getStaticProps
함수를 실행한 결과를 JSON 파일로 생성하여 클라이언트에게 전달해줍니다.
클라이언트측에서는 새롭게 전달받은 JSON 파일을 props 객체로 사용하여 페이지 컴포넌트 함수를 실행하여 렌더링합니다.
이러한 pre-rendering 방식을 "Incremental Static Generation"(ISG) 방식이라고 합니다.
export async function getStaticProps(context) {
,,,
return {
,,,
revalidate: 10 // -> 해당 페이지 요청에 대해서 10초가 지난후 해당 페이지에 접속하는 경우 함수 다시 실행
};
}
"notFound" 프로퍼티 값은 불리언 값을 가지며, true로 설정하면 404 페이지를 렌더링합니다.
해당 설정은 getStaticProps
함수가 렌더링 데이터를 가져오는데 실패한 경우 notFound를 true로 설정하여 404 페이지가 렌더링되도록 할 수 있습니다.
export async function getStaticProps(context) {
,,,
if(조건) {
return {
,,,
notFound: true // -> 404 페이지를 화면에 렌더링
};
}
return {
props: { ,,, }
};
}
"redirect"는 경로를 리다이렉트를 위해 사용합니다. 즉, 해당 경로를 요청시 해당 페이지를 렌더링하지 않고 다른 페이지, 즉 다른 경로로 리다이렉트하게 됩니다.
이 또한 렌더링 데이터를 가져오는데 실패할 경우 필요한 설정입니다.
redirect 프로퍼티의 값은 객체를 작성해야 하며, 객체에 destination 프로퍼티에는 리다이렉트될 경로값을 문자열로 작성해줍니다.
export async function getStaticProps(context) {
,,,
if(조건) {
return {
,,,
redirect: {
destination: '/경로'
}
};
}
return {
props: { ,,, }
};
}
빌드시 서버측에서 pre-rendering하여 생성한 HTML 문서와 JSON 파일을 클라이언트에게 전달합니다.
클라이언트측에서는 pre-rendering된 HTML 문서를 즉시 렌더링합니다.
이후 Hydrate 과정으로 해당 페이지 컴포넌트 함수를 실행하는데 인수로 props 객체 역할로 JSON 파일을 전달하여 실행합니다.
> pages
index.js // -> getStaticProps 함수 존재(SSG)
> [meetupsId]
index.js // -> (Static)
> new-meetup
index.js // -> (Static)
위 pages 폴더 구조를 갖는 NextJS 프로젝트에서 터미널에 npm run build
를 입력하면 빌드가 진행됩니다.
이때 터미널에 출력된 결과물을 보면 Generating static pages(5/5)는 생성된 HTML 문서가 총 5개인 것을 확인할 수 있고, 아래에는 생성된 HTML 문서가 나옵니다. 색칠이 되어있는 원의 경우 SSG(Static Site Generate)로 생성되었다는 것을 의미하고, 빈 원의 경우 Static으로 생성되었다는 것을 확인할 수 있습니다.
빌드를 완료하면 프로젝트에 ".next" 폴더가 생성됩니다. pages 폴더 내부에 pre-rendering된 HTML 문서가 생성된 것을 확인할 수 있습니다.
즉, ".next/server/pages 폴더" 내에 pre-rendering된 HTML 문서가 존재하는 것을 확인할 수 있습니다.
참고로 404.html, 500.html 문서는 NextJS가 자동으로 생성한 HTML 문서입니다.