๐Ÿ’ก 15. ์„œ๋ฒ„๋กœ ํšŒ๊ท€ํ•˜๋‹ค: RSC์™€ next.js ๋ธŒ๋ฆฟ์ง€

2026๋…„ 4์›” 30์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

React ์ƒํƒœ๊ณ„์˜ ํŒจ๋Ÿฌ๋‹ค์ž„ ๋ณ€ํ™”์ธ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ(RSC)์˜ ์˜๋ฏธ์™€, use client ์ง€์‹œ์–ด๊ฐ€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋ฅผ ๋‚˜๋ˆ„๋Š” ๊ฒฝ๊ณ„์„ (Boundary) ์—ญํ• ์„ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ์ด์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽฏ ์ด ์„น์…˜์„ ์ฝ๊ณ  ๋‚˜๋ฉด:

  • React Server Components(RSC)๊ฐ€ ๊ธฐ์กด์˜ SSR(Server-Side Rendering)๊ณผ ์™„์ „ํžˆ ๋‹ค๋ฅธ ๋งˆ๋ฒ•์ด๋ผ๋Š” ์ ์„ ์ดํ•ดํ•œ๋‹ค.
  • use client ์ตœ์ƒ๋‹จ ์ง€์‹œ์–ด์˜ ์ง„์งœ ์˜๋ฏธ๊ฐ€ '๋ธŒ๋ผ์šฐ์ € ์ „์šฉ ์‹คํ–‰'์ด ์•„๋‹ˆ๋ผ ๋‹จ์ ˆ์˜ ๊ฒฝ๊ณ„์„ (Network Boundary) ์ž„์„ ์™„๋ฒฝํžˆ ๊ทธ๋ ค๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ์˜ ์ฑ…์ž„ ์†Œ์žฌ์ง€(์„œ๋ฒ„๋ƒ, ํด๋ผ์ด์–ธํŠธ๋ƒ)๋ฅผ ๋ช…ํ™•ํžˆ ํŒ๋ณ„ํ•˜๋Š” ์‹œ๊ฐ์„ ๊ฐ–๋Š”๋‹ค. (๋Œ€๋‹จ์› ๋งˆ๋ฌด๋ฆฌ)

๐Ÿ“‹ ๋ชฉ์ฐจ


๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 10๋ถ„ / ํ•ต์‹ฌ ํŒŒํŠธ: 6๋ถ„

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ์˜์ฒ (์‹ ์ž…):"์„ ๋ฐฐ๋‹˜! Next.js 13 ๋ฒ„์ „๋ถ€ํ„ฐ ํŽ˜์ด์ง€ ์ƒ๋‹จ์— use client ์“ฐ๋ผ๊ณ  ๊ณ„์† ์—๋Ÿฌ๊ฐ€ ๋– ์„œ ๋‹ต๋‹ตํ•ด์š”. ๊ทธ๋ƒฅ _app.tsx ์ ค ์œ„์— ํ•œ ๋ฒˆ ์ ์–ด๋‘๋ฉด ์ „๋ถ€ ํด๋ผ์ด์–ธํŠธ๋กœ ํŽธํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ฑฐ ์•„๋‹Œ๊ฐ€์š”?"
  • ์˜ํ˜ธ(๋ฆฌ๋“œ):"์˜์ฒ  ๋‹˜. ๊ทธ๊ฑธ ์ „๋ถ€ ํด๋ผ์ด์–ธํŠธ๋กœ ๋Œ๋ ค๋ฒ„๋ฆด ๊ฑฐ๋ฉด ๋ฌด๊ฑฐ์šด ๋ฒˆ๋“ค ํŒŒ์ผ์„ ์œ ์ € ๋ธŒ๋ผ์šฐ์ €๋กœ ๋ชจ๋‘ ๋ณด๋‚ด๊ฒ ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ 10๋…„ ๋งŒ์— ์ผ์–ด๋‚œ 'ํ”„๋ก ํŠธ์—”๋“œ์˜ ๋Œ€๋ฅ™ ์ด๋™(์„œ๋ฒ„์‚ฌ์ด๋“œ ์˜ํ†  ๊ท€ํ™˜)' ์˜ ํ•œ๊ฐ€์šด๋ฐ ์„œ ์žˆ์Šต๋‹ˆ๋‹ค."

๐Ÿค” ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€: JS ๋ฒˆ๋“ค ๋‹ค์ด์–ดํŠธ์˜ ์ „์Ÿ

์ง€๊ธˆ๊นŒ์ง€ 01๊ฐ•๋ถ€ํ„ฐ 14๊ฐ•๊นŒ์ง€ ๋ฐฐ์šด ๋ชจ๋“  ๋‚ด์šฉ์€ ๋‹จ์„œ๋ฅผ ๋‹ฌ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
"์ด ์ฝ”๋“œ๋Š” ๋ธŒ๋ผ์šฐ์ €(ํฌ๋กฌ, ์‚ฌํŒŒ๋ฆฌ) ์œ„์—์„œ ์‹คํ–‰๋œ๋‹ค."

