๐Ÿ“– TIL - Next.js์˜ ๋ Œ๋”๋ง ๋ฐฉ์‹ ์ด์ •๋ฆฌ: CSR, SSR, ISR, SSG

์Š˜ยท2025๋…„ 3์›” 7์ผ

๐Ÿ“– TIL

๋ชฉ๋ก ๋ณด๊ธฐ
71/90

์˜ค๋Š˜์€ Next.js์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” 4๊ฐ€์ง€ ๋ Œ๋”๋ง ๋ฐฉ์‹์— ๋Œ€ํ•ด ์•Œ์•„๋ดค๋‹ค. ๊ฐ ๋ฐฉ์‹์ด ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ์ง€, ์–ด๋–จ ๋•Œ ์“ฐ๋ฉด ์ข‹์€์ง€, ๊ทธ๋ฆฌ๊ณ  ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ์–ด๋–ป๊ฒŒ ํ…Œ์ŠคํŠธํ•˜๋Š”์ง€ ์ •๋ฆฌํ–ˆ๋‹ค.

๐Ÿ“Œ 1. CSR (Client-Side Rendering)

CSR์€ ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
์ฒ˜์Œ์— ๋นˆ HTML์„ ๋ฐ›์•„์˜จ ๋‹ค์Œ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ API๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ๊ทธ๋ž˜์„œ ์ฒ˜์Œ์—” ๋นˆ ํ™”๋ฉด์ด ๋ณด์ด๋‹ค๊ฐ€ ๋‚˜์ค‘์— ๋ฐ์ดํ„ฐ๊ฐ€ ์ฑ„์›Œ์ง€๋Š” ๊ฒฝํ—˜์„ ํ•˜๊ฒŒ ๋œ๋‹ค.

๊ตฌํ˜„ ์ฝ”๋“œ

"use client";
import React from "react";
import PostListPage from "../components/PostListPage";

const page = () => {
  return (
    <>
      <h1>CSRPage</h1>
      <PostListPage />
    </>
  );
};

export default page;

ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•

  1. ๊ฐœ๋ฐœ์ž ๋„๊ตฌ(F12) ์—ด๊ณ  Network ํƒญ ํ™•์ธํ–ˆ๋‹ค
  2. Disable Cache ์ฒดํฌํ•˜๊ณ  ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจํ–ˆ๋‹ค
  3. HTML ์†Œ์Šค ๋ณด๊ธฐ(Ctrl+U) ํ•ด๋ณด๋‹ˆ ๋ฐ์ดํ„ฐ ์—†์ด ๋น„์–ด์žˆ์—ˆ๋‹ค
  4. Network ํƒญ์—์„œ ๋ฐ์ดํ„ฐ ์š”์ฒญ์ด ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)์—์„œ ์ด๋ฃจ์–ด์ง€๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค

์ ํ•ฉํ•œ ์‚ฌ์šฉ ์ผ€์ด์Šค

์‚ฌ์šฉ์ž ๋Œ€์‹œ๋ณด๋“œ์ฒ˜๋Ÿผ ๊ฐœ์ธํ™”๋œ ํŽ˜์ด์ง€
SEO๊ฐ€ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ํŽ˜์ด์ง€
๋งŽ์€ ์ƒํ˜ธ์ž‘์šฉ์ด ํ•„์š”ํ•œ ํŽ˜์ด์ง€


๐Ÿ“Œ 2. SSR (Server-Side Rendering)

SSR์€ ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ HTML์„ ์™„์„ฑ์‹œํ‚จ ๋‹ค์Œ์— ํด๋ผ์ด์–ธํŠธ์— ๋ณด๋‚ด์ฃผ๋Š” ๋ฐฉ์‹์ด๋‹ค.
๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž๋Š” ์ฒซ ๋กœ๋”ฉ๋ถ€ํ„ฐ ์™„์„ฑ๋œ ํŽ˜์ด์ง€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค!

๊ตฌํ˜„ ์ฝ”๋“œ

import { DEFAULT_POST_URL } from "../constants/postConstant";
import { Post } from "../types/posts";
import PostList from "../components/PostList";

const page = async () => {
  const res = await fetch(`${DEFAULT_POST_URL}/posts`, {
    cache: "no-store",  // ์ด ์˜ต์…˜์ด SSR์˜ ํ•ต์‹ฌ!
  });
  const data: Post[] = await res.json();
  return (
    <>
      <h1>SSRPage</h1>
      <PostList data={data} />
    </>
  );
};

export default page;

