[Next.js] NextJS SSG로 빌드하기
SSG(Static-Site-Generation)이란?
Next는 브라우저에서 렌더링 할 때 기본적으로 pre-rendering(사전 렌더링)을 한다고 소개한다.(Next default 설정)
pre-rendering이란 각 페이지들을 사전에 미리 HTML 문서로 생성하여 가지고 있는 것이다. 즉 Pure React에서 CSR 방식은 번들링된 js가 클라이언트 단에서 모든 추가 렌더링을 담당했다면 Next의 pre-rendering 시스템에서는 빌드 타임 때 해당하는 페이지 별로 각각의 HTML 문서를 미리 생성해 가지고 있다가 서버로 요청이 들어올 때 알맞은 페이지를 반환해준다.
Next에서 pre-rendering을 하기 위해 두 가지 형식을 제안하고 있는데, 이는 다음과 같다.
1. Static-Generation(추천) :
- HTML을 빌드 타임에 각 페이지 별로 생성하고 해당 페이지로 요청이 올 경우 이미 생성된 HTML 문서를 반환한다.
- 퍼포먼스에 집중(CDN을 통해 더 빠른 응답 가능)
- 마케팅 페이지/블로그 게시물/ 제품의 목록 등과 같이 정적 생성하여 각 요청에 동일한 문서를 반환할 수 있는 경우
2. Server-Side-Rendering :
- 요청이 올 때 마다 해당하는 HTML 문서를 그때 그때 생성하여 반환한다.
- 항상 최신 상태를 유지해야 하는 경우(요청에 따라 응답해야 할 내용이 시시각각 변함)
- 제품의 상세 페이지/분석 차트 등 요청마다 다른 내용 또는 형식의 HTML 문서가 반환되는 경우
2. Page에 동적 데이터 추가하기(getStaticProps)
보통 React에서는 Rendering 이후에 API로 값을 조회해서 화면을 갱신하며, 이 경우 사용자는 첫 화면으로 아무것도 없는 로딩 화면을 보게 된다.
Next에서는 빌드 시점에 API 값을 조회하고, 그 값을 패키지 전달하여 생성한다. 때문에, API 조회 시간을 없애, 렌더링 속도와 First Meaningful 속도를 올릴 수 있다. 브라우저가 아닌 Node 상에서 API를 조회해야 하기 때문에 fetch는 쓸 수 없고, node-fetch를 써야한다.
빌드 시점에 한 번만 데이터를 가져와 페이지에 전달하기 때문에, 값이 계속 변화하는 API에는 클라이언트에서 한 번 더 조회할 필요가 있다.
import fetch from ‘node-fetch’;
function Index ({ data }) {
return <div>
Dog API
<img src={data.message} />
</div>;
};
export async function getStaticProps(context) {
const res = await fetch(
'https://dog.ceo/api/breeds/image/random'
);
const data = await res.json();
return {
props: { data }
};
};
getStaticProps에서는 파일 값도 조회하여 전달할 수 있다. 하지만, 파일을 직접 전달할 수는 없고, 내용을 obejct나 string 형태로 전달해야 한다.
빌드된 html을 확인하면, <script id="_NEXT_DATA_" type="application/json">{...}</script> 형태로 값을 전달하는 것을 볼 수 있다.
파일을 조회하는 것도 Node에서 하기 때문에, fs, path를 사용할 수 있다.보통 Node에서는 현재 경로를 _dirname로 가져올 수 있지만, Next에서는 별도의 process.cwd()를 사용해야 한다.
import fs from 'fs';
import path from 'path';
export async function getStaticProps(context) {
const file = path.join(process.cwd(), '/src/asset/data.txt');
const content = fs.readFileSync(file, 'utf8');
return {
props: { content }
};
};
3. Next.js SSG로 빌드하기
작업물을 Static Site로 배포하기 위해서 각각의 페이지와 파일들을 export 기능으로 빌드한다.
package.json의 scripts 영역에 아래와 같이 next build & next export 명령어를 세팅해준다.
// package.json
"scripts": {
"build": "next build && next export",
}
빌드 완료시, 기본적으로 out 폴더 밑으로 정적 파일들이 생성된다.
만약 build 폴더를 바꿔야 한다면, next.config.js에 distDir 정보를 변경해줌으로써 build 폴더를 세팅할 수 있다.
html과 asswet을 다른 서버로 관리해야 한다면, next.config.js에서 assetPrefix 값을 변경해주면 된다.
기본적으로 파일들은 pages 하위의 파일명을 따라가는데, 모든 html을 index.html로 build 해야한다면, next.config.js에서 exportTrailingSlash를 true로 설정한다.
// next.config.js
{
"distDir": "build",
"exportTrailingSlash": true,
"assetPrefix": "https://~~~"
}
Build Error 정리
Error: Image Optimization using Next.js' default loader is not compatible with `next export`.
next-optimized-images라는 third-party loader를 설치한다.
npm install next-optimized-images
next.config.js에 아래와 같은 구문을 추가하여 Image Optimization 클라우드 공급자에 Akami를 추가한다.
module.exports = {
images: {
loader: 'akamai',
path: '/',
}
}
Reference