ํ•˜์ง€๋งŒ ์ƒ๊ฐํ•ด๋ณด์„ธ์š”. ๋‹น์‹ ์ด ๊ฑฐ๋Œ€ํ•œ ๋‚ ์”จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ moment.js (ํฌ๊ธฐ: 300KB)๋‚˜ Markdown ๋ Œ๋”๋ง ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์จ์„œ ํ™”๋ฉด์„ ๊ทธ๋ฆฐ๋‹ค๊ณ  ์นฉ์‹œ๋‹ค.
๊ธฐ์กด์˜ React ์ƒํƒœ๊ณ„(CSR, ์ „ํ†ต์  SPA)์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ ๋‚ด ์‚ฌ์ดํŠธ์— ๋“ค์–ด์˜ค์ž๋งˆ์ž ๊ทธ ๋ฌด๊ฑฐ์šด ์ฝ”๋”ฉ ํŒŒ์ผ 300KB๋ฅผ ๋ชฝ๋•… ๋‹ค์šด๋กœ๋“œํ•ด์•ผ ๋น„๋กœ์†Œ ์‹คํ–‰์ด ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค. "๋กœ๋”ฉ ์ค‘..." ์Šคํ”ผ๋„ˆ๊ฐ€ ๋ฌดํ•œ์ • ๋ฑ…๊ธ€๋ฑ…๊ธ€ ๋•๋‹ˆ๋‹ค.

๐Ÿค” ์ž ๊น, ๋จผ์ € ์ƒ๊ฐํ•ด๋ด
์ด๊ฑฐ ์šฐ๋ฆฌ ์ปดํ“จํ„ฐ(์„œ๋ฒ„) ์„ฑ๋Šฅ ์ข‹์€๋ฐ... ์šฐ๋ฆฌ๊ฐ€ ์„œ๋ฒ„์—์„œ ์ € ๋ฌด๊ฑฐ์šด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค ๋Œ๋ ค์„œ HTML๋งŒ ์˜ˆ์˜๊ฒŒ ๊นŽ์•„๋‚ธ ๋‹ค์Œ ๊ฒฐ๊ณผ๋ฌผ ํ…์ŠคํŠธ(๋ฌธ์ž์—ด)๋งŒ ํฐ์œผ๋กœ ๋ณด๋‚ด์ฃผ๋ฉด ์œ ์ € ๋ฐ์ดํ„ฐ(MB)๋„ ์•„๋ผ๊ณ  ๋กœ๋”ฉ๋„ 0.1์ดˆ ์ปท ์•„๋‹๊นŒ?

์˜ˆ. ๊ทธ ์ƒ๊ฐ์—์„œ ์ถœ๋ฐœํ•œ ๊ถ๊ทน์˜ ์ง„ํ™”๊ฐ€ ๋ฐ”๋กœ React Server Components (RSC) ์ž…๋‹ˆ๋‹ค.


๐Ÿ—๏ธ ๋น„์œ ๋กœ ๋จผ์ € ์ดํ•ดํ•˜๊ธฐ

