Next.js - 4가지 렌더링 방식 (SSG, SSR, CSR, ISR)
SSG (Server Side Generation)
서버에서 미리 HTML 파일을 만든 다음 브라우저에서 보여주는 형태의 렌더링 방식
`빌드 타임`에 홈페이지를 만들어줌 > `정적 페이지`라서 초기에 한번 페이지를 로드하고 나서는 다시 로드하지 않음
vsCode 상 내용을 바꾸게 되면 다시 빌드를 해줘야함
실행과정
- 아무것도 하지 않아도 됨!! (Next.js는 기본적으로 아무것도 설정하지 않는다면 SSG로 동작)
yarn build && yarn start
빌드, 실행을 하면 아래와 같이 터미널에 뜸

(Static) 이라고 적힌걸 보면 0/ 으로 되어있는 곳이 정적인 페이지로 만들어졌다는 이야기이다.
서버 컴포넌트에서는 데이터를 불러올 때 useEffect등을 이용하지 않아도 됨
비동기 함수를 직접 사용할 수 있음!!
Next.js에서는 Fetch API를 통해서 최적화를 하고 있음 (Axios 사용 보다는 Fetch API사용하기!!)
export default async function Home() {
const res = await fetch("http://localhost:4000/products");
const data: Product[] = await res.json();
return (
<>
<div>
<div className="p-8 m-4">
{data.map((product) => (
<div className="flex border p-4 gap-4 rounded-md" key={product.id}>
<img
className="rounded-smr"
width={150}
height={150}
src={product.images}
alt={product.title}
/>
<div className="flex flex-col justify-between">
<div>
<h2 className="text-xl font-bold">{product.title}</h2>
<p className="text-sm">{product.description}</p>
<p className="mt-4 text-2xl">{product.price.amount}$</p>
</div>
</div>
</div>
))}
</div>
</div>
</>
);
}
export type Product = {
id: number;
handle: string;
availableForSale: boolean;
isNew: boolean;
title: string;
description: string;
descriptionHtml: string;
options: {
name: string;
values: string[];
}[];
price: {
amount: string;
currencyCode: string;
};
images: string;
seo: {
title: string;
description: string;
};
tags: string[];
rating: number;
};

SSR(Server-Side-rendering)
사용자가 웹사이트에 접속을 하려고 시도 할 때마다 새로 콘텐츠를 불러와서 보여주는 렌더링 방식
(유저가 요청 할 때 마다)
사용방법
fetch 부분에 옵션만 추가하면 됨
export default async function Home() {
const res = await fetch("http://localhost:4000/products", {
cache: "no-store",
});
const data: Product[] = await res.json();
console.log("렌더링 완료");
return (
<>
<div>
...
}


추가를 하게 되면 빌드를 했을 때, `0/ Static`으로 되어있던게 `f/ Dynamic`으로 변경되어있음
새로고침을 할 때 마다 렌더링이 되고 있음
서버 사이드 제너레이션
간단하게 옵션을 `force-cache`로 변경해주면 됨 / 기본이기에 안적도 됨
const res = await fetch("http://localhost:4000/products", {
cache: "force-cache",
});
const data: Product[] = await res.json();
console.log("렌더링 완료");
클라이언트 사이드 렌더링
`"use client"` 사용이 필수!!
_components 폴더에 컴포넌트를 만들고 나서 흔히 리액트에서 사용하던 식으로 사용하면 됨
// componenet > ProductList.tsx
import React, { useEffect, useState } from "react";
import { Product } from "../page";
const ProductList = () => {
const [data, setData] = useState<Product[]>([]);
const fetchData = async () => {
const res = await fetch("http://localhost:4000/products");
const data: Product[] = await res.json();
return data;
};
useEffect(() => {
console.log("렌더링");
fetchData().then(setData);
}, []);
return (
<div className="p-8 m-4">
{data.map((product) => (
<div className="flex border p-4 gap-4 rounded-md" key={product.id}>
<img
className="rounded-smr"
width={150}
height={150}
src={product.images}
alt={product.title}
/>
<div className="flex flex-col justify-between">
<div>
<h2 className="text-xl font-bold">{product.title}</h2>
<p className="text-sm">{product.description}</p>
<p className="mt-4 text-2xl">{product.price.amount}$</p>
</div>
</div>
</div>
))}
</div>
);
};
export default ProductList;
//page.tsx
export default async function Home() {
return (
<>
<div>
<ProductList />
</div>
</>
);
}

서버가 아닌 클라이언트에서 console이 찍히는걸 볼 수 있음
ISR (Incremental Static Regeneration) - 정적 증분 방식
특정 타입에 맞춰서 특정 타임에만 렌더링 다시 되도록 하는 SSG와 SSR이 섞여있는 방식
fetch에 next 옵션을 추가
revalidate라는 키에 들어간 값은 초 단위로 들어감
const fetchData = async () => {
const res = await fetch("http://localhost:4000/products", {
next: {
revalidate: 3,
},
});
const data: Product[] = await res.json();
return data;
};

fetch의 옵션값인 next, cache 이 두 설정값과 "use client" 이 세가지만 알면
원하는 데 적재적소로 사용 가능