주요 렌더링 패턴 4가지 (SSG, SSR, ISR, CSR)

하영·2024년 9월 26일
0

Next.js

목록 보기
2/19

주요 렌더링 패턴 4가지

01. SSG (Server Side Generation) 👩🏻‍💻

: 서버에서 미리 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>;
}

두번째 방법은 fetchforce-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 정적인 데이터가 불러와졌고 브라우저에서 확인해보면

역시 잘 불러와지는 것을 볼 수 있다.


02. SSR(Server Side Rendering)👩🏻‍💻

: 사용자가 웹사이트에 접속을 하려고 시도를 할 때마다 새로 콘텐츠를 불러와서 보여주는 방식

//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 또한 잘 나타나는걸 볼 수 있다.


03. CSR(Client Side Rendering) 👩🏻‍💻

: 요청이 있을 때 마다 지속해서 갱신해준다.

⭐️ 클라이언트 환경에서 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” 를 적어준 후 클라이언트 로직을 사용해야하는 곳에 훅 , 이벤트 헨들러같은 클라이언트 코드를 작성해주면 된다.


04. ISR (Incremental Static Regeneration)👩🏻‍💻

: 주어진 시간에 한 번씩 갱신된다.

//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 = {
  // 생략
};

✅ 결과 확인

🔍 fetch에 어떤 옵션을 주는가!, use client를 사용하는가! 에 달려있다

  • SSG : 1) 아무것도 쓰지 않거나 2)force-cache 옵션 주기
  • SSR : cache: “no-store” 옵션 주기
  • ISR : next : {revalidate : 값} 옵션 주기
  • CSR :use client 옵션 준 후 클라이언트 로직 적어주기

+ 작업 시 알아둘 것 👩🏻‍💻

yarn build && yarn start 할 때 vscode에서 .next 파일 지워서 캐싱된 데이터 지우고 확인해야 정확하게 체크할 수 있다.

profile
왕쪼랩 탈출 목표자의 코딩 공부기록

0개의 댓글