๐Ÿง’ 5์‚ด์—๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค๋ฉด?

  1. ๊ณผ๊ฑฐ (Client Component ์œ„์ฃผ ์‹œ๋Œ€):
    ์‹๋‹น ์š”๋ฆฌ์‚ฌ(์˜์ฒ )๊ฐ€ ์†๋‹˜(๋ธŒ๋ผ์šฐ์ €)์—๊ฒŒ ์ƒ๊ณ ๊ธฐ, ์•ผ์ฑ„, ์นผ, ๋„๋งˆ, ๊ฐ€์Šค๋ฒ„๋„ˆ(๊ฑฐ๋Œ€ํ•œ JS ๋ฒˆ๋“ค ์ฝ”๋“œ ๋ฉ์–ด๋ฆฌ)๋ฅผ ๋ฐ•์Šค ์ฑ„๋กœ ํ…Œ์ด๋ธ”์— ํ•œ๊บผ๋ฒˆ์— ๊ฑด๋„ค์คŒ.
    โ€œ์†๋‹˜! ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ๋Š” ์†๋‹˜ ํœด๋Œ€ํฐ์ด ์ง์ ‘ ๊ฐ€์Šค๋ฒ„๋„ˆ ์ผœ๊ณ (useEffect), ๋„ค์ด๋ฒ„์— ๋‚ ์”จ ๋ฌผ์–ด๋ณด๊ณ (fetch), ๊ณ ๊ธฐ ๊ตฌ์›Œ์„œ ํ–„๋ฒ„๊ฑฐ ์กฐ๋ฆฝ(๋ Œ๋”๋ง)ํ•ด ๋“œ์„ธ์š”!โ€ -> ์œ ์ € ํฐ์ด ์—„์ฒญ ๋œจ๊ฑฐ์›Œ์ง€๊ณ  ๋กœ๋”ฉ์ด ๊น€.

  2. ํ˜„์žฌ (์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ, Server Components):
    ๊ฐ•๋ ฅํ•œ ์ฃผ๋ฐฉ(Node.js ์„œ๋ฒ„)์—์„œ ์š”๋ฆฌ์‚ฌ(์˜ํ˜ธ)๊ฐ€ ์—„์ฒญ ๋น ๋ฅธ ์†๋„๋กœ ๋‚ ์”จ๋„ ์•Œ์•„์˜ค๊ณ , ๊ณ ๊ธฐ๋„ ๋‹ค ๊ตฝ๊ณ  ๋งˆํฌ๋‹ค์šดํŒŒ์‹ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฒ˜๋ฆฌ๋„ ๋‹ค ๋๋ƒ„.
    ํ…Œ์ด๋ธ”(์œ ์ € ํฐ)์—๋Š” ๋ญ๋งŒ ๋ฐฐ๋‹ฌํ•ด์ฃผ๋А๋ƒ? ๋‹จ 0.01์ดˆ ๋งŒ์— ์ด์˜๊ฒŒ ์™„์„ฑ๋œ ํ–„๋ฒ„๊ฑฐ(์ •์ ์ธ HTML ๋ ˆ์ด์•„์›ƒ)๋งŒ ์‹ํƒ ์œ„์— ์‚ฌ๋ฟํžˆ ์˜ฌ๋ ค์คŒ.
    ์œ ์ €๋Š” ํŒŒ์ผ ์šฉ๋Ÿ‰์„ ๊ฑฐ์˜ ์•ˆ ๋ฐ›์•„๋„ ํ™”๋ฉด์„ ์ฆ‰๊ฐ(0์ดˆ ๋งŒ์—) ๋ณด๊ฒŒ ๋จ!

์ด ์—„์ฒญ๋‚œ ํŒจ๋Ÿฌ๋‹ค์ž„ ๋•Œ๋ฌธ์— Next.js ๊ฐ™์€ ์‹ ๊ธฐ์ˆ  ์œ„์—์„œ๋Š” ์ด์ œ "๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์˜ ๊ธฐ๋ณธ๊ฐ’(Default)์€ ๋ฌด์กฐ๊ฑด ์ฃผ๋ฐฉ(์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ)์—์„œ ๊ตฌ์›Œ์ง„๋‹ค" ๋กœ ๊ทœ์น™์ด ์™„์ „ํžˆ ๋’ค์ง‘ํžŒ ๊ฒƒ์ž…๋‹ˆ๋‹ค.


๐Ÿงฉ ๊ทน์˜ ์ฒด๋“: RSC์™€ use client์˜ ์ง„์งœ ์ž„๋ฌด

๊ทธ๋Ÿผ ์˜์ฒ ์ด์˜ ์งˆ๋ฌธ์œผ๋กœ ๋Œ์•„๊ฐ€ ๋ด…์‹œ๋‹ค. ์™œ ์ž๊พธ ์—๋Ÿฌ๊ฐ€ ๋‚˜๊ณ  use client๋ฅผ ๊ฐ•์ œํ–ˆ์„๊นŒ์š”?

์„œ๋ฒ„ ์ฃผ๋ฐฉ์—์„œ ์š”๋ฆฌ๋ฅผ ์•”๋งŒ ์ž˜ ๊ตฌ์›Œ์„œ ์คฌ์–ด๋„, "์†๋‹˜์ด ์ง์ ‘ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ๋ฐœ์ƒํ•˜๋Š” ๋ฐ˜์‘(onClick)" ์ด๋‚˜ "์†๋‹˜์˜ ์ง€๊ธˆ ํ˜„์žฌ ๋งˆ์šฐ์Šค ์œ„์น˜(useState)" ๋Š” ์„œ๋ฒ„ ์ฃผ๋ฐฉ์—์„œ ์•Œ ํ„ฑ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค!

โœ… 1. RSC์˜ ์ฒ ์น™ (์„œ๋ฒ„์˜ ์˜ํ† )

๊ธฐ๋ณธ์ ์œผ๋กœ ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ์ ์œผ๋ฉด ๋ชฝ๋•… ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ์ž…๋‹ˆ๋‹ค.

// ๐ŸŽฏ ์ด๊ฑฐ์Šจ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ (Next.js 13+ App Router ๊ธฐ์ค€)
// ์ตœ์ƒ๋‹จ์— ์•„๋ฌด๊ฒƒ๋„ ์—†๋‹ค. ๊ณ ๋กœ ๋‚˜๋Š” ์„œ๋ฒ„์—์„œ ๋นš์–ด์ ธ ๋‚ด๋ ค๊ฐ„๋‹ค.
 
