๐Ÿ˜ต ๋“ค์–ด๊ฐ€๋ฉฐ


๋ฆฌ์•กํŠธ์™€ ๋„ฅ์ŠคํŠธ์˜ ์ฐจ์ด์ ์ด๋ผ ํ•˜๋ฏ„ ๋ Œ๋”๋ง์„ ์–ด๋””์„œ ํ•˜๋А๋ƒ๋ฉฐ, CSR๊ณผ SSR ์˜ ์ฐจ์ด๋ผ๊ณ ๋งŒ ์ƒ๊ฐํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ SSR์—๋„ ์ข…๋ฅ˜๊ฐ€ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ,,! ์ •ํ™•ํžˆ๋Š” Next.js์˜ ๋ Œ๋”๋ง ์ข…๋ฅ˜์—” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ,,! ๋ฅผ ๊นจ๋‹ซ๊ณ  ์จ๋ณด๋Š” ์˜ค๋Š˜์˜ ํฌ์ŠคํŒ…์ด๋‹ค.



๐Ÿ”ฅ ๊ธฐ๋ณธ ๊ฐœ๋… ์ •๋ฆฌ


React์˜ Rendering

๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์„œ๋ฒ„์—์„œ JavaScript, CSS, HTML ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•œ ํ›„, JavaScript๊ฐ€ ์‹คํ–‰๋˜์–ด ํ™”๋ฉด์„ ๋ Œ๋”๋งํ•œ๋‹ค. ์ด ๊ณผ์ •์—์„œ ์‚ฌ์šฉ์ž๋Š” ์ดˆ๊ธฐ์— ๋นˆ ํ™”๋ฉด์„ ๋ณด๊ฒŒ ๋˜๋ฉฐ, ์ดˆ๊ธฐ ๋นˆ ๊ป๋ฐ๊ธฐ์ธ html๋กœ ์ธํ•ด ๊ฒ€์ƒ‰์—”์ง„์ตœ์ ํ™”(SEO)๊ฐ€ ๋ถˆ๋ฆฌํ•˜๋‹ค.


Next.js์˜ Pre-rendering

ํŽ˜์ด์ง€์˜ HTML์„ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•˜๊ธฐ ์ „์— ์„œ๋ฒ„๋‚˜ ๋นŒ๋“œ ๋‹จ๊ณ„์—์„œ HTML์„ ์ค€๋น„ํ•ด ๋‘๋Š” ๊ฒƒ์„ ๋œปํ•œ๋‹ค. ๊ทธ๋กœ์ธํ•ด ์ด๋ฏธ ์ค€๋น„๋œ HTML๋กœ ์‚ฌ์šฉ์ž๋Š” ๊ธฐ๋‹ค๋ฆผ ์—†์ด ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ๊ณ , SEO๊ฐ€ ๊ฐœ์„ ๋œ๋‹ค.


Hydration

Next.js์—์„œ Pre-rendering์€ HTML๊ณผ CSS๋งŒ์„ ์ค€๋น„ํ•ด๋‘” ์ƒํƒœ๋กœ ๋นˆ ๊ป๋ฐ๊ธฐ์— ๋ถˆ๊ณผํ•˜๋‹ค. ๋ธŒ๋ผ์šฐ์ €์—์„œ JavaScript๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ํŽ˜์ด์ง€์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์—†๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฒ„ํŠผ๊ณผ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋Š” ์ดˆ๊ธฐ์—๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ JavaScript ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ React ์ปดํฌ๋„ŒํŠธ์™€ HTML์„ ์—ฐ๊ฒฐํ•˜๊ณ , ๋™์ž‘์„ ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ณผ์ •์ด ์ง„ํ–‰๋˜๋Š”๋ฐ, ์ด๋ฅผ Hydration์ด๋ผ๊ณ  ํ•œ๋‹ค.



๐ŸŒธ Next.js์˜ Rendering


