Series
Next.js 시작하기 - (1) Project setting, Routing
Next.js 시작하기 - (2) CSS-in-JS, Custom App
Next.js 시작하기 - (3) Pre-rendering, Data Fetching
Pre-rendering
기본적으로 next.js는 모든 페이지를 pre-render한다. 이는 각 페이지에 대해 html을 미리 만들어두는 것을 의미한다.
Initial Load 과정에서는 자바스크립트 동작이 없는 html을 먼저 화면에 보여주는데, 아직 js 파일이 로드되기 전이므로 <Link />와 같은 컴포넌트는 동작하지 않는다.
Initial Load에서 html을 로드한 뒤, js 파일을 서버로부터 받아 html을 연결시키는 과정이 일어나는데 이를 Hydration이라고 한다. 해당 과정에서 react 컴포넌트는 초기화되고 사용자와 상호작용할 준비를 마친다.
만약 pre-rendering이 없다면 자바스크립트 전체가 로드되어야 하기 때문에 최초 load에서 사용자에게 아무것도 보여지지 않게된다.
아래는 간단한 예시 코드이다.
pages/counter.tsx
import { useState } from "react";
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<h1>Counter</h1>
<div>{count}</div>
<button onClick={() => setCount((prev) => prev - 1)}>-</button>
<button onClick={() => setCount((prev) => prev + 1)}>+</button>
</div>
);
};
export default Counter;
+, - 버튼을 누르면 숫자가 증가, 감소되는 간단한 카운터이다.
네트워크 탭에서 맨 처음으로 생기는 document를 보면 "__next"라는 id의 div안에 카운터의 초기 값들이 pre-render 되어있는 것을 확인할 수 있다.
(실제로 자바스크립트를 disable해놓고 페이지를 로드하면 버튼은 아무 동작도 하지 않고 html만 존재한다.)
pre-rendering에는 두 가지 형태가 있다.
SSG(Static Site Generation): html을 빌드타임에 생성하고 각 리퀘스트에서 재사용된다.
SSR(Server Side Rendering): html을 각 리퀘스트가 일어날 때마다 생성하는 방식이다.
development mode(npm run dev)에서는 페이지들이 매 요청마다 pre-rendered된다. (개발의 편의를 위해 개발 모드에서는 static generation도 마찬가지로 매 요청마다 pre-render한다.)
각 페이지에 어떤 종류의 pre-rendering을 사용할 지 선택할 수 있다.
공식문서에 따르면 가능한 SSG를 추천한다. 페이지가 한 번에 빌드될 수 있기 때문이다. 이는 모든 리퀘스트마다 페이지가 render되는 것 보다 빠르다.
하지만 만약 유저의 요청 전에 pre-render를 할 수 없는 경우라면 SSR을 쓰는 것이 더 좋을 수도 있다. (ex. 데이터를 자주 업데이트하거나 매 요청마다 콘텐츠가 달라지는 경우 등)
Data Fetching
Next.js에서 데이터를 fetching하는 방법은 총 4가지가 있다.
CSR(Client Side Rendering)
import { useEffect, useState } from "react";
import axios from "axios";
const DateTime = () => {
const [dateTime, setDateTime] = useState("");
useEffect(() => {
axios
.get("https://worldtimeapi.org/api/ip")
.then((res) => setDateTime(res.data.datetime))
.catch((e) => console.error(e));
}, []);
return <div>{dateTime || "불러오는 중 ..."}</div>;
};
export default DateTime;
일반적인 react에서처럼 useEffect를 사용해 data를 fetch해오는 방식이다.
SSR(Server Sider Rendering)
import { GetServerSideProps, InferGetServerSidePropsType } from "next";
import axios from "axios";
const DateTime = ({ dateTime }: InferGetServerSidePropsType<GetServerSideProps>) => {
return <div>{dateTime || "불러오는 중 ..."}</div>;
};
export default DateTime;
export async function getServerSideProps() {
const res = await axios.get("https://worldtimeapi.org/api/ip");
return {
props: {
dateTime: res.data.datetime,
},
};
}
getServerSideProps라는 서버에서 실행되는 async 함수를 사용한다. getServerSideProps라는 비동기함수를 export하면 next는 이 페이지를 빌드타임에 이 함수에서 리턴한 값(위 코드에서 dateTime)을 컴포넌트에 props로 전달한다.
SSG(Static Site Generation)
import axios from "axios";
import { GetStaticProps, InferGetStaticPropsType } from "next";
const DateTime = ({ dateTime }: InferGetStaticPropsType<GetStaticProps>) => {
return <div>{dateTime || "불러오는 중 ..."}</div>;
};
export default DateTime;
export async function getStaticProps() {
const res = await axios.get("https://worldtimeapi.org/api/ip");
return {
props: {
dateTime: res.data.datetime,
},
};
}
getStaticProps라는 async 함수를 사용한다. SSR과 마찬가지로 getStaticProps 함수에서 리턴한 값을 컴포넌트에 props로 전달한다.
이 때 주의할 점은 SSG를 테스트해볼 때는 yarn build를 한 후, yarn start로 실행을 해주어야 한다는 것이다. (이렇게 하지 않으면 새로고침할 때마다 시간이 바뀐다. production 모드로 실행하면 페이지를 reload를 해도 dateTime이 바뀌지 않는 것을 확인할 수 있다.)
ISR(Incremental Static Regeneration)
import { GetStaticProps, InferGetStaticPropsType } from "next";
import axios from "axios";
const DateTime = ({ dateTime }: InferGetStaticPropsType<GetStaticProps>) => {
return <div>{dateTime || "불러오는 중 ..."}</div>;
};
export default DateTime;
export async function getStaticProps() {
const res = await axios.get("https://worldtimeapi.org/api/ip");
return {
props: {
dateTime: res.data.datetime,
},
revalidate: 5,
};
}
ISR은 SSG의 장점을 취하면서 단점을 보완할 수 있도록 만들어진 방식이다.
getStaticProps로 빌드 시 데이터를 받아오되, 일정 시간이 지난 후의 페이지 요청에 대해서는 함수가 다시 실행된다. (일정 시간이 지나기 전에는 SSG로 동작하다가 일정 시간이 지난 후에는 SSR로 동작을 한다고 보면 된다.)
References
Pre-rendering and Data Fetching
[Next.js] Data Fetching을 하는 4가지 방법
'FE > Next.js' 카테고리의 다른 글
Next.js에서 mui 사용하기(TypeScript) (0) | 2022.10.10 |
---|---|
Next.js 시작하기 - (2) CSS-in-JS, Custom App (2) | 2022.09.11 |
Next.js 시작하기 - (1) Project setting, Routing (0) | 2022.09.04 |