import fs from 'fs'; // ํ—‰! ๋ฆฌ์•กํŠธ ๋‚ด๋ถ€์—์„œ ๋””์Šคํฌ ํŒŒ์ผ ์ฝ๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง!
import HeavyMarkdownToHtml from 'markdown-heavy-lib'; // 300MB์งœ๋ฆฌ ์œ„ํ—˜ํ•œ ๋ฌด๊ฑฐ์šด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ!
 
// ํ—‰! ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜ ์•ž์— async๊ฐ€ ๋ถ™์–ด? (useEffect ์—†์ด await๋กœ API ์ง๋นต ์ฝœ)
export default async function WeatherBoard() {
  const dbData = await db.query("SELECT * FROM weather"); // DB ์ง์ ‘ ์ฐŒ๋ฅด๊ธฐ!
  const htmlResult = HeavyMarkdownToHtml(dbData.content);
 
  // ๐Ÿ’ฅ ์ค‘์š”ํ•œ ํ˜œํƒ: ์œ„์—์„œ ์“ฐ์ธ HeavyMarkdownToHtml ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์†Œ์Šค์ฝ”๋“œ๋Š”
  // ์œ ์ €์˜ ๋ธŒ๋ผ์šฐ์ €๋กœ 1kb๋„ ์ „์†ก(๋‹ค์šด๋กœ๋“œ)๋˜์ง€ ์•Š๋Š”๋‹ค! ์˜ค์ง ๋ณ€ํ™˜๋œ <div> ๊ฒฐ๊ณผ๋ฌผ๋งŒ ์ „์†ก!
  return <div>{htmlResult}</div>;
}

์ด๊ฑด ๊ธฐ์กด CSR ๋ฆฌ์•กํŠธ๋กœ์„  ๊ฐํžˆ ์ƒ์ƒ๋„ ๋ชปํ•  ์••๋„์ ์ธ ๋Šฅ๋ ฅ์ž…๋‹ˆ๋‹ค. ํŒŒ์ผ ํฌ๊ธฐ ์ œ๋กœ, ๋กœ๋”ฉ ์ œ๋กœ.

โœ… 2. use client ์„ ์–ธ์˜ ์ง„์งœ ๋œป (๋„๊ฐœ๊ต ๋‚ด๋ฆฌ๊ธฐ)

๊ทธ๋Ÿฐ๋ฐ ์œ„ ๊ฒŒ์‹œํŒ ์•ˆ์— "๐Ÿ‘ ์ข‹์•„์š” ๋ฒ„ํŠผ"์„ ๋‹ฌ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํด๋ฆญํ•˜๋ฉด ์ˆซ์ž๊ฐ€ ์˜ฌ๋ผ๊ฐ€๋Š” ์ƒํƒœ(useState)๊ฐ€ ํ•„์š”ํ•˜์ฃ .
์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ export default function WeatherBoard ์•ˆ์— onClick= ์ด๋”ด ๊ฑธ ์“ฐ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋นก! ํ„ฐ์ง‘๋‹ˆ๋‹ค.

"Error: Event handlers cannot be passed to Client Component props. (์ด๋ด! ์—ฌ๊ธด ์„œ๋ฒ„ ์ฃผ๋ฐฉ์ด๋ผ๊ณ ! ์œ ์ € ๋งˆ์šฐ์Šค ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ๋‚ด๊ฐ€ ์—ฌ๊ธฐ์„œ ์–ด๋–ป๊ฒŒ ๊ฐ์ง€ํ•ด!)"

์ด๋Ÿด ๋•Œ ์“ฐ๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ use client ์ž…๋‹ˆ๋‹ค.
use client๋Š” "๋ฆฌ์•กํŠธ ์—”์ง„๋‹˜, ์š” ํŒŒ์ผ๋ถ€ํ„ฐ๋Š” ์ฃผ๋ฐฉ(์„œ๋ฒ„) ๋ฐ–์œผ๋กœ ๋ณด๋‚ด์„œ, ์œ ์ € ํฐ(ํด๋ผ์ด์–ธํŠธ) ์•ˆ์—์„œ ์ง์ ‘ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์‹คํ–‰๋˜๊ฒŒ ๋ฒˆ๋“ค์„ ํฌ์žฅ ๋ฐฐ๋‹ฌํ•ด์ฃผ์„ธ์š”!" ๋ผ๋Š” ๋„คํŠธ์›Œํฌ ๊ฒฝ๊ณ„์„ (Boundary) ์ปคํŒ… ์ง€์‹œ์–ด ์ž…๋‹ˆ๋‹ค.

