[Next.js] SSG, SSR, ISR, CSR

조아영·2024년 9월 27일

📌

4가지 주요 렌더링 기법을 Next.js에서 이해하는 것은 매우 중요합니다. 각각의 렌더링 방식은 성능과 사용자 경험에 영향을 미치기 때문에, 프로젝트의 요구사항에 맞게 선택하는 것이 필요합니다.

◼ SSG(정적 사이트 생성, Static Site Generation) : Pre-Rendering (Static)

SSG는 빌드 시점에 미리 페이지를 생성하여 HTML 파일로 저장합니다. 서버 요청이 들어올 때마다 HTML을 즉시 제공할 수 있으므로 매우 빠릅니다.

  • 사용 예시 : 콘텐츠가 자주 변하지 않는 블로그나 문서 사이트에 적합합니다.
  • 특징 : 데이터를 빌드 시점에만 가져오며, 페이지는 변경되지 않습니다.

예시

계속 새로고침을 하여도 동일한 페이지만 출력됩니다.

import { Posts } from "../../../types";

const SSGPage = async () => {
    // Next.js는 axios보다는 fetch를 권장하고 있음
    // 첫 번째 방법 : fetch에 아무 옵션을 주지 않기
    const response = await fetch("http://localhost:4000/posts");
    // 두 번째 방법 : fetch에 force-cache 옵션 주기
    const response = await fetch("http://localhost:4000/posts", { 
        cache: "force-cache"
    });
    
    const data: Posts[] = await response.json();
    console.log("render");

    return (
        <>
            <div>
                Next.js는 기본적으로 정적 사이트 생성(SSG)로 동작하며, 별도의 설정 없이 SSG를 사용할 수 있다.
                <br />
                Next.js는 각 페이지를 빌드 시 HTML로 미리 생성하여 저장하고, <br />
                요청이 들어올 때 서버에서 이 HTML 파일을 제공하는 방식으로 작동한다.
            </div>
            <br />
            {data.map((post) => (
                <div key={post.id}>
                    <div>id: {post.id}</div>
                    <div>title: {post.title}</div>
                    <div>author: {post.author}</div>
                </div>
            ))}
        </>
    );
};

export default SSGPage;

◼ SSR(서버 사이드 렌더링, Server Side Rendering) : Pre-Rendering (Dynamic)

SSR은 요청이 있을 때마다 서버에서 페이지를 생성하고 데이터를 제공하는 방식입니다. 매번 최신 데이터를 제공할 수 있지만, 서버에서 매번 처리해야 하므로 응답 속도가 느릴 수 있습니다.

  • 사용 예시: 사용자별로 동적으로 변경되는 콘텐츠가 많은 페이지나 실시간 정보가 필요한 서비스에 적합합니다.
  • 특징: 각 요청 시 페이지가 생성되며, 실시간 데이터를 제공합니다.

예시

요청이 있을 때 마다 계속 갱신됩니다.

import { Posts } from "../../../types";

const SSRPage = async () => {
	// 방법 : fetch에 옵션 주기
    const response = await fetch("http://localhost:4000/posts", {
        cache: "no-store",
    });
    const data: Posts[] = await response.json();
    console.log("render");

    return (
        <>
            <div>
                서버 사이드 렌더링(SSR)은 페이지 요청 시 서버에서 실시간으로 HTML을 생성해 클라이언트에 전달하는
                방식이다.
                <br />
                주로 동적 데이터가 필요할 때 사용되며,한요청 시마다 최신 데이터를 반영한 페이지를 제공한다.
            </div>
            <br />
            {data.map((post) => (
                <div key={post.id}>
                    <div>id: {post.id}</div>
                    <div>title: {post.title}</div>
                    <div>author: {post.author}</div>
                </div>
            ))}
        </>
    );
};

export default SSRPage;

◼ ISR(증분 정적 재생성, Incremental Static Regeneration)

