Next.js에서는 동적 경로를 갖는 페이지에서 SSG(Static Site Generation)
방식으로 사전 렌더링을 설정할 때, 해당 페이지에서 존재할 수 있는 경로들을 미리 정의해야 한다. 이를 위해 getStaticPaths
함수를 사용하고, 해당 경로에 접근할 때 반환되는 페이지를 조절하는 fallback
옵션을 추가할 수 있다.
이 fallback
옵션은 SSG와 SSR의 혼합형 페이지 제공 방식을 지원하는 유연한 옵션으로, 'blocking'
, true
, false
의 세 가지 값으로 설정할 수 있다.
다양한 동적 경로를 갖는 book페이지에 SSG 방식의 사전 렌더링을 적용하기 위해서는getStaticPaths
함수를 작성해서 이 함수 안에서 paths
라는 값을 return함으로써 현재 어떤 페이지들이 존재할 수 있는지 직접 설정을 해야 하는데,
기본값인 false
로 설정할 경우, paths에 정의된 경로 외의 요청이 들어오면 해당 페이지는 404 Not Found
로 반환된다. 예를 들어, book/1
, book/2
, book/3
경로만 설정한 경우, book/4
로의 요청은 404 페이지
를 반환하게 된다.
// src/pages/book/[id].tsx
export const getStaticPaths = () => {
return {
paths: [
{params: {id: "1"}},
{params: {id: "2"}},
{params: {id: "3"}}
],
fallback: 'blocking',
};
};
이 설정은 지정한 경로 외의 추가 경로 요청을 차단하는 가장 단순한 방식이다. 그러나 추후에 경로가 추가될 가능성이 있는 경우에는 정해둔 paths들 외에는 Not Found페이지
를 반환하게 되기 때문에 설정이 유연하지 않으므로 'blocking'
이나 true
옵션을 고려할 수 있다.
'blocking'
옵션은 paths 외의 경로 요청 시, SSR처럼 해당 경로를 서버 측에서 즉시 사전 렌더링하여 제공하는 방식이다. 이를 통해 새로운 페이지가 서버에서 처음 요청될 때 SSR 방식으로 생성되고, 생성된 후에는 정적 페이지로 저장되므로 이후 요청 시에는 SSG와 동일하게 빠르게 응답할 수 있다.
export const getStaticPaths = () => {
return {
paths: [
{params: {id: "1"}},
{params: {id: "2"}},
{params: {id: "3"}}
],
fallback: 'blocking', // 존재하지 않는 페이지도 SSR처럼 생성하여 제공
};
};
4번 페이지처럼 SSR방식으로 새롭게 생성된 페이지는 우리가 빌드 타임에 생성해둔 1, 2, 3번 페이지처럼 Next서버에 자동으로 저장이 된다. 그렇기 때문에 .next/server/pages/book
경로의 폴더를 보면
이렇게 1, 2, 3번 페이지처럼 방금 생성된 4번 페이지 또한 이런식으로 정적페이지로써 잘 생성이 되어서 저장이 된 걸 볼 수 있다.
요청된 경로가 paths
에 정의되지 않았을 경우, Nextjs가 해당 페이지를 SSR
방식으로 생성한 후 반환한다.
이 과정에서 페이지 생성 시간이 길어질 수 있지만, 생성 후에는 정적 페이지로 저장되어 이후에는 SSG처럼 빠르게 제공된다.
'blocking'
옵션을 사용하게 되면 빌드 타임에 사전에 생성해 두지 않았었던 페이지까지 사용자에게 제공해 줄 수 있다는 장점을 갖는다.true
옵션은 'blocking'
옵션과 달리, paths
에 없는 경로에 대해 props
가 없는 버전의 페이지를 우선적으로 반환하여, 사용자에게 즉시 기본적인 레이아웃을 보여주고, 백그라운드에서 필요한 데이터를 받아와 화면을 업데이트한다.
// src/pages/book/[id].tsx
export const getStaticPaths = () => {
return {
paths: [
{params: {id: "1"}},
{params: {id: "2"}},
{params: {id: "3"}}
],
fallback: true,
};
};
이때 기본 컴포넌트를 렌더링한 후getStaticProps
가 데이터를 받아오면 페이지를 업데이트하게 된다.
그래서 이렇게 fallback
을 true
로 설정해 주게 되면 우리가 빌드 타임에 생성해 놓지 않은 페이지를 앞서 살펴본 'blocking'
옵션처럼 그대로 제공할 수 있으면서도 동시에 일단 사용자에게 긴 로딩시간 대신에 데이터가 없는 버전의 페이지라도 일단은 먼저 보여줄 수 있다는 장점이 존재하는 옵션이다.
참고로 페이지 컴포넌트가 아직 서버로부터 데이터를 전달받지 못한 상태를
fallback 상태
라고 한다.
페이지 컴포넌트가 fallback
상태에 빠져있을 때에만 "로딩중입니다"라는 텍스트를 렌더링 하도록 해준다.
페이지 컴포넌트의 로딩 상태를 처리하기 위해 router
의 isFallback
값을 사용하여 데이터가 도착하기 전 로딩 상태를 처리할 수 있다.
import { useRouter } from "next/router";
export default function Page({ book }: InferGetServerSidePropsType<typeof getStaticProps>) {
const router = useRouter();
if (router.isFallback) return "로딩중입니다";
if (!book) return "문제가 발생했습니다 다시 시도하세요";
return (
<div>
<h1>{book.title}</h1>
<p>{book.description}</p>
</div>
);
}
isFallback
프로퍼티가 true라면 fallback상태라는 뜻이다. 그래서 이때에는 데이터를 기다리는 중이니까 "로딩중입니다"
라고 렌더링 하도록 설정해 준다.
그리고 로딩이 끝났는데도 그때도 데이터가 안 들어온다면 그때는 진짜 오류가 발생한 걸로 취급하고 "문제가 발생했습니다 다시 시도하세요"
라는 텍스트가 렌더링 되도록 한다.
페이지 데이터가 존재하지 않을 경우 404 페이지
로 redirection할 수 있다. 예를 들어, 요청한 book 데이터가 존재하지 않을 경우 getStaticProps
의 notFound
값을 true
로 설정하여 404 페이지
를 반환하도록 한다.
export const getStaticProps = async (context: GetStaticPropsContext) => {
const id = context.params!.id;
const book = await fetchOneBook(Number(id));
if (!book) {
return {
notFound: true,
};
}
return {
props: {
book
}
};
};
페이지에 필요한 데이터를 계산하는 이 getStaticProps
함수 안에 만약 book데이터를 불러왔는데 if 조건문으로 book데이터가 존재하지 않을 경우 이때에는 return으로 notFound
라는 프로퍼티의 값을 true
로 설정해 주면 된다.
그럼 Next 서버가 book데이터를 불러오지 못했을 경우에는 자동으로 404 Not Found
페이지로 페이지를 redirection시켜준다.
이 경우, getStaticProps
에서 book 데이터가 없을 때 바로 404 페이지
를 반환한다.
즉, 서버 측에서 사전 렌더링 시 데이터 유무를 확인하고 데이터가 없으면 클라이언트로 404 페이지를 보내는 방식이다.
이 방식은 클라이언트에서 추가적으로 데이터 확인을 하지 않아도 되기 때문에 간결하고 빠르게 동작한다.
getStaticProps
에서 데이터를 props
로 전달하고, 컴포넌트에서 book 데이터 유무를 확인하여 "문제가 발생했습니다 다시 시도하세요"라는 메시지를 출력한다.
즉, 클라이언트 측에서 데이터 유무를 확인하고 없을 때 오류 메시지를 보여주는 방식이다.
이 방식은 데이터를 직접 확인하여 오류 메시지를 커스터마이징할 수 있다.
notFound: true
옵션을 사용하는 것이 더 간결하고 최적화된 방법으로 보인다. 이 방법은 불필요한 클라이언트 사이드 검사를 줄이고, 데이터가 없을 때 빠르게 404 페이지
로 이동시킨다.
그러나 오류 처리나 로딩 상태 표시가 클라이언트 측에서 필요할 경우에는 두 번째 방식처럼 컴포넌트 내에서 데이터를 검증하는 방식이 유용할 수 있다.
따라서, 두 가지 방식 중 상황에 맞게 하나만 선택하여 사용하는 것이 효율적이다.
fallback
옵션은 동적 경로를 가진 페이지에서 필요한 경로만을 사전 렌더링하되, paths
에 정의되지 않은 경로에 대한 유연한 대응을 가능하게 한다. 'blocking'
옵션은 경로가 존재하지 않을 경우 SSR 방식
으로 페이지를 생성해주며, 이후에는 정적 페이지로 저장해 빠르게 응답할 수 있다. true
옵션은 사용자에게 기본 레이아웃을 먼저 보여주고, 데이터가 준비되는 대로 페이지를 업데이트해 즉각적인 응답과 사용성을 높이는 데 유리하다.
Next.js의
getStaticPaths
와fallback
옵션을 적절히 활용하면, 최적화된SSG
와SSR
방식을 혼합하여 유연하게 페이지를 구성할 수 있다.