// ๐ŸŽฏ 1. LikeButton.tsx ํŒŒ์ผ (์ƒˆ๋กœ ๋ถ„๋ฆฌ)
'use client' // ์—ฌ๊ถŒ์„ ๋ฐœ๊ธ‰ํ–ˆ๋‹ค. "๋‚˜๋Š” ์ง€๊ธˆ๋ถ€ํ„ฐ ๋ธŒ๋ผ์šฐ์ € ํด๋ผ์ด์–ธํŠธ ๋•…์œผ๋กœ ์ž…๊ตญํ•  ์ฝ”๋“œ๋‹ค."
 
import { useState } from 'react';
 
export default function LikeButton() {
  const [likes, setLikes] = useState(0); // ํฐ์—์„œ ๋Œ์•„๊ฐˆ ๋กœ์ง
  return <button onClick={() => setLikes(c => c+1)}>โค๏ธ {likes}</button>;
}

์ด์ œ ์„œ๋ฒ„์—์„œ ๋„๋Š” ๊ฑฐ๋Œ€ํ•œ ๊ฒŒ์‹œํŒ(WeatherBoard) ์•ˆ์—, ํด๋ผ์ด์–ธํŠธ์—์„œ ์ƒํ˜ธ์ž‘์šฉํ•  ์ž‘์€ ์กฐ๊ฐ(LikeButton)์„ ๊ตฌ๋ฉ ์†ก์†ก ํŒŒ์„œ ๋ผ์›Œ ๋„ฃ์œผ๋ฉด ํ™˜์ƒ์ ์ธ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์™„์„ฑ๋ฉ๋‹ˆ๋‹ค.

// ๐ŸŽฏ 2. WeatherBoard.tsx ํŒŒ์ผ (์„œ๋ฒ„ ์ฃผ๋ฐฉ)
// (use client ๊ตฌ๋ฌธ ์—†์Œ. ๊ณ ๋กœ ์„œ๋ฒ„)
import LikeButton from './LikeButton'; // ๋ธŒ๋ฆฟ์ง€ ๊ฒฐํ•ฉ!
 
export default async function WeatherBoard() {
  return (
    <div>
      <h1>์˜ค๋Š˜์˜ ๋‚ ์”จ (์„œ๋ฒ„์—์„œ DB ๊ธ์–ด์˜ด)</h1>
      <p>๊ตฌ๋ฆ„ ๋งŽ์Œ</p>
 
      {/* ๐Ÿš€ ์—ฌ๊ธฐ ํ•˜์œ„๋ถ€ํ„ฐ๋Š” ํด๋ผ์ด์–ธํŠธ ํฐ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋Œ๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค ๐Ÿš€ */}
      <LikeButton />
    </div>
  );
}

์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ "๋‚˜๋ญ‡์žŽ(Leaf) ๋๋‹จ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ชฐ์•„๋‚ด๋ผ (Push client components to the leaves)" ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
๋ฌด๊ฑฐ์šด ๋ Œ๋”๋ง ํŠธ๋ฆฌ์˜ ๊ธฐ๋‘ฅ๊ณผ ๊ฐ€์ง€(Layout, Data Fetching, Markdown ๋ Œ๋”)๋Š” ํŠผํŠผํ•œ ์„œ๋ฒ„์—์„œ ๋งก์•„ ๋‹ค ๊ทธ๋ ค๋ฒ„๋ฆฌ๊ณ , ๋‚˜๋ญ‡์žŽ ๋์—์„œ ์‚ด๋ž‘๊ฑฐ๋ฆฌ๋Š” ๋ฒ„ํŠผ ์ธํ„ฐ๋ž™์…˜ ๋ถ€์Šค๋Ÿฌ๊ธฐ๋“ค๋งŒ ๋–ผ์–ด๋‚ด์„œ ์œ ์ € ๋ธŒ๋ผ์šฐ์ €(ํฐ)์— ์ „์†กํ•˜๋Š” ํ™˜์ƒ์ ์ธ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ตฌ์กฐ.

์ด๊ฒƒ์ด ํ”„๋ก ํŠธ์—”๋“œ์˜ ๋‹ค์Œ ๋ชฉ์ ์ง€, ๋ธŒ๋ฆฟ์ง€ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ํŒจํ„ด ์ž…๋‹ˆ๋‹ค.


๐Ÿ ๋“œ๋””์–ด, ๋Œ€๋‹จ์› ์ด์ •๋ฆฌ

