7/4 TIL

Hwiยท2024๋…„ 7์›” 4์ผ

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
63/96

๐Ÿ“š ์ง„ํ–‰ํ•œ ๊ณต๋ถ€

  • ๊ฐœ์ธ๊ณผ์ œ ํฌ์ผ“๋ชฌ ์ƒ์„ธํŽ˜์ด์ง€ ์ž‘์„ฑ
  • Next.js Rendering

๐Ÿ“– ๊ฐœ์ธ๊ณผ์ œ ํฌ์ผ“๋ชฌ ์ƒ์„ธํŽ˜์ด์ง€ ์ž‘์„ฑ

PokemonDetail ์ปดํฌ๋„ŒํŠธ

pokemondetail/[id]/page.tsx

์œ„์—์„œ ๋งŒ๋“ค์–ด ๋‘” ํฌ์ผ“๋ชฌ๋””ํ…Œ์ผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฌ๊ธฐ๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ๋งŒ ํ•˜๋ฉด ๋๋‹ค.

๋ฌธ์ œ์—†์ด ์ž˜ ๋“ค์–ด๊ฐ€์ง€๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ด์ œ ๋‚ด๊ฒŒ ๋‚จ์€ ๊ฑด ๋””ํ…Œ์ผ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ

ํฌ์ผ“๋ชฌ๋””ํ…Œ์ผ ์ปดํฌ๋„ŒํŠธ์— ๋‹ค์–‘ํ•œ ํฌ์ผ“๋ชฌ์˜ ์ƒ์„ธ ์ •๋ณด๋“ค์„ ๋‹ด์•„์ฃผ๊ณ  pokemondetail/[id]/page.tsx์—์„œ ๋ถˆ๋Ÿฌ์™”์Œ

์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Œ

CSS๋ฅผ ์ข€ ๋” ๊ฐ€๊ณตํ•˜๊ณ  ์‹ถ์ง€๋งŒ.. ๊ณผ์ œ ํ•„์ˆ˜ ๊ตฌํ˜„ ์‚ฌํ•ญ์€ ๋‹ค ๋งŒ์กฑํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ์ธ ๊ณต๋ถ€์— ์ข€ ๋” ์‹œ๊ฐ„์„ ์“ฐ๋ ค๊ณ  ํ•œ๋‹ค

๐Ÿ“— Next.js Rendering

๐Ÿ“– 01. v12์™€ v13์˜ ์ฃผ์š” ์ฐจ์ด์  ํ›‘๊ธฐ

(1) ์ฃผ์š” ์ฐจ์ด์ 
Next.js๋ฅผ ํ•  ๋•Œ, ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ฒŒ ๋ณด๋Š” ๊ฐœ๋… = ๋ Œ๋”๋ง ๋ฐฉ์‹
CSR, SSR, ISR, SSG
Next.js ๋ฒ„์ „ 12๊นŒ์ง€๋Š” ์ด๋Ÿฌํ•œ ๋ Œ๋”๋ง ๋ฐฉ์‹์„ 'ํŽ˜์ด์ง€ ๋‹จ์œ„'๋กœ ๊ทœ์ •ํ–ˆ์Œ ์˜ˆ๋ฅผ ๋“ค์–ด

  • "about ํŽ˜์ด์ง€๋Š” SSG๋กœ ๋™์ž‘ํ•จ"
  • "todolist ํŽ˜์ด์ง€๋Š” SSR๋กœ ๋™์ž‘ํ•จ"
  • "sample ํŽ˜์ด์ง€๋Š” CSR๋กœ ๋™์ž‘ํ•จ"

๊ณผ ๊ฐ™์ด ๋ง์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, Next.js 13 ๋ฒ„์ „์—์„œ๋Š” React 18 ๋ฒ„์ „์—์„œ ์ œ์‹œํ•œ

  • ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ(์„œ๋ฒ„ ์ƒ์—์„œ๋งŒ ๋™์ž‘)
  • ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ(๋ธŒ๋ผ์šฐ์ €์—์„œ๋งŒ ๋™์ž‘)

์— ํž˜์ž…์–ด ๋ Œ๋”๋ง ๋ฐฉ์‹์ด ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ๋ฒฝ๋…•๋จ. ์ด์ œ๋Š” ํ•œ ํŽ˜์ด์ง€ ์•ˆ์—์„œ ์—ฌ๋Ÿฌ ๋ Œ๋”๋ง ๋ฐฉ์‹์ด ๊ณต์กดํ•  ์ˆ˜ ์ž‡์Œ


