주요 렌더링 패턴 4가지
: 서버에서 미리 html 파일을 만든 다음에 브라우저에서 보여지는 방식
: build 타임에 생성해준다.
//SSG
//기본적으로 SSG로 실행됨
export default async function Home() {
const res = await fetch("http://localhost:4000/products");
//fetch도 아무것도 설정하지 않으면 기본적으로 SSG로 동작
const data = await res.json();
console.log(data);
return <div>Next.js 입니다.</div>;
}
SSG
설정하는 방법은 2가지인데 하나는 위 코드처럼 fetch
에 아무 옵션을 주지 않는 방법이다.
//SSG
//기본적으로 SSG로 실행됨
export default async function Home() {
const res = await fetch("http://localhost:4000/products",
**{cache: "force-cache"});**
const data = await res.json();
console.log(data);
return <div>Next.js 입니다.</div>;
}
두번째 방법은 fetch
에 force-cache
옵션을 주는 방식이다.
✅ console.log 확인
조금 더 확실하게 알아보기 위해 Product라는 컴포넌트와 typescript를 작성해서 확인해보자.
//SSG
export default async function Home() {
const res = await fetch("http://localhost:4000/products");
const data: Product[] = await res.json();
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>
);
}
//Product type 설정
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;
};
이번에도 역시 Static
정적인 데이터가 불러와졌고 브라우저에서 확인해보면
역시 잘 불러와지는 것을 볼 수 있다.
: 사용자가 웹사이트에 접속을 하려고 시도를 할 때마다 새로 콘텐츠를 불러와서 보여주는 방식
//SSR
//사용자가 웹사이트에 접속할 때마다 콘텐츠 가져옴
export default async function Home() {
const res = await fetch("http://localhost:4000/products", {
cache: "no-store", // user가 요청할 때마다 실행
});
const data: Product[] = await res.json();
console.log("render"); //render 시점 확인
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>
);
}
//Product type 설정
export type Product = {
// 생략
};
fetch
뒤에 옵션으로 cache: "no-store"
를 적어주면 요청이 있을 때마다 갱신해서 데이터를 보여준다.
✅ Terminal 확인
이 페이지가 Dynamic 동적으로 바뀌게 되었고 콘솔을 확인해보면,
render 또한 잘 나타나는걸 볼 수 있다.
: 요청이 있을 때 마다 지속해서 갱신해준다.
⭐️ 클라이언트 환경에서 console 결과를 확인할 수 있다는 점!
→ “use client”
옵션을 적어준 후 코드를 작성해야한다는 것!
//src/app/component/ProductList.tsx
"use client";
import React, { useEffect, useState } from "react";
import { Product } from "../page";
const fetchData = async () => {
const res = await fetch("http://localhost:4000/products");
const data: Product[] = await res.json();
return data;
};
const ProductList = () => {
const [data, setData] = useState<Product[]>([]); //return문에서 받아서 쓸 data 불러오기
useEffect(() => { //useEffect 안에서 새로 fetchData를 불러서 setData
console.log("render"); //Terminal에서 뜨지 않고 브라우저(클라이언트)에서 콘솔 확인이 됨
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;
Home 컴포넌트 수정
//SSR
//사용자가 웹사이트에 접속할 때마다 콘텐츠 가져옴
import ProductList from "./component/ProductList";
export default async function Home() {
return (
<div>
<ProductList />
</div>
);
}
//Product type 설정
export type Product = {
// 생략
};
✅ console.log 확인
클라이언트 환경에서 콘솔을 확인할 수 있다.
CSR은 “use client”
를 적어준 후 클라이언트 로직을 사용해야하는 곳에 훅 , 이벤트 헨들러같은 클라이언트 코드를 작성해주면 된다.
: 주어진 시간에 한 번씩 갱신된다.
//ISR
export default async function Home() {
const res = await fetch("http://localhost:4000/products", {
**next: {
revalidate: 3, // 3초마다 렌더링
},**
});
const data: Product[] = await res.json();
console.log("render");
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>
);
}
//Product type 설정
export type Product = {
// 생략
};
✅ 결과 확인
force-cache
옵션 주기cache: “no-store”
옵션 주기next : {revalidate : 값}
옵션 주기use client
옵션 준 후 클라이언트 로직 적어주기+ 작업 시 알아둘 것 👩🏻💻
yarn build && yarn start
할 때 vscode에서 .next
파일 지워서 캐싱된 데이터 지우고 확인해야 정확하게 체크할 수 있다.