์ง€๊ธˆ๊นŒ์ง€ ์‹ ์ž… '์˜์ฒ '์ด๊ฐ€ ๊ฒช์€ ๋ชจ๋“  ๋ฆฌ์•กํŠธ์˜ ํ•จ์ •๊ณผ, ๋ฆฌ๋“œ '์˜ํ˜ธ'๊ฐ€ ์•Œ๋ ค์ค€ ์‹œ๋‹ˆ์–ด์˜ ํ†ต์ œ ๊ธฐ์ˆ ์„ ๋ชฉ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.

  1. ์ƒํƒœ ๊ด€๋ฆฌ์˜ ์ฐฉ๊ฐ (๊ฐ€์ด๋“œ 1~4): ์ƒํƒœ๋Š” ๋ Œ๋”๋ง ์Šค๋ƒ…์ƒท์ด๋‹ค. ๋ถˆ๋ณ€์„ฑ์€ ํ™”๋ฉด์„ ์ƒˆ๋กœ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•œ ์‹ ํ˜ธํƒ„์ด๋‹ค. ํ•จ๋ถ€๋กœ ์ „์—ญ ๋„๊ตฌ๋ฅผ ์น˜๋•์น˜๋• ๋ฐ”๋ฅด๊ธฐ ์ „์— "State Colocation(๋ฐ‘๋™์œผ๋กœ ๋ฐ€์–ด๋‚ด๊ธฐ)"์„ ์‹ค์ฒœํ•˜๋ผ.
  2. ์ดํŽ™ํŠธ์™€ ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฏธ๋“œ (๊ฐ€์ด๋“œ 5~8): useEffect๋Š” ๋งˆ์šดํŠธ ์‹œ์  ์ฝœ๋ฐฑ์„ ๋ชจ์•„๋‘๋Š” ์žฅ์†Œ์ด ์•„๋‹ˆ๋ผ, ๋ฆฌ์•กํŠธ ์™ธ๋ถ€ ์˜์—ญ(DOM API, ์„œ๋ฒ„ ๋™๊ธฐํ™”)๊ณผ ์ˆ˜์œ„๋ฅผ ๋งž์ถ”๋Š” ๋™๊ธฐํ™” ์ง€์ ๋‹ค.
  3. ์ตœ์ ํ™” ๊ฐ•๋ฐ•์˜ ํ•ด์ฒด (๊ฐ€์ด๋“œ 9~11): useMemo๋‚˜ useCallback์œผ๋กœ ๋ง‰์žฅ ๋ฐฉ์–ด๋ฅผ ์งœ๊ธฐ ์ „์—, "์ปดํฌ๋„ŒํŠธ ์ชผ๊ฐœ๊ธฐ + Children ํ•ฉ์„ฑ + Context State/Action ๋ถ„๋‹จ" ์ด๋ผ๋Š” ์˜ํ˜ธ์˜ ๊ทผ์›์  ์•„ํ‚คํ…์ฒ˜ ์ˆ˜์ˆ ๋ฒ•์„ ๋“ค์ด๋ฐ€์–ด๋ผ.
  4. ์ฐจ์„ธ๋Œ€ ๋””์ž์ธ ์บก์Аํ™” (๊ฐ€์ด๋“œ 12~14): ์ œ์–ด๊ถŒ์„ ๋ถ€๋ชจ๋กœ ๋‹ค ๋‚ด๋˜์ง€๊ณ (IoC), ์ปดํŒŒ์šด๋“œ ๋ธ”๋ก์„ ์—ญํ• ๋ณ„๋กœ ๋‚˜๋ˆ„๊ณ , Headless Hook๋กœ ๋กœ์ง ์ฝ”์–ด๋ฅผ ์™„๋ฒฝํžˆ ์ ์ถœํ•˜๋ฉด ๊ทธ ์–ด๋–ค ๋””์ž์ธ์ด ๋ฐ”๋€Œ์–ด๋„ ๋‘๋ ต์ง€ ์•Š๋‹ค.
  5. ์„œ๋ฒ„๋กœ ๊ท€ํ™˜ (ํ˜„์žฌ ๊ฐ€์ด๋“œ 15): ์ด์ œ ๋ฆฌ์•กํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ €๋ผ๋Š” ๊ฐ์˜ฅ์„ ํƒˆ์ถœํ•ด ์„œ๋ฒ„๊นŒ์ง€ ์ง‘์–ด์‚ผ์ผฐ๋‹ค. ์˜ํ˜ธ์™€ ์˜์ฒ ์ด๋Š” ๋ฐ”์•ผํ๋กœ RSC ๋ผ๋Š” ์ƒˆ๋กœ์šด ๋Œ€๋ฅ™์— ๋„๋‹ฌํ–ˆ๋‹ค.

