Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Archives
Today
Total
관리 메뉴

heyday2024 님의 블로그

Next.js 렌더링 패턴과 구현 방식 본문

프론트엔드 부트캠프

Next.js 렌더링 패턴과 구현 방식

heyday2024 2024. 12. 10. 22:34

 

1. 렌더링 패턴 종류

1. Client-Side Rendering (CSR)

  • 설명: 리액트의 전통적인 방식으로 SPA(Single Page Application)에서 클라이언트 측에서 동적으로 페이지를 렌더링.
  • 장점:
    • 최초 로딩 후 사용자와의 상호작용이 빠르고 부드럽다.
    • 서버 부하가 적고, 서버 요청 없이도 동작 가능.
    • MPA(Multi Page Application)에서 발생했던 깜빡거림 문제를 해결.
  • 단점:
    • 초기 로딩 시간이 길어질 수 있음.
    • SEO 최적화가 어려움(검색 엔진이 CSR을 완전히 지원하지 않는 경우가 있음).

2. Static Site Generation (SSG)

  • 설명: 정적인 페이지를 빌드 타임에 미리 생성하여 제공.
  • 장점:
    • **TTV(Time To View)**가 짧고 SEO 최적화에 유리.
    • CDN 캐싱 가능.
    • 서버 부하가 적음.
  • 단점:
    • 데이터 의존적인 페이지(예: 마이페이지) 구현이 불가능.
    • 빌드 시간이 길어질 수 있음.
    • 정적 페이지이기 때문에 실시간 데이터 갱신이 어려움.

3. Incremental Static Regeneration (ISR)

  • 설명: SSG의 단점을 보완하여, 설정한 주기마다 정적 페이지를 다시 생성.
  • 장점:
    • SSG처럼 빠른 초기 로딩 속도.
    • 일정 시간 간격으로 콘텐츠 업데이트 가능.
    • CDN 캐싱 가능.
  • 단점:
    • 실시간 데이터 업데이트에는 한계.
    • 데이터 의존적인 페이지 구현에는 부적합.

4. Server-Side Rendering (SSR)

  • 설명: 클라이언트의 요청마다 서버에서 HTML을 생성하여 제공.
  • 장점:
    • SEO 최적화 및 실시간 데이터 갱신 가능.
    • 데이터 의존적인 페이지(예: 마이페이지) 구현 가능.
    • 보안성이 높음.
  • 단점:
    • 요청마다 서버 렌더링이 발생하므로 서버 부하 증가.
    • CDN 캐싱이 제한적.

2. 코드 구현

1. SSG (Static Site Generation)

  • Next.js에서 기본 설정으로 동작.
  • HTML은 빌드 타임에 생성되며, 클라이언트 요청 시 정적인 페이지를 제공.
export const getStaticProps = async () => {
  const res = await fetch("http://localhost:4000/products");
  const products = await res.json();

  return {
    props: { products },
  };
};

const Home = ({ products }: { products: Product[] }) => {
  return (
    <div>
      {products.map((product) => (
        <div key={product.id}>
          <h2>{product.title}</h2>
          <p>{product.price.amount}$</p>
        </div>
      ))}
    </div>
  );
};

export default Home;

2. SSR (Server-Side Rendering)

  • **cache: "no-store"**를 설정하여 클라이언트 요청마다 서버에서 데이터를 가져옴.
  • 실시간 데이터가 필요한 경우 적합.
export const getServerSideProps = async () => {
  const res = await fetch("http://localhost:4000/products", {
    cache: "no-store",
  });
  const products = await res.json();

  return {
    props: { products },
  };
};

const Home = ({ products }: { products: Product[] }) => {
  return (
    <div>
      {products.map((product) => (
        <div key={product.id}>
          <h2>{product.title}</h2>
          <p>{product.price.amount}$</p>
        </div>
      ))}
    </div>
  );
};

export default Home;

3. ISR (Incremental Static Regeneration)

  • revalidate를 설정하여 주기적으로 정적 페이지를 갱신.
export const getStaticProps = async () => {
  const res = await fetch("http://localhost:4000/products");
  const products = await res.json();

  return {
    props: { products },
    revalidate: 3, // 3초마다 정적 페이지 갱신
  };
};

const Home = ({ products }: { products: Product[] }) => {
  return (
    <div>
      {products.map((product) => (
        <div key={product.id}>
          <h2>{product.title}</h2>
          <p>{product.price.amount}$</p>
        </div>
      ))}
    </div>
  );
};

export default Home;

4. CSR (Client-Side Rendering)

  • 클라이언트에서 데이터를 가져와 렌더링.
  • 브라우저에서 비동기로 데이터를 요청.
"use client";

import React, { useEffect, useState } from "react";
import { Product } from "../page";

const ProductList = () => {
  const [data, setData] = useState<Product[]>([]);

  useEffect(() => {
    const fetchData = async () => {
      const res = await fetch("http://localhost:4000/products");
      const products = await res.json();
      setData(products);
    };

    fetchData();
  }, []);

  return (
    <div>
      {data.map((product) => (
        <div key={product.id}>
          <h2>{product.title}</h2>
          <p>{product.price.amount}$</p>
        </div>
      ))}
    </div>
  );
};

export default ProductList;

3. 언제 각각의 렌더링 패턴을 사용해야하는지...

CSR 사용자와의 상호작용이 많고, SEO가 덜 중요한 경우
SSG 콘텐츠가 정적이고 자주 변경되지 않는 경우
ISR 콘텐츠가 주기적으로 갱신되고 실시간 반영이 필요하지 않은 경우
SSR 실시간 데이터 갱신과 SEO가 중요한 경우