1. SSG
- 비동기 데이터 fetching
data / products.json에 데이터가 있다고 가정하고
[
{
"id": "1",
"name": "청바지",
"price": "10000"
},
{
"id": "2",
"name": "티셔츠",
"price": "13000"
},
...objects
]
api 폴더의 products.ts 모듈을 만들어 데이터를 가져온다.
import path from "path";
import { promises as fs } from "fs";
export type Product = {
id: string;
name: string;
price: string;
};
export async function getProducts(): Promise<Product[]> {
const filePath = path.join(process.cwd(), "data", "products.json"); //data json 파일의 경로
const data = await fs.readFile(filePath, "utf-8");
return JSON.parse(data); //비동기적으로 파싱해서 object를 리턴해줌
}
export function getProduct(id: string) {
return "shirt";
}
데이터를 읽어오는 컴포넌트
//비동기 !
export default async function ProductsPage() {
const products = await getProducts();
return (
<>
<ul>
{products.map((product, idx) => (
<Link key={idx} href={`/products/${product.id}`}>
<li>{product.name}</li>
</Link>
))}
</ul>
</>
);
}
아이템 컴포넌트 에서 params를 읽어온 후 아이템을 가져오는 getProduct함수 호출
type Props = {
params: {
post: string;
};
};
export function generateMetadata({ params }: Props) {
return {
title: `제품 이름 : ${params.post}`,
};
}
//SSR
export default async function PostPage({ params: { post } }: Props) {
const product = await getProduct(post);
if (!product) {
notFound();
}
return <h1>{product.name} 설명 페이지</h1>;
}
export async function generateStaticParams() {
const products = await getProducts(); //await으로 promise가 끝날때 까지 기다린 후 값을 할당
return products.map(({ id }) => ({
post: id, //[post]에 대응되는 페이지는 id로 라우팅되고 있음
}));
}
2. ISR
1) revalidate 코드 추가
export const revalidate = 3; //3초마다 revalidate
예를 들어 3초마다 변경하길 원하면 해당 컴포넌트들에 위의 코드를 추가해주면된다.
build 하고 start한 뒤, 코드를 변경해보면 리렌더링 후 3초 뒤 변경되는것을 볼 수 있다.
2) fetch의 두번째 인자 next options
export default async function ProductsPage() {
const products = await getProducts();
const res = await fetch("https://meowfacts.herokuapp.com", {
next: { revalidate: 3 }, //3초마다 반영해서 ISR로 만들어줌
});
const data = await res.json();
const fact = data.data[0];
return (
<>
<h1>제품 소개 페이지!</h1>
<ul>
{products.map((product, idx) => (
<Link key={idx} href={`/products/${product.id}`}>
<li>{product.name}</li>
</Link>
))}
</ul>
<article>{fact}</article>
</>
);
}
3. SSR
1) fetch의 두번째 인자 next options
0을 주면 SSR로 만들어 변화가 생기면 바로 반영해준다. (새로고침할 때 마다 반영됨)
...
export default async function ProductsPage() {
const products = await getProducts();
const res = await fetch("https://meowfacts.herokuapp.com", {
// next: { revalidate: 3 }, //3초마다 반영해서 ISR로 만들어줌
next: { revalidate: 0 }, // SSR로 만들어줌!
});
...
SSR로 만들어준다 = 새롭게 html을 만들어준다
2) fetch의 두번째 인자 cache options
cache: "no-store"도 server side rendering처럼 동작한다. cache를 하지 않기 때문에 서버에서 변경되면 그때마다 html을 새로 생성한다.
...
export default async function ProductsPage() {
const products = await getProducts();
const res = await fetch("https://meowfacts.herokuapp.com", {
// next: { revalidate: 3 }, //3초마다 반영해서 ISR로 만들어줌
// next: { revalidate: 0 }, // SSR로 만들어줌!
cache: "no-store",
});
...
4. CSR
동적으로 자주 바뀌지만 페이지에서 중요하지는 않은 내용 -> CSR
혹은 구글맵 AP처럼 동적으로 자주 바뀌는 실시간 데이터일 경우 -> CSR
사용자가 화면에서 지도를 드래그하거나 줌을 조정하는 등의 인터랙션은 클라이언트 사이드에서 처리하는 것이 사용자 경험에 더 좋음
"use client";
import { useEffect, useState } from "react";
export default function MeowArticle() {
const [text, setText] = useState();
useEffect(() => {
const fetchCats = async () => {
const res = await fetch("https://meowfacts.herokuapp.com");
const data = await res.json();
setText(data.data[0]);
};
fetchCats();
}, []);
return <div>{text}</div>;
}
use client로 만들었더니 html에서 사라졌다...!!! 와우 정적인 요소가 지금 없기 때뮨....
정적인 요소를 채워넣고싶다면
const [text, setText] = useState("데이터 준비중!");
데이터 준비중! 텍스트를 디폴트로 추가해보쟈... 그리고 다시 빌드하면
데이터 준비중! 이라는 정적인 데이터를 볼 수 있다. hydration 전까지 이 텍스트가 보이다가 hydration이 완료되면 cat article로 바뀐다. 짱신기
'Computer Programming > Next' 카테고리의 다른 글
Next.js 13 - loading.tsx , error.tsx, 이미지, 폰트 (0) | 2023.08.02 |
---|---|
Next.js 13 - Route Handler (0) | 2023.08.02 |
Next.js - Server Component/ Client Components (0) | 2023.08.01 |
Next.js - Metadata (0) | 2023.08.01 |
Next.js - File Convention :not-found, layout(+Link tag), loading, (0) | 2023.08.01 |