๋‹จ์–ธ์ปจ๋Œ€, ๋‹น์‹ ์ด 15๊ฐ•๊นŒ์ง€์˜ ์ฝ”๋“œ๋ฅผ ๋ˆˆ์œผ๋กœ ์ข‡์œผ๋ฉฐ ๊ณ ๊ฐœ๋ฅผ ๋„๋•์˜€๋‹ค๋ฉด, ๋‹น์‹ ์€ ์ด๋ฏธ ๋‹จ์ˆœํ•œ '์ฝ”๋”'๋ฅผ ๋„˜์–ด ์‹œ์Šคํ…œ์˜ ๋ณ‘๋ชฉ์„ ์ง„๋‹จํ•˜๊ณ  ๋ถ€์ˆด๋ฒ„๋ฆฌ๋Š” '5๋…„ ์ฐจ ํ”„๋ก ํŠธ์—”๋“œ ์„ค๊ณ„์ž'์˜ ๋‡Œ๋ฅผ ์žฅ์ฐฉํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋™์•ˆ ๊ธฐ๋‚˜๊ธด ๋Œ€์žฅ์ •์„ ํ•จ๊ป˜ํ•œ ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ์ „๋Œ€์›์—๊ฒŒ ๋ฐ•์ˆ˜๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค! ์ฝ”๋”ฉ์˜ ์ถ•๋ณต์ด ๋‹น์‹ ์˜ ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ๊ณผ ํ•จ๊ป˜ํ•˜๊ธฐ๋ฅผ.

๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ(์—ํ•„๋กœ๊ทธ) ํ€ด์ฆˆ

Q1. ์˜์ฒ ์ด๊ฐ€ App Router์˜ ์ตœ์ƒ๋‹จ layout.tsx์— ์Šต๊ด€์ฒ˜๋Ÿผ 'use client'๋ฅผ ๋ถ™์ด๋ฉด ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋‚˜์š”?

โœ… ์ •๋‹ต: ์ƒ์œ„ ๊ฒฝ๊ณ„ ์•„๋ž˜์˜ ๋งŽ์€ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค๋กœ ๋”ฐ๋ผ ๋‚ด๋ ค๊ฐ€ JS ๋‹ค์šด๋กœ๋“œ์™€ hydration ๋น„์šฉ์ด ์ปค์ง„๋‹ค

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: 'use client'๋Š” ํŒŒ์ผ ํ•˜๋‚˜์˜ ํŽธ์˜ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ฐ€๋ฅด๋Š” ๋ฒˆ๋“ค ๊ฒฝ๊ณ„์ž…๋‹ˆ๋‹ค. ์˜ํ˜ธ๊ฐ€ ๋งํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ ์กฐํšŒ, ๋งˆํฌ๋‹ค์šด ๋ณ€ํ™˜, ์ •์  ๋ ˆ์ด์•„์›ƒ์€ ์„œ๋ฒ„์— ๋‚จ๊ธฐ๊ณ  ๋ฒ„ํŠผ์ด๋‚˜ ์ž…๋ ฅ์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ € ์ƒํ˜ธ์ž‘์šฉ์ด ํ•„์š”ํ•œ leaf๋งŒ ํด๋ผ์ด์–ธํŠธ๋กœ ๋‚ด๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: ์—๋Ÿฌ๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค๋Š” ์ด์œ ๋กœ ๊ฒฝ๊ณ„๋ฅผ ์œ„๋กœ ์˜ฌ๋ฆฌ๋ฉด RSC์˜ ์žฅ์ ์ธ ์ž‘์€ ๋ฒˆ๋“ค, ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ, ๋‚ฎ์€ hydration ๋น„์šฉ์„ ์žƒ์Šต๋‹ˆ๋‹ค.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ํด๋ผ์ด์–ธํŠธ ๊ฒฝ๊ณ„๋Š” ํŽธ์˜๊ฐ€ ์•„๋‹ˆ๋ผ ๋น„์šฉ์ž…๋‹ˆ๋‹ค.

Q2. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

โœ… ์ •๋‹ต: useState, useEffect, onClick์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ € ์ƒํƒœ์™€ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ์— ์˜์กดํ•˜๋Š” ์ƒํ˜ธ์ž‘์šฉ ๋กœ์ง

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ํ˜„์žฌ ํด๋ฆญ, ํฌ์ปค์Šค, ์ฐฝ ํฌ๊ธฐ, ๋กœ์ปฌ ์ƒํƒœ๋ฅผ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์˜์ˆ™์ด ์š”๊ตฌํ•œ ์ข‹์•„์š” ๋ฒ„ํŠผ์ฒ˜๋Ÿผ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๋งŒ์ง€๋Š” ๋ถ€๋ถ„์€ ์ž‘์€ Client Component๋กœ ๋ถ„๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ HTML์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•ด์„œ ๋ธŒ๋ผ์šฐ์ € ์ด๋ฒคํŠธ๊นŒ์ง€ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ์„œ๋ฒ„๋Š” ์ค€๋น„ํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฐ˜์‘ํ•ฉ๋‹ˆ๋‹ค.

Q3. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์— ๊ฐ’์„ ๋„˜๊ธธ ๋•Œ ํ™•์ธํ•ด์•ผ ํ•  ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์กฐ๊ฑด์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