๐Ÿ“– 02. ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ / ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ

(1) ์žŠ์ง€ ๋ง์•„์•ผ ํ•  ๊ฒƒ
๊ธฐ๋ณธ์ ์œผ๋กœ app ํด๋” ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ชจ๋‘ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ
๋งค์šฐ ์ค‘์š”ํ•จ

(2) ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ

// src>app>page.tsx
export default function Home() {
  console.log("์—ฌ๊ธฐ๋Š” ์–ด๋””์ผ๊นŒ์š”?");

  return (
    <div className="p-8">
      ์•ˆ๋…•ํ•˜์„ธ์š”! ๋‚ด๋ฐฐ์บ  ๋ฆฌ์•กํŠธ.. ์•„๋‹ˆ์•„๋‹ˆ ๋„ฅ์ŠคํŠธ์ž…๋‹ˆ๋‹ค!
    </div>
  );
}

์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜๋ฉด, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•„๋‹ˆ๋ผ terminal์— console.log๊ฐ€ ์ถœ๋ ฅ์ด ๋จ.

์šฐ๋ฆฌ๊ฐ€ ์„œ๋ฒ„๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ๋Š” localhost ์ฆ‰, ๋‚ด ์ปดํ“จํ„ฐ์˜ node ํ™˜๊ฒฝ์—์„œ console.log๊ฐ€ ์ถœ๋ ฅ๋˜๊ณ  ์žˆ์Œ

๋งŒ์ผ ํ”„๋กœ์ ํŠธ๊ฐ€ aws ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ์ปดํ“จํŒ…์—์„œ ๋Œ์•„๊ฐ€๊ณ  ์žˆ๋‹ค๋ฉด, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•„๋‹ˆ๋ผ ํ•ด๋‹น ์„œ๋ฒ„์˜ ๋กœ๊ทธ์— console.log๊ฐ€ ์ถœ๋ ฅ๋  ๊ฒƒ์ž„

alert ๋ช…๋ น์–ด๋Š” ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ(Node.js ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ)์—์„  ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ณ  os.hostname ๋ช…๋ น์–ด๋Š” ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅ

(3) ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ
์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” alert, confirm ์ฒ˜๋Ÿผ ์œ ์ €์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์ด ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ, ๊ธฐ๋Šฅ์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ useEffect, useState ์ฒ˜๋Ÿผ CSR์„ ์œ„ํ•ด ์‚ฌ์šฉ๋œ ๊ธฐ์ˆ ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋‚˜
์ด๋Ÿฐ ๊ฒฝ์šฐ์—” ์ปดํฌ๋„ŒํŠธ ์ตœ์ƒ๋‹จ์— "use client"๋งŒ ๋ถ™์—ฌ์ฃผ๋ฉด ๋จ

(4) ์–ธ์ œ, ์–ด๋–ป๊ฒŒ SC/CC๋ฅผ ์“ฐ๋Š”์ง€?
์œ ์ €์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์ด ์žˆ๋Š” ๊ฒฝ์šฐ CC, ๊ทธ ์™ธ์˜ ๊ฒฝ์šฐ๋Š” SC๋ฅผ ๊ถŒ์žฅ

(5) ๋” ๋‚˜์•„๊ฐ€๊ธฐ(์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ)

// src>app>page.tsx
export default function Home() {
  return (
    <div className="p-8">
      ์•ˆ๋…•ํ•˜์„ธ์š”! 
      <section>
        <h1>์ œ๋ชฉ</h1>
      <button onClick={() => {
          alert("์•ˆ๋…•ํ•˜์„ธ์š”!");
        }}
      >ํด๋ฆญ</button>
		</section>
    </div>
  );
}

์ด ์ฝ”๋“œ๋Š” "use client"๊ฐ€ ์ตœ์ƒ๋‹จ์— ์—†๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์ž„
useEffect, useState, onClick ๋“ฑ์€ CC์—์„œ๋งŒ ๊ฐ€๋Šฅํ•œ ๊ธฐ์ˆ ์ธ๋ฐ SC์ธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉ์„ ํ•˜๊ณ  ์‹ถ์–ด์„œ ์œ„์— "use client"๋ฅผ ์จ๋ฒ„๋ฆฌ๊ฒŒ ๋˜๋ฉด CC๋กœ ๋˜์–ด๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿด ๊ฒฝ์šฐ์—” ์ด๋ ‡๊ฒŒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ

  • page.tsx
