Next JS에서는 각 페이지에 대해서 pre-rendering을 위해 SSR(서버 사이드 렌더링) 또는 SG(정적 생성) 옵션을 제공한다. 각각 페이지 컴포넌트에서 getServerSideProps
, getStaticProps
/getStaticPaths
함수 export를 통해서 옵션을 정할 수 있으며, 여기서 페이지 생성을 위한 데이터 페칭 등의 작업을 진행할 수 있다.
여기서 정적 페이지 생성 옵션을 선택할 경우에는 페이지가 "앱 빌드"시(next build
커맨드 실행시)에 생성되고, 서버 사이드 렌더링 옵션을 선택할 경우에는 각 "클라이언트 요청에 맞춰서" 페이지가 생성된다.
물론 페이지의 일부분에 대해서만 pre-rendering을 적용하고, 일부분은 클라이언트 사이드에서 데이터 페칭 후 렌더링하는 등 유연하게 페이지를 구성하는 것도 가능하다.
우선은 Static Generation 쪽을 살펴보자.
조금 풀어서 말해보면, 정적 페이지 생성 옵션의 경우에 앱 빌드시 한번만 페이지가 빌드되고, 여러 요청에 대해서 빌드시에 만들어 놓은 똑같은 페이지를 계속해서 반환한다.
getStaticProps
간단한 예시 코드를 만들어봤다. 아래 페이지 컴포넌트는 Next JS 파일 시스템 라우팅 규칙에 따라서, /users
로 들어온 GET 요청을 처리한다.
// pages/users/index.js
import axios from 'axios'
import _ from 'lodash'
export default function UsersPage({ users }) {
const userList = _.map(users, (user) => {
return <li key={user.id}>{user.id} / {user.name} / {user.email}</li>
})
return (
<ul>
{userList}
</ul>
)
}
export async function getStaticProps(context) {
const { data: users } = await axios.get('https://jsonplaceholder.typicode.com/users');
return {
props: {
users
}
}
}
이 페이지를 정적으로 생성하도록 하기 위해서, getStaticProps
함수를 export 해준다. 이렇게하면, Next JS 앱 빌드를 할 때 각각 정적 페이지에 대해서
getStaticProps
함수가 실행되고실제로 next build
커맨드를 실행해보면,
next build 커맨드 실행 결과
친절하게 결과를 알려주는데, 위의 코드에서 정의한 /users
페이지가 SSG를 통해서 생성되었음을 알 수 있다. 실제로 빌드된 파일을 살펴보면 .next/server/pages
디렉토리에 users.html
이 있는 것을 확인할 수 있고, 이 파일이 클라이언트 요청시에 반환되는 것이다.
getStaticPaths
만약 생성하고자 하는 페이지가 라우트 파라미터에 의존하는 경우(users/1
, users/2
), 페이지 컴포넌트를 [id].js
와 같은 이름으로 지정해줘야한다. 이런 경우에 어떤 파라미터들에 대해서 정적 페이지를 생성할 것인지 판단할 수 없기 때문에, getStaticPaths
함수를 export 해줘야한다.
이 함수를 통해서 어떤 라우트 파라미터들에 대해서 페이지를 빌드타임에 생성할지 지정해줄 수 있다. 단, getStaticPaths
함수만 export 해서는 안되고, 마찬가지로 getStaticProps
함수 역시 export 해줘야한다.
각 함수의 역할은 위에서 언급한 것 처럼
getStaticPaths
: 어떤 path들의 정적 페이지를 빌드할건지 반환getStaticProps
: 각각 path에 대해서 정적 페이지 빌드에 필요한 데이터 반환라고 정리할 수 있다.
아래 코드 예시는 users/:userId
로 들어온 GET 요청을 처리하는 페이지 컴포넌트다.
// pages/users/[id].js
import axios from 'axios'
import _ from 'lodash';
export default function UserDetailPage({ user }) {
return (
<div>
{user.id} / {user.name} / {user.email}
</div>
)
}
export async function getStaticPaths() {
const { data: users } = await axios.get('https://jsonplaceholder.typicode.com/users');
const paths = _.map(users, (user) => {
return { params: {id: _.toString(user.id)}};
});
return {
paths,
fallback: false
}
}
export async function getStaticProps(context) {
const { id } = context.params;
const { data: user } = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`);
return {
props: {
user
}
}
}
위 코드는 마찬가지로 Next 앱 빌드시에
getStaticPaths
를 통해 정적으로 생성할 페이지들의 path 반환getStaticProps
를 통해 생성할 각 페이지들에 대해서 필요한 데이터 페칭 & 반환html
문서 생성하는 과정을 거치게 된다.
next build
커맨드를 실행해보면,
getStaticPaths
에서 반환한 path들(1~10 id를 가진 users)을 대상으로 정적 페이지가 생성되었음을 알 수 있다. 실제로 파일들도 정상적으로 생성된 것을 확인할 수 있다.
getStaticProps
는 각각 페이지에 대해 HTML과 JSON파일을 만드는데, 둘 모두 CDN에 의해 캐싱될 수 있다 → 성능에 이점.getStaticProps
revalidate
옵션notFound
옵션getStaticPaths
paths
로 반환되지 않은(즉, 빌드시에 정적으로 생성되지 않은) path의 페이지들에 대해서 어떤 응답을 보낼지 지정
→ 반환 객체의 fallback
옵션
false
)path
에 맞는 페이지 생성(getStaticProps
이용), 이후 오는 이 path
에 대한 요청들에 대해서 이때 생성한 페이지 반환