์—ฌ๊ธฐ์„œ cache: "no-store" ์˜ต์…˜์ด ์ค‘์š”ํ•˜๋‹ค! ์ด ์˜ต์…˜์€ "์บ์‹œ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ํ•ญ์ƒ ์„œ๋ฒ„์—์„œ ์ตœ์‹  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€!"๋ผ๋Š” ์˜๋ฏธ๋‹ค.

ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•

  1. ๊ฐœ๋ฐœ์ž ๋„๊ตฌ Network ํƒญ ์—ด๊ณ  Disable Cache ์ฒดํฌํ–ˆ๋‹ค
  2. ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจํ–ˆ๋‹ค
  3. HTML ์†Œ์Šค ๋ณด๊ธฐ(Ctrl+U)ํ–ˆ๋”๋‹ˆ ์ด๋ฏธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ์—ˆ๋‹ค!
  4. Network ํƒญ์—์„œ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ถ”๊ฐ€ API ์š”์ฒญ์ด ์—†๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค

์ ํ•ฉํ•œ ์‚ฌ์šฉ ์ผ€์ด์Šค

  • SEO๊ฐ€ ์ค‘์š”ํ•œ ํŽ˜์ด์ง€ (๋ธ”๋กœ๊ทธ, ๋‰ด์Šค ๋“ฑ)
  • ํ•ญ์ƒ ์ตœ์‹  ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ค˜์•ผ ํ•˜๋Š” ํŽ˜์ด์ง€
  • ์ฒซ ๋กœ๋”ฉ ๊ฒฝํ—˜์ด ์ค‘์š”ํ•œ ํŽ˜์ด์ง€

๐Ÿ“Œ 3. ISR (Incremental Static Regeneration)

ISR์€ ์ •์  ํŽ˜์ด์ง€(SSG)์ด์ง€๋งŒ ์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ๋‹ค์‹œ ์ƒ์„ฑ๋˜๋Š” ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ฐฉ์‹์ด๋‹ค.
๋ฏธ๋ฆฌ ์ƒ์„ฑ๋œ ํŽ˜์ด์ง€๋ฅผ ์ œ๊ณตํ•˜๋ฉด์„œ๋„, ์„ค์ •ํ•œ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋Š” ๋ฐฉ์‹์ด๋‹ค!

๊ตฌํ˜„ ์ฝ”๋“œ

import React from "react";
import { DEFAULT_POST_URL } from "../constants/postConstant";
import { Post } from "../types/posts";

const page = async () => {
  const res = await fetch(`${DEFAULT_POST_URL}/posts`, {
    next: {
      revalidate: 20,  // 20์ดˆ๋งˆ๋‹ค ํŽ˜์ด์ง€ ์žฌ์ƒ์„ฑ!
    },
  });

  const data: Post[] = await res.json();
  return (
    <>
      <h1>ISRPage</h1>
      <ul>
        {data.map((e) => (
          <li key={e.id} className="flex flex-col">
            <span>title: {e.title}</span>
            <span>author: {e.author}</span>
          </li>
        ))}
      </ul>
    </>
  );
};

export default page;

next: { revalidate: 20 } ์˜ต์…˜์ด ํ•ต์‹ฌ์ด๋‹ค! 20์ดˆ๋งˆ๋‹ค ์„œ๋ฒ„์—์„œ ์ƒˆ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ์ƒ์„ฑํ•œ๋‹ค๋Š” ์˜๋ฏธ๋‹ค.

ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•

  1. ๊ฐœ๋ฐœ์ž ๋„๊ตฌ Network ํƒญ ์—ด๊ณ  Disable Cache ์ฒดํฌํ–ˆ๋‹ค
  2. ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ ํ›„ HTML ์†Œ์Šค ํ™•์ธํ–ˆ๋”๋‹ˆ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์—ˆ๋‹ค
  3. 20์ดˆ ํ›„์— ๋‹ค์‹œ ์ƒˆ๋กœ๊ณ ์นจํ–ˆ๋”๋‹ˆ ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์—ˆ๋‹ค!
  4. (ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด API ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•œ ๋‹ค์Œ revalidate ์‹œ๊ฐ„ ์ดํ›„์— ํ™•์ธํ–ˆ๋‹ค)

์ ํ•ฉํ•œ ์‚ฌ์šฉ ์ผ€์ด์Šค

  • ๋ฐ์ดํ„ฐ๊ฐ€ ์ž์ฃผ ๋ณ€ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์™„์ „ํžˆ ์ •์ ์ด์ง€๋„ ์•Š์€ ํŽ˜์ด์ง€
  • ๋งˆ์ผ€ํŒ… ํŽ˜์ด์ง€, ์ œํ’ˆ ๋ชฉ๋ก ๋“ฑ
  • ํŠธ๋ž˜ํ”ฝ์ด ๋งŽ์ง€๋งŒ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹ˆ์–ด๋„ ๊ดœ์ฐฎ์€ ํŽ˜์ด์ง€

๐Ÿ“Œ 4. SSG (Static Site Generation)

SSG๋Š” ๋นŒ๋“œ ํƒ€์ž„์— HTML์„ ์ƒ์„ฑํ•ด๋‘๊ณ  ๊ณ„์† ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
ํ•œ ๋ฒˆ ์ƒ์„ฑ๋œ HTML์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๊ณ  ๊ณ„์† ๊ฐ™์€ ๋‚ด์šฉ์„ ์ œ๊ณตํ•œ๋‹ค.

๊ตฌํ˜„ ์ฝ”๋“œ

import React from "react";
import { DEFAULT_POST_URL } from "../constants/postConstant";
import { Post } from "../types/posts";
import PostList from "../components/PostList";

const page = async () => {
  const res = await fetch(`${DEFAULT_POST_URL}/posts`);  // ๊ธฐ๋ณธ๊ฐ’์ด force-cache
  const data: Post[] = await res.json();
  return (
    <>
      <h1>SSGPage</h1>
      <PostList data={data} />
    </>
  );
};

export default page;

fetch ํ•จ์ˆ˜์— ์•„๋ฌด๋Ÿฐ ์บ์‹œ ์˜ต์…˜์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์€ force-cache๋กœ, ์ด๋Š” SSG ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•

  1. next build && next start ์‹คํ–‰ํ–ˆ๋‹ค (๊ฐœ๋ฐœ ๋ชจ๋“œ์—์„œ๋Š” ์ œ๋Œ€๋กœ ํ…Œ์ŠคํŠธ ๋ถˆ๊ฐ€)
  2. ํŽ˜์ด์ง€ ๋ฐฉ๋ฌธ ํ›„ HTML ์†Œ์Šค ๋ณด๊ธฐํ–ˆ๋”๋‹ˆ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์—ˆ๋‹ค
  3. Network ํƒญ์—์„œ API ์š”์ฒญ์ด ์—†๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค
  4. API ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ ๋นŒ๋“œํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ํŽ˜์ด์ง€ ๋‚ด์šฉ์ด ๋ณ€ํ•˜์ง€ ์•Š์•˜๋‹ค

์ ํ•ฉํ•œ ์‚ฌ์šฉ ์ผ€์ด์Šค

  • ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฑฐ์˜ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€
  • ํšŒ์‚ฌ ์†Œ๊ฐœ, ๋งˆ์ผ€ํŒ… ๋žœ๋”ฉ ํŽ˜์ด์ง€
  • ๋ฌธ์„œ, ํŠœํ† ๋ฆฌ์–ผ ๋“ฑ ์ •์  ์ฝ˜ํ…์ธ 
  • ๊ฐ€์žฅ ๋น ๋ฅธ ๋กœ๋”ฉ ์‹œ๊ฐ„์ด ํ•„์š”ํ•œ ํŽ˜์ด์ง€

๐ŸŽฏ ํ•œ๋ˆˆ์— ๋น„๊ต

๋ Œ๋”๋ง ๋ฐฉ์‹๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์‹œ์ HTML ์†Œ์Šค์— ๋ฐ์ดํ„ฐ ํฌํ•จ?ํŠน์ง•์ ํ•ฉํ•œ ์‚ฌ์šฉ ์ผ€์ด์Šค
CSR๋ธŒ๋ผ์šฐ์ €์—์„œโŒ ์—†์Œ์ฒ˜์Œ์— ๋นˆ ํ™”๋ฉด, ํ›„์— ๋ฐ์ดํ„ฐ ๋กœ๋“œ๋Œ€์‹œ๋ณด๋“œ, ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€
SSR๋งค ์š”์ฒญ๋งˆ๋‹ค ์„œ๋ฒ„์—์„œโœ… ํฌํ•จํ•ญ์ƒ ์ตœ์‹  ๋ฐ์ดํ„ฐ ์ œ๊ณต๋ธ”๋กœ๊ทธ, ๋‰ด์Šค, SEO ์ค‘์š” ํŽ˜์ด์ง€
ISR์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์„œ๋ฒ„์—์„œโœ… ํฌํ•จ์ •์ ์ด์ง€๋งŒ ์ฃผ๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ์ œํ’ˆ ๋ชฉ๋ก, ์ค‘๊ฐ„ ์ •๋„ ๋ณ€๊ฒฝ ๋นˆ๋„
SSG๋นŒ๋“œ ์‹œ ํ•œ๋ฒˆ๋งŒโœ… ํฌํ•จํ•ญ์ƒ ๊ฐ™์€ ๋‚ด์šฉ ์ œ๊ณต, ๋งค์šฐ ๋น ๋ฆ„ํšŒ์‚ฌ ์†Œ๊ฐœ, ๋งˆ์ผ€ํŒ… ํŽ˜์ด์ง€
  • ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๊ฐ€ ์ค‘์š”ํ•œ ํŽ˜์ด์ง€: SSR
  • ์ž์ฃผ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ: ISR
  • ์ƒํ˜ธ์ž‘์šฉ์ด ๋งŽ์€ ๋™์  ํŽ˜์ด์ง€: CSR
  • ์ •์ ์ธ ์ฝ˜ํ…์ธ : SSG
profile
์ฃผ๋‹ˆ์–ด ํ”„๋ก ํŠธ์—”๋“œ ์„ฑ์žฅ๊ธฐ ๊ธฐ๋ก๊ธฐ๋ก

0๊ฐœ์˜ ๋Œ“๊ธ€