// src>app>page.tsx
import Button from "@/components/Button";

export default function Home() {
  return (
    <div className="p-8">
      ์•ˆ๋…•ํ•˜์„ธ์š”! 
      <section>
        <h1>์ œ๋ชฉ</h1>
		<Button />
      </section>
    </div>
  );
}
  • Button.tsx
// src>components>Button.tsx

"use client";

import React from "react";

const Button = () => {
  return (
    <button
      onClick={() => {
        alert("์•ˆ๋…•ํ•˜์„ธ์š”!");
      }}
    >
      ํด๋ฆญ
    </button>
  );
};

export default Button;

๐Ÿ“– 03. ๋ Œ๋”๋ง ์ดํ•ด๋ฅผ ์œ„ํ•œ ํ•ต์‹ฌ ๊ฐœ๋…

(1) SSG(Static Site Generation)
fetchํ•œ ๋ฐ์ดํ„ฐ๋Š” ์˜์›ํžˆ ๋ณ€์น˜ ์•Š์Œ = ๊ณ„์† ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐฑ์‹ ํ•  ํ•„์š” X

SSG๋Š” ๋นŒ๋“œํƒ€์ž„๋•Œ๋งŒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ดํ›„๋Š” ๋ณ€ํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€๋กœ ๊ฐ€์ •ํ•˜์—ฌ static ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ๋งํ•จ.

๊ทธ๋ฆฌ๊ณ  Next.js๋Š” ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ SSG๋กœ ๋™์ž‘

(2) ISR(Incremental Site Regeneration)
fetchํ•œ ๋ฐ์ดํ„ฐ๋Š” ๊ฐ€๋” ๋ณ€ํ•จ = ์ผ์ • ์ฃผ๊ธฐ๋งˆ๋‹ค ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐฑ์‹ 

ISR์€ ๋นŒ๋“œํƒ€์ž„๋•Œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ดˆ๊ธฐ ์ƒ์„ฑํ•˜๊ณ , ์ดํ›„๋Š” ์ผ์ • ์ฃผ๊ธฐ๋งˆ๋‹ค ๋ณ€ํ™”๋ฅผ ์ ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•จ

(3) SSR(Server Side Rendering)
fetchํ•œ ๋ฐ์ดํ„ฐ๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ณ„์† ๋ฐ”๋€œ = ์ปดํฌ๋„ŒํŠธ ์š”์ฒญ์ด ์žˆ์„ ๋•Œ ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐฑ์‹ ํ•ด์„œ ์ตœ์‹  ๋ฐ์ดํ„ฐ๋งŒ ์ œ๊ณตํ•ด์•ผ ํ•จ

SSR์€ ๋นŒ๋“œํƒ€์ž„๋•Œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ดˆ๊ธฐ ์ƒ์ƒํ•˜๊ณ , ์ดํ›„ ์ปดํฌ๋„ŒํŠธ ์š”์ฒญ์ด ์žˆ์„ ๋•Œ ๋งˆ๋‹ค ๋ณ€ํ™”๋ฅผ ์ ์šฉํ•˜์—ฌ ๊ฐ€์žฅ ์ตœ์‹ ์˜ ๋ฐ์ดํ„ฐ๋ฅผ user์—๊ฒŒ ์ œ๊ณต

(4) CSR(Client Side Rendering)
CSR์€ ๋นŒ๋“œํƒ€์ž„์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ดˆ๊ธฐ ์ƒ์„ฑํ•˜์ง„ ์•Š์Œ.
JavaScript๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฆฌ์•กํŠธ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๊ณ  ๊ทธ์ œ์„œ์•ผ ํ™”๋ฉด์ด ๊ทธ๋ ค์ง€๊ฒŒ ๋จ

use client ๋“ค์–ด๊ฐ€๋ฉด CSR์ž„

profile
๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ณ  ์‹ถ์–ด~~~

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

๋””ํ…Œ์ผํ•œ ๋ถ€๋ถ„๊นŒ์ง€ ์„ธ์„ธํ•˜๊ฒŒ ์ •๋ฆฌํ•˜์…จ๋„ค์š” ๋Œ€๋ฐ•
ui๋„ ๋„ˆ๋ฌด ๊น”๋”ํ•˜๋„ค์šฉ

1๊ฐœ์˜ ๋‹ต๊ธ€