ISR / SSR / SSG
기본적으로 fetch는 Web API임. 하지만, 리액트18버전에서 fetch를 nodeJS 기반에서도 사용가능하도록 하였음.
React 18 버전에서 서버 컴포넌트에서도 fetch를 사용할 수 있도록 구현해둠.
바로 fetch를 사용해보도록 하자.
import { getProducts } from "@/service/products";
import Link from "next/link";
import styles from "./page.module.css";
// export const revalidate = 3;
export default async function ProductsPage() {
const products = await getProducts();
const res = await fetch("https://meowfacts.herokuapp.com", {
next: { revalidate: 0 }, // 0일 경우 SSR 이 됨.
});
const data = await res.json();
const factText = data.data[0];
return (
<>
<h1>제품 소개 페이지</h1>
<ul>
{products.map((p, i) => (
<li key={i}>
<Link href={`/products/${p.id}`}>{p.name}</Link>
</li>
))}
</ul>
<article className={styles.article}>{factText}</article>
</>
);
}
TypeScript
복사
src/app/products/page.tsx
.article {
font-size: 1.5rem;
margin: 4px;
padding: 8px;
background-color: darkcyan;
}
JavaScript
복사
src/app/products/page.module.css
fetch
fetch의 두번째 인자로, 특정 설정이 가능하다.
예시로 아래와 같이 작성할 경우, next에서 ISR 혹은 SSR로 사용을 할 수 있다.
ISR의 경우 0보다 큰 숫자를 적으면 되고,
SSR의 경우 0을 기입하면 된다.
fetch('https://...', {
next: { revalidate: number}
}
JavaScript
복사
cache
요청한 데이터를 기본적으로 next에서 캐싱을 하고 있는데, 이부분도 cache에 대한 옵션으로 수정이 가능하다.
예시)
// 'force-cache' is the default, and can be omitted
fetch('https://...', { cache: 'force-cache' })
JavaScript
복사
참고로, cache 상태가 ‘force-cache’ 여도 revalidate가 설정이 되어있다면, 해당 캐시를 제거하고 최신 데이터를 가져온다.
캐시 옵션은 다음과 같다.
•
default: 기본적인 브라우저 캐싱 규칙을 따름. 브라우저가 요청과 응답을 캐싱하는 방식을 자동으로 처리함.
•
force-cache (SSG): 요청을 보낼 때 항상 캐시를 사용. 브라우저 캐시에 유효한 응답이 있는 경우 해당 응답을 반환하고, 캐시가 없는 경우에만 네트워크를 통해 요청.
•
no-cache: 캐시된 응답을 사용하지 않고 항상 서버에 요청을 보냄. 서버는 요청에 대한 응답을 캐시할 수 있지만, 응답을 캐시해도 브라우저는 캐시를 사용하지 않고 서버로부터 새로운 응답을 받는다.
•
no-store (SSR): 요청과 응답을 캐시하지 않는다. 매 요청마다 항상 네트워크를 통해 데이터를 가져온다.
•
only-if-cached: 오직 브라우저 캐시에서만 응답을 가져온다. 캐시에 저장된 응답이 없는 경우, 네트워크 요청을 하지 않고 실패함.
•
reload: 캐시된 응답을 무시하고 항상 서버로부터 새로운 응답을 가져온다. 브라우저는 요청을 캐시하거나 캐시된 응답을 사용하지 않는다.
CSR
1.
components 폴더 하위에 fetch를 활용한 데이터를 받은 컴포넌트를 격리한다.
왜냐하면, page는 서버컴포넌트이기 때문.
"use client";
import { useEffect, useState } from "react";
import styles from "./MeowArticle.module.css";
export default function MeowArticle() {
const [text, setText] = useState("데이터 준비중");
useEffect(() => {
fetch("https://meowfacts.herokuapp.com")
.then((res) => res.json())
.then((res) => setText(res.data[0]));
}, []);
return <article className={styles.article}>{text}</article>;
}
JavaScript
복사
src/app/components/MeowArticle.tsx
.article {
font-size: 1.5rem;
margin: 4px;
padding: 8px;
background-color: darkcyan;
}
JavaScript
복사
src/app/components/MeowArticle.module.css
2.
기존 page 하위의 코드를 지우거나, 주석처리하고, 위에 만든 컴포넌트를 추가한다.
import { getProducts } from "@/service/products";
import Link from "next/link";
import MeowArticle from "../components/MeowArticle";
export default async function ProductsPage() {
const products = await getProducts();
return (
<>
<h1>제품 소개 페이지</h1>
<ul>
{products.map((p, i) => (
<li key={i}>
<Link href={`/products/${p.id}`}>{p.name}</Link>
</li>
))}
</ul>
<MeowArticle />
</>
);
}
JavaScript
복사
src/app/products/page.tsx
참고
•
전체 data-fetching : https://nextjs.org/docs/app/building-your-application/data-fetching