(Static Site Generation, 정적 사이트 생성)
서버측에서 페이지를 빌드 타임에 한번만 렌더링 하는 것
... 이후의 hydration과정은 SSR과 같음
SSR에서 SSG로 바꾸기
getServerSideProps
에서 getStaticProps
로만 바꾸면 된다.import { fetchCountries } from "@/api";
export default function Home({ countries }) {
return (
<div>
{countries.map((country) => {
return <div key={country.code}>{country.commonName}</div>;
})}
</div>
);
}
export const getStaticProps = async () => { //👈🏻
console.log("countires 데이터 불러옴"); // 👈🏻참고
const countries = await fetchCountries();
return {
props: {
countries,
},
};
};
참고:
getStaticProps
내부에 있는console.log
찍힘
- 빌드 전 npm run dev에서 작동시킬때는 새로고침을 할때마다 서버측에 내용이 나타나지만,
- 빌드 이후 npm run start로 작동시키면 서버에 나타나지 않는다.
getStaticProps
를 사용해서 만들 수 없다.import { fetchCountry } from "@/api";
import SubLayout from "@/components/SubLayout";
import { useRouter } from "next/router";
export default function Country({ country }) {
// 클라이언트에서 사용
const router = useRouter();
const { code } = router.query;
if (!country) {
return <div>존재하지 않는 국가입니다.</div>;
}
return (
<div>
{country.commonName}
{country.officialName}
</div>
);
}
Country.Layout = SubLayout;
export const getStaticPaths = async () => {
return {
paths: [
//어떤경로가 필요한지 명시
{ params: { code: "ABW" } },
{ params: { code: "KOR" } },
],
fallback: true, // 👈🏻paths에 없는 경로 요청이 오는 경우 처리 옵션 (하단설명참고)
};
};
export const getStaticProps = async (context) => {
// 서버측에서 불러옴
const { code } = context.params;
let country = null;
if (code) {
country = await fetchCountry(code);
}
return {
props: { country },
};
};
존재하지 않는 경로를 요청하는 경우
fallback: false;
: 404페이지
fallback: "blocking";
: 빌드타임에 생성하지 않은 페이지도 실시간으로 생성해서 제공할 수 있다.
- 특징: (짧은) 로딩 시간이 생김
fallback: true;
: 사용자에게 데이터 없는 상태의 페이지를 먼저 보여준 후 데이터를 보냄지정값 외에 경로 요청시 빈 페이지 (존재하지 않는 국가입니다.
)를 먼저 내보냈음을 확인할 수 있다.
그 이후 데이터 값을 보내주었다.
- 특징: blocking 방식에 비해 페이지 자체는 빠르게 렌더링되어 사용자 입장에서는 쾌적한 환경이라고 느낄 수 있다.
참고: router객체를 이용해 현재 페이지가 fallback상태인지 구분 가능
- 컴포넌트 내에 다음 코드 추가
export default function Country({ country }) { const router = useRouter(); const { code } = router.query; if (router.isFallback) { // 👈🏻 return <div>Laoding...</div>; } // ...후략... }
pages/country/[code].js
처럼 동적경로를 갖는다고 생각하고 getStaticPaths
를 사용할 수 없음getStaticPaths
사용 가능getStaticProps
함수 내부에서는 url parameter에 접근가능하지만, qeury string에는 접근 불가※ 클라이언트 사이드에서 직접 불러오기
fetchSearchResults의 값(검색결과)이 굳이 서버측에서 불러올 필요가 없다면 컴포넌트 내부에서 useRouter훅을 통해 query stirng만 가져오고, 컴포넌트가 페이지에 마운트 되었을 때 쿼리값을 가지고 컴포넌트 내부에서 api를 호출하여 state에 보관하는 방법이 있다.
import { fetchSearchResults } from "@/api";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
export default function Search() {
const router = useRouter();
const { q } = router.query;
const [countries, setCountries] = useState([]);
const setData = async () => {
const data = await fetchSearchResults(q); // 👈🏻검색결과 불러오기
setCountries(data);
};
useEffect(() => {
if (q) {
setData();
}
}, [q]);
return (
<div>
{countries.map((country) => {
return <div key={country.code}>{country.commonName}</div>;
})}
</div>
);
}