ISR은 SSG의 한계를 보완하는 방식으로, 지정된 시간마다 페이지를 재생성하여 새로운 데이터를 반영할 수 있습니다.

  • 사용 예시: 자주 변경되지는 않지만, 업데이트가 필요한 페이지에서 유용합니다. 예를 들어, 이벤트 목록이나 상품 정보 페이지.
  • 특징: 특정 시간이 지난 후 요청이 들어오면 페이지를 다시 생성하여 최신 데이터를 반영합니다.

예시

주어진 시간마다 한 번씩 갱신됩니다.

import { Posts } from "../../../types";

const ISRPage = async () => {
    const response = await fetch("http://localhost:4000/posts", {
		// 방법 : fetch에 옵션 주기
        next: {
            revalidate: 3,
        },
    });
    const data: Posts[] = await response.json();
    console.log("render");

    return (
        <>
            <div>
                증분 정적 재생성(ISR)은 정적 페이지를 생성한 후 일정 간격으로 재생성하여 최신 데이터를 반영하는
                방식으로, <br />
                SSGSSR의 장점을 결합한 Next.js의 렌더링 방법이다.
            </div>
            <br />
            {data.map((post) => (
                <div key={post.id}>
                    <div>id: {post.id}</div>
                    <div>title: {post.title}</div>
                    <div>author: {post.author}</div>
                </div>
            ))}
        </>
    );
};

export default ISRPage;

◼ CSR(클라이언트 사이드 렌더링, Client Side Rendering) : use client

CSR은 모든 렌더링을 클라이언트(브라우저)에서 처리하며, 서버에서는 빈 HTML 파일만 전송합니다. JavaScript가 로드된 후에 데이터가 불러와지고 페이지가 렌더링됩니다.

  • 사용 예시: 사용자 인터랙션이 많은 SPA(Single Page Application)에 적합합니다.
  • 특징: 초기 로딩이 느릴 수 있지만, 이후에는 빠르게 동작하며, 클라이언트 측에서 로딩 상태를 처리할 수 있습니다.

예시

요청이 있을 때 마다 계속 갱신됩니다.

import PostList from "../_components/PostList";

const CSRPage = async () => {
    return (
        <>
            <div>
                클라이언트 사이드 렌더링(CSR)은 브라우저에서 JavaScript로 모든 페이지를 렌더링하고, <br />
                서버는 기본 HTML과 스크립트만 전달하는 방식이다.
            </div>
            <br />
            <PostList />
        </>
    );
};

export default CSRPage;

// PostList.tsx
// 방법 : "use client" 옵션 주기
"use client";

import React, { useEffect, useState } from "react";
import { Posts } from "../../../types";

const fetchData = async () => {
    const response = await fetch("http://localhost:4000/posts");
    const data: Posts[] = await response.json();

    return data;
};

const PostList = () => {
    const [data, setData] = useState<Posts[]>([]);

    useEffect(() => {
        console.log("render");
        fetchData().then(setData);
    }, []);

    return (
        <>
            {data.map((post) => (
                <div key={post.id}>
                    <div>id: {post.id}</div>
                    <div>title: {post.title}</div>
                    <div>author: {post.author}</div>
                </div>
            ))}
        </>
    );
};

export default PostList;

차이점

  • SSG : 빌드 시점에 페이지가 고정되어 업데이트가 필요 없는 정적인 콘텐츠에 적합합니다.
  • SSR : 매번 새로운 데이터를 제공하므로, 실시간 데이터가 필요한 서비스에 적합합니다.
  • ISR : 일정 시간이 지난 후 재생성이 가능하여, 자주 변경되지 않는 콘텐츠에 적합합니다.
  • CSR : 클라이언트에서 렌더링을 처리하며, 초기 로딩이 느리지만 이후 빠르게 작동합니다.

특징 정리

  • SSG : 빠른 응답 속도, 정적인 콘텐츠에 적합.
  • SSR : 실시간 데이터 제공, 서버 부하가 클 수 있음.
  • ISR : 주기적인 업데이트, 자주 변하지 않는 콘텐츠에 적합.
  • CSR : 클라이언트에서 상태 관리 및 렌더링, 사용자 인터랙션이 많은 페이지에 적합.

0개의 댓글