์œ„์˜ ๊ฐœ๋…์—์„œ ์ •๋ฆฌํ–ˆ๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ ํด๋ผ์ด์–ธํŠธ(1)์™€ ์„œ๋ฒ„๋‹จ(3)์—์„œ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ถ„๋ฅ˜๋ฅผ ํ•˜๋ฉด ์•„๋ž˜์˜ ์ด 4๊ฐ€์ง€์˜ ๋ Œ๋”๋ง ๋ฐฉ์‹์ด ์กด์žฌํ•œ๋‹ค. ์ด๋Š” Next.js 13 ๋ฒ„์ „ ๊ธฐ์ค€์˜ ๋ฐฉ์‹์ด๋‹ค.

CSR: Client Side Rendering

  • ํด๋ผ์ด์–ธํŠธ์—์„œ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ fetchํ•˜๋Š” ๋ฐฉ์‹
  • ์ฝ”๋“œ ์ƒ๋‹จ์— โ€˜use clientโ€™ ๊ตฌ๋ฌธ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๊ธฐ์กด ๋ฆฌ์•กํŠธ ๋ฐฉ์‹์ฒ˜๋Ÿผ CSR ๋ฐฉ์‹์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์•„๋ž˜ ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๋Š” ๋ Œ๋”๋ง์‹œ์˜ ์‹œ๊ฐ„์„ ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅํ•œ๋‹ค. ์ƒˆ๋กœ๊ณ ์นจ ๋งˆ๋‹ค ์‹œ๊ฐ„์ด ๋ณ€๊ฒฝ๋˜์–ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์† ์š”์ฒญํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


"use client";

import { useEffect, useState } from "react";

export default function CSRPage() {
  const [time, setTime] = useState<string>("");

  useEffect(() => {
    const getTime = async () => {
      const res = await fetch(
        "http://worldtimeapi.org/api/timezone/Asia/Seoul",

        {
          cache: "no-store",
        }
      );

      const data = await res.json();

      setTime(data.datetime);
    };

    getTime();
  }, []);

  return <div>CSR: {time}</div>;
}


csr



SSR: Server Side Rendering

  • ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ–ˆ์„ ๋•Œ, ์„œ๋ฒ„์—์„œ ๋ฐ”๋กœ ์ƒ์„ฑํ•˜์—ฌ ์ œ๊ณต๋œ๋‹ค.
  • ์š”์ฒญ ๋งˆ๋‹ค ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณด์—ฌ์ง€๋Š” ํŽ˜์ด์ง€์— ์ ํ•ฉํ•œ ๋ Œ๋”๋ง ๋ฐฉ์‹ ์ด๋‹ค.
  • SSR ๋ฐฉ์‹ ์—ญ์‹œ, ๋ Œ๋”๋ง์„ ์š”์ฒญํ•œ ์‹œ์ ์˜ ์‹œ๊ฐ„์„ ์ถœ๋ ฅํ•˜๋ฉฐ ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ํ˜ธ์ถœ๋กœ ์‹œ๊ฐ„์ด ๋ณ€๊ฒฝ๋œ๋‹ค.


export default async function SSRPage() {
  const res = await fetch("http://worldtimeapi.org/api/timezone/Asia/Seoul", {
    cache: "no-store",
  });

  const data = await res.json();

  return <div>SSR: {data.datetime}</div>;
}


ssr



SSG: Static Site Generation

  • ํŽ˜์ด์ง€๊ฐ€ ๋นŒ๋“œ ์‹œ์ ์— ๋ฏธ๋ฆฌ ์ƒ์„ฑ๋˜์–ด ์„œ๋ฒ„์— ์ œ๊ณต๋ ๋•Œ, ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘” HTML์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ Œ๋”๋ง ๋ฐฉ์‹์ด๋‹ค.
  • ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ์ฝ˜ํ…์ธ ์— ์ ํ•ฉํ•˜๋‹ค.
  • ํ•ด๋‹น ์ด๋ฏธ์ง€๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด, ๋นŒ๋“œ ์‹œ์— ์ €์žฅ๋œ ์‹œ๊ฐ„์œผ๋กœ๋งŒ ๊ณ„์† ์ถœ๋ ฅํ•˜์—ฌ ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