โœ… ์ •๋‹ต: ๋„คํŠธ์›Œํฌ ๊ฒฝ๊ณ„๋ฅผ ์ง€๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ๋งŒ props๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: RSC ๊ฒฝ๊ณ„๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ฒฝ๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์—์„œ ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „๋‹ฌ๋˜๋Š” ๋ฐ์ดํ„ฐ ๊ฒฝ๊ณ„์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜, DB ์ปค๋„ฅ์…˜, ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์ฒ˜๋Ÿผ ์‹คํ–‰ ํ™˜๊ฒฝ์— ๋ฌถ์ธ ๊ฐ’์€ ๊ทธ๋Œ€๋กœ ๋„˜๊ธธ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ฒŒ์‹œ๊ธ€ ๋ฐ์ดํ„ฐ์ฒ˜๋Ÿผ JSON์œผ๋กœ ํ‘œํ˜„ ๊ฐ€๋Šฅํ•œ ๊ฐ’์€ ๊ดœ์ฐฎ์ง€๋งŒ, ์„œ๋ฒ„์—์„œ๋งŒ ์˜๋ฏธ ์žˆ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ๋“ค๊ณ  ๊ฐ€๋ ค ํ•˜๋ฉด ๊ฒฝ๊ณ„๊ฐ€ ๋ฌด๋„ˆ์ง‘๋‹ˆ๋‹ค.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: props๋Š” ์‹คํ–‰ ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ „๋‹ฌ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

15๊ฐ• ๋Œ€์žฅ์ •์„ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ ๊ฐ€์žฅ ํฌ๊ฒŒ ๋ฐ”๋€ ์ƒ๊ฐ์€ ํ•˜๋‚˜๋‹ค. use client๋Š” ์—๋Ÿฌ๋ฅผ ์—†์• ๋Š” ์ฃผ๋ฌธ์ด ์•„๋‹ˆ๋ผ ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์„œ๋ฒ„์™€ ์‚ฌ์šฉ์ž ๋ธŒ๋ผ์šฐ์ € ์‚ฌ์ด์— ๋†“๋Š” ์‹ค์ œ ๊ฒฝ๊ณ„์„ ์ด์—ˆ๋‹ค. ์˜ˆ์ „์˜ ๋‚˜๋Š” "๋ฒ„ํŠผ ํ•˜๋‚˜ ๋•Œ๋ฌธ์— ๊ท€์ฐฎ์œผ๋‹ˆ ์œ„์— ๋ถ™์ด๋ฉด ๋˜๊ฒ ์ง€"๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ์ด์ œ๋Š” ๊ทธ ํ•œ ์ค„์ด ์˜์ˆ™์ด ๋งŒ๋“  ํ™”๋ฉด์˜ ๋กœ๋”ฉ๊ฐ๊ณผ ์˜์ˆ˜๊ฐ€ ๋ณด๋Š” ์šด์˜ ๋น„์šฉ๊นŒ์ง€ ๋ฐ”๊พผ๋‹ค๋Š” ๊ฑธ ์•ˆ๋‹ค.

๐Ÿ’ก "๋ฌด๊ฑฐ์šด ๋ฐ์ดํ„ฐ ์ ‘๊ทผ๊ณผ ์ •์  ๊ตฌ์กฐ๋Š” ์„œ๋ฒ„์— ๋‚จ๊ธฐ๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๋งŒ์ง€๋Š” ์ž‘์€ ์กฐ๊ฐ๋งŒ ํด๋ผ์ด์–ธํŠธ๋กœ ๋‚ด๋ ค๋ณด๋‚ด๋ผ."

์˜ํ˜ธ๋Š” ์˜ค๋Š˜๋„ ๋‹ต์„ ๋Œ€์‹  ์ฃผ๊ธฐ๋ณด๋‹ค ํŒ๋‹จ ๊ธฐ์ค€์„ ๋‚จ๊ฒผ๋‹ค. ๋ Œ๋”๋ง, ์ƒํƒœ, ์ดํŽ™ํŠธ, ํ•ฉ์„ฑ, ์ ‘๊ทผ์„ฑ, ๊ทธ๋ฆฌ๊ณ  RSC๊นŒ์ง€ ์ง€๋‚˜์˜ค๋ฉด์„œ ๋‚˜๋Š” React๋ฅผ ๋ฌธ๋ฒ• ๋ฌถ์Œ์ด ์•„๋‹ˆ๋ผ ๋น„์šฉ๊ณผ ์ฑ…์ž„์„ ๋ฐฐ์น˜ํ•˜๋Š” ๋„๊ตฌ๋กœ ๋ณด๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ์ด์ œ ์ ์–ด๋„ "์–ด๋””์—์„œ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š”๊ฐ€"๋ฅผ ๋จผ์ € ๋ฌป๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์—ˆ๋‹ค.