기본적으로 Next.js는 모든 페이지를 사전 렌더링합니다. 즉, Next.js는 클라이언트 측 JavaScript에서 모든 작업을 수행하는 대신 미리 각 페이지에 대한 HTML을 생성합니다. 사전 렌더링을 통해 더 나은 성능과 SEO를 얻을 수 있습니다.
생성된 각 HTML은 해당 페이지에 필요한 최소한의 JavaScript 코드와 연결됩니다. 페이지가 브라우저에 의해 로드되면 해당 JavaScript 코드가 실행되어 페이지가 완전히 상호 작용하도록 합니다. (이 과정을 hydration이라 합니다.)



중요한 점은 Next.js를 사용하면 각 페이지에 사용할 사전 렌더링 양식을 선택할 수 있다는 것입니다. 대부분의 페이지에는 정적 생성을 사용하고 다른 페이지에는 서버측 렌더링을 사용하여 "하이브리드" Next.js 앱을 만들 수 있습니다.
페이지를 한 번 빌드하고 CDN에서 제공할 수 있으므로 가능한 한 정적 생성(데이터 포함 및 제외)을 사용하는 것이 좋습니다. 이렇게 하면 요청이 있을 때마다 서버에서 페이지를 렌더링하는 것보다 훨씬 빠릅니다.
You can use Static Generation for many types of pages, including:
"사용자 요청에 앞서 이 페이지를 미리 렌더링할 수 있습니까?"라고 스스로에게 물어봐야 합니다. 대답이 예인 경우 정적 생성을 선택해야 합니다.
반면에 정적 생성은 사용자 요청보다 먼저 페이지를 미리 렌더링할 수 없는 경우 좋은 생각이 아닙니다. 페이지에 자주 업데이트되는 데이터가 표시되고 페이지 콘텐츠가 모든 요청에서 변경될 수 있습니다.
이 경우 서버 측 렌더링을 사용할 수 있습니다. 속도는 느려지지만 미리 렌더링된 페이지는 항상 최신 상태입니다. 또는 사전 렌더링을 건너뛰고 클라이언트 측 JavaScript를 사용하여 자주 업데이트되는 데이터를 채울 수 있습니다.
일부 페이지의 경우 일부 외부 데이터를 먼저 가져오지 않고는 HTML을 렌더링하지 못할 수 있습니다. 파일 시스템에 액세스하거나 외부 API를 가져오거나 빌드 시 데이터베이스를 쿼리해야 할 수 있습니다. Next.js는 이 경우(데이터를 사용한 정적 생성)를 즉시 지원합니다.

getStaticProps는 프로덕션에서 빌드 시 실행되며…
함수 내에서 외부 데이터를 가져와 페이지에 대한 소품으로 보낼 수 있습니다.
export default function Home(props) { ... }
export async function getStaticProps() {
// Get external data from the file system, API, DB, etc.
const data = ...
// The value of the `props` key will be
// passed to the `Home` component
return {
props: ...
}
}
기본적으로 getStaticProps를 사용하면 Next.js에 다음과 같이 알릴 수 있습니다.
"이 페이지에는 약간의 데이터 종속성이 있습니다. 따라서 빌드 시 이 페이지를 사전 렌더링할 때 먼저 해결해야 합니다!"
참고: 개발 모드에서는 getStaticProps가 각 요청에서 실행됩니다.
데이터를 getStaticProps를 사용하여 props에 넣어주면 props로 사용가능
import { getSortedPostsData } from '../lib/posts';
export async function getStaticProps() {
const allPostsData = getSortedPostsData();
return {
props: {
allPostsData,
},
};
}
export default function Home ({ allPostsData }) { ... }

export async function getSortedPostsData() {
// fetch post data from an external API endpoint
const res = await fetch('..');
return res.json();
}
데이터베이스를 직접 쿼리할 수도 있습니다.
import someDatabaseSDK from 'someDatabaseSDK'
const databaseClient = someDatabaseSDK.createClient(...)
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from a database
return databaseClient.query('SELECT posts...')
}
이는 getStaticProps가 서버 측에서만 실행되기 때문에 가능합니다. 클라이언트 측에서는 실행되지 않습니다. 브라우저용 JS 번들에도 포함되지 않습니다. 즉, 브라우저로 보내지 않고도 직접 데이터베이스 쿼리와 같은 코드를 작성할 수 있습니다.
빌드 시 실행되도록 되어 있기 때문에 쿼리 매개 변수 또는 HTTP 헤더와 같이 요청 시에만 사용할 수 있는 데이터를 사용할 수 없습니다.
getStaticProps는 페이지에서만 내보낼 수 있습니다. 페이지가 아닌 파일에서는 내보낼 수 없습니다.
이 제한의 이유 중 하나는 페이지가 렌더링되기 전에 React에 필요한 모든 데이터가 있어야 하기 때문입니다.
정적 생성은 빌드 시 한 번 발생하므로 자주 업데이트되거나 사용자 요청마다 변경되는 데이터에는 적합하지 않습니다. 이와 같이 데이터가 변경될 가능성이 있는 경우 서버 측 렌더링을 사용할 수 있습니다. 다음 섹션에서 서버 측 렌더링에 대해 자세히 알아보겠습니다.
요청 시 데이터 가져오기
빌드 시간이 아닌 요청 시간에 데이터를 가져와야 하는 경우 서버 측 렌더링을 시도할 수 있습니다.

서버 측 렌더링을 사용하려면 페이지에서 getStaticProps 대신 getServerSideProps를 내보내야 합니다.
export async function getServerSideProps(context) {
return {
props: {
// props for your component
},
};
}
요청 시 getServerSideProps가 호출되기 때문에 해당 매개변수(컨텍스트)에는 요청별 매개변수가 포함됩니다.
요청 시 데이터를 가져와야 하는 페이지를 미리 렌더링해야 하는 경우에만 getServerSideProps를 사용해야 합니다. 첫 번째 바이트까지의 시간(Time to First Byte, TTFB)는 서버가 모든 요청에서 결과를 계산해야 하고 추가 구성 없이 CDN에서 결과를 캐시할 수 없기 때문에 getStaticProps보다 느립니다.
데이터를 미리 렌더링할 필요가 없는 경우 클라이언트 렌더링을 사용할 수도 있습니다.

이 접근 방식은 예를 들어 사용자 대시보드 페이지에 적합합니다. 대시보드는 비공개의 사용자별 페이지이므로 SEO와 관련이 없으며 페이지를 미리 렌더링할 필요가 없습니다. 데이터는 자주 업데이트되므로 요청 시 데이터를 가져와야 합니다.
Next.js 팀은 SWR이라는 데이터 가져오기를 위한 React 후크를 만들었습니다. 클라이언트 측에서 데이터를 가져오는 경우 이를 적극 권장합니다. 캐싱, 재검증, 포커스 추적, 일정 간격으로 다시 가져오기 등을 처리합니다. 여기서는 자세한 내용을 다루지 않지만 다음은 사용 예입니다.
import useSWR from 'swr';
function Profile() {
const { data, error } = useSWR('/api/user', fetch);
if (error) return <div>failed to load</div>;
if (!data) return <div>loading...</div>;
return <div>hello {data.name}!</div>;
}