export default async function SSGPage() {
  const res = await fetch("https://worldtimeapi.org/api/timezone/Asia/Seoul");

  const data = await res.json();

  return <div>SSG: {data.datetime}</div>;
}

ssg



ISR: Incremental Static Regeneration

  • SSG์™€ SSR์˜ ์ค‘๊ฐ„ ํ˜•ํƒœ๋กœ, ํŽ˜์ด์ง€๋Š” ๋นŒ๋“œ ์‹œ ์ƒ์„ฑ๋˜์ง€๋งŒ ํŠน์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์„œ๋ฒ„์—์„œ ๋‹ค์‹œ ์ƒ์„ฑํ•˜์—ฌ ์ฃผ๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์ฝ”๋“œ์—์„œ 10์ดˆ๋งˆ๋‹ค ๊ฐฑ์‹ ํ•˜๋Š” ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ๋ฅผ ์˜ต์…˜์œผ๋กœ ์ถ”๊ฐ€ํ•˜์˜€๋Š”๋ฐ, ์ƒˆ๋กœ๊ณ ์นจ ์‹œ ๋ณ€๋™ํ•˜๋Š” ์‹œ๊ฐ„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


export default async function ISRPage() {
  const res = await fetch("http://worldtimeapi.org/api/timezone/Asia/Seoul", {
    next: { revalidate: 10 },
  }); // 10์ดˆ๋งˆ๋‹ค ๊ฐฑ์‹ 

  const data = await res.json();

  return <div>ISR: {data.datetime}</div>;
}

isr



๐Ÿ˜€ ๋งˆ๋ฌด๋ฆฌ


CSR ์ž์ฒด๋Š” ํด๋ผ์ด์–ธํŠธ ๋‹จ์—์„œ ๋Œ€๋ถ€๋ถ„์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„๊ฐ€ ํ•˜๋Š” ์—ญํ• ์ด ๊ฑฐ์˜ ์—†๋‹ค. ๋ฐ˜๋ฉด์— SSR์€ ์„œ๋ฒ„์—์„œ ๊ณ„์† ์ƒˆ๋กœ์šด HTML์„ ๋งŒ๋“ค์–ด๋‚ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๋Œ€์ ์œผ๋กœ ๋ถ€ํ•˜๊ฐ€ ์˜ฌ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋–„๋ฌธ์— ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ํ™”๋ฉด์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ Œ๋”๋ง ๋ฐฉ์‹์„ ์ฑ„ํƒํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜๊ณผ ์„ฑ๋Šฅ ์ธก๋ฉด์—์„œ ๋งค์šฐ ์ด์ ์ด ์žˆ๋‹ค. ์™œ ์ด๊ฑธ ์ง€๊ธˆ์—์•ผ ์ •๋ฆฌํ–ˆ์„๊นŒ ๋ฐ˜์„ฑ + ์˜ค๋Š˜ ์ •๋ฆฌํ•œ ๊ฐœ๋…์„ ๋ฐ”ํƒ•์œผ๋กœ ๋” ๋‚˜์€ ์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์€ ์ž์‹ ๊ฐ๊ณผ ํ•จ๊ป˜,,,๋„ฅ์ŠคํŠธ๋ฅผ ๋” ์ž˜ ์ดํ•ดํ•œ ๋“ฏ ํ•œ ๋А๋‚Œ์„ ๊ฐ€์ ธ๊ฐ€๋ฉฐ,, ์˜ค๋Š˜์˜ ํฌ์ŠคํŒ… ๋งˆ๋ฌด๋ฆฌํ•ด๋ณด๊ฒ ๋‹ค.๐Ÿค—