[๐Ÿค–] Next.js 13+ Server Components์™€ Client Components, ์™„๋ฒฝ ์ดํ•ดํ•˜๊ธฐ

Next.js App Router์˜ ํ•ต์‹ฌ์ธ Server Components์™€ Client Components์˜ ๊ฐœ๋…, ์ฐจ์ด์ , ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค, ๊ทธ๋ฆฌ๊ณ  ์‹ค์งˆ์ ์ธ ์„ฑ๋Šฅ ์ด์ ๊ณผ ์ฃผ์˜์‚ฌํ•ญ์„ ์ž์„ธํžˆ ์•Œ์•„๋ด์š”.

15๋ถ„
๋‹จ์–ด: 1,310๊ฐœ
๊ฒŒ์‹œ๊ธ€ ์ธ๋„ค์ผ
์ •๋ณด

Next.js App Router์˜ Server Components์™€ Client Components๋Š” ์›น ๊ฐœ๋ฐœ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ๋ณ€ํ™”์‹œํ‚ค๋Š” ์ค‘์š”ํ•œ ๊ฐœ๋…์ด์—์š”. ์ด ๊ธ€์—์„œ๋Š” ๋‘ ์ปดํฌ๋„ŒํŠธ์˜ ์ฐจ์ด์ ๊ณผ ์‚ฌ์šฉ๋ฒ•, ๊ทธ๋ฆฌ๊ณ  ์‹ค๋ฌด์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์ ํ™” ์ „๋žต์„ ์‹ฌ๋„ ์žˆ๊ฒŒ ๋‹ค๋ค„๋ณผ๊ฒŒ์š”.

๐Ÿค” ๋ฌธ์ œ/๋ฐฐ๊ฒฝ

0๏ธโƒฃ ์™œ ์ด ์ฃผ์ œ๋ฅผ ๋‹ค๋ฃจ๋Š”๊ฐ€

Next.js 13 ๋ฒ„์ „๋ถ€ํ„ฐ ๋„์ž…๋œ App Router๋Š” ๋ฆฌ์•กํŠธ ์ƒํƒœ๊ณ„์— ํฐ ๋ณ€ํ™”๋ฅผ ๊ฐ€์ ธ์™”์–ด์š”. ํŠนํžˆ Server Components์™€ Client Components๋ผ๋Š” ์ƒˆ๋กœ์šด ๊ฐœ๋…์€ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ๋งŽ์€ ํ˜ผ๋ž€์„ ์ฃผ๊ธฐ๋„ ํ–ˆ์–ด์š”. ์ด ๋‘ ๊ฐ€์ง€ ์ปดํฌ๋„ŒํŠธ ํƒ€์ž…์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์€ App Router ๊ธฐ๋ฐ˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํšจ์œจ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ  ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐ ํ•„์ˆ˜์ ์ธ ๋ถ€๋ถ„์ด์—์š”. ์ž˜๋ชป๋œ ์‚ฌ์šฉ์€ ์˜คํžˆ๋ ค ์„ฑ๋Šฅ ์ €ํ•˜๋‚˜ ๊ฐœ๋ฐœ ๋ณต์žก์„ฑ์„ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋ฒˆ ๊ธฐํšŒ์— ์ œ๋Œ€๋กœ ํŒŒ์•…ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์–ด์š”.

1๏ธโƒฃ ๊ธฐ์กด ๋ฐฉ์‹์˜ ํ•œ๊ณ„

๊ธฐ์กด React ๊ฐœ๋ฐœ ๋ฐฉ์‹์ด๋‚˜ Next.js Pages Router์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํด๋ผ์ด์–ธํŠธ์—์„œ Hydration ๊ณผ์ •์„ ๊ฑฐ์ณ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ฒŒ ๋ผ์š”. ์ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•œ๊ณ„๋ฅผ ๊ฐ€์กŒ์–ด์š”.

  • ์ดˆ๊ธฐ ๋กœ๋”ฉ ์„ฑ๋Šฅ ์ €ํ•˜: ๋ชจ๋“  JavaScript ์ฝ”๋“œ๊ฐ€ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†ก๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ๊ฐ€ ์ปค์ง€๊ณ , ์ด๋Š” TTI(Time To Interactive) ์ง€์—ฐ์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์—ˆ์–ด์š”.
  • ์„œ๋ฒ„ ๋ฆฌ์†Œ์Šค ํ™œ์šฉ์˜ ์–ด๋ ค์›€: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ์ด๋‚˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์‚ฌ์šฉ ๋“ฑ ์„œ๋ฒ„ ์ „์šฉ ๋กœ์ง์„ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ง์ ‘ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์–ด๋ ค์› ๊ณ , API ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹๋งŒ ๊ฐ€๋Šฅํ–ˆ์–ด์š”.
  • Hydration ์˜ค๋ฒ„ํ—ค๋“œ: ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์ด ์—†๋Š” ์ •์ ์ธ UI์ž„์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , Hydration์„ ์œ„ํ•œ JavaScript ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•ด์„œ ๋ถˆํ•„์š”ํ•œ ๋น„์šฉ์ด ๋ฐœ์ƒํ–ˆ์–ด์š”.

์ด๋Ÿฌํ•œ ํ•œ๊ณ„์ ๋“ค์€ ํŠนํžˆ ์ดˆ๊ธฐ ๋กœ๋”ฉ ์„ฑ๋Šฅ๊ณผ SEO๊ฐ€ ์ค‘์š”ํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํฐ ๊ฑธ๋ฆผ๋Œ์ด ๋˜๊ณค ํ–ˆ์–ด์š”.

โš™๏ธ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

0๏ธโƒฃ ํ•ต์‹ฌ ์•„์ด๋””์–ด: Server Components์™€ Client Components์˜ ํƒ„์ƒ

React ํŒ€์€ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ์ ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด React Server Components(RSC) RFC๋ฅผ ๋ฐœํ‘œํ–ˆ๊ณ , Next.js๋Š” App Router๋ฅผ ํ†ตํ•ด ์ด๋ฅผ ์ ๊ทน์ ์œผ๋กœ ๋„์ž…ํ–ˆ์–ด์š”. ํ•ต์‹ฌ ์•„์ด๋””์–ด๋Š” ๊ฐ„๋‹จํ•ด์š”.

  • Server Components: ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋˜๊ณ , ์ตœ์ข… HTML ํ˜•ํƒœ๋กœ ํด๋ผ์ด์–ธํŠธ์— ์ „์†ก๋ผ์š”. JavaScript ๋ฒˆ๋“ค์— ํฌํ•จ๋˜์ง€ ์•Š์•„ ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ  ์ดˆ๊ธฐ ๋กœ๋”ฉ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œ์ผœ์š”. ๋ฐ์ดํ„ฐ ํŽ˜์นญ, ์„œ๋ฒ„ ์ „์šฉ ๋กœ์ง, SEO์— ์œ ๋ฆฌํ•œ ์ •์  ์ฝ˜ํ…์ธ  ํ‘œ์‹œ์— ์ ํ•ฉํ•ด์š”.
  • Client Components: ๊ธฐ์กด React ์ปดํฌ๋„ŒํŠธ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ Œ๋”๋ง๋˜๊ณ  Hydration ๊ณผ์ •์„ ๊ฑฐ์ณ ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์„ ์ฒ˜๋ฆฌํ•ด์š”. useState, useEffect์™€ ๊ฐ™์€ ํ›…์ด๋‚˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํ•„์š”ํ•œ ๋™์ ์ธ UI์— ์‚ฌ์šฉ๋ผ์š”.
์ •๋ณด

๊ธฐ๋ณธ์ ์œผ๋กœ App Router์˜ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” Server Components๋กœ ๊ฐ„์ฃผ๋ผ์š”. ๋ช…์‹œ์ ์œผ๋กœ "use client" ์ง€์‹œ์ž๋ฅผ ์„ ์–ธํ•ด์•ผ๋งŒ Client Components๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

1๏ธโƒฃ Server Components์˜ ํŠน์ง•๊ณผ ์‚ฌ์šฉ

Server Components๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ ธ์š”.

  • ์„œ๋ฒ„์—์„œ ์‹คํ–‰: ์ปดํฌ๋„ŒํŠธ์˜ ์ฝ”๋“œ๊ฐ€ ํด๋ผ์ด์–ธํŠธ JavaScript ๋ฒˆ๋“ค์— ํฌํ•จ๋˜์ง€ ์•Š์•„์š”.
  • ๋ฐ์ดํ„ฐ ํŽ˜์นญ์— ์ตœ์ ํ™”: async/await๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ์™ธ๋ถ€ API์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด์š”.
  • ํŒŒ์ผ ์‹œ์Šคํ…œ ์ ‘๊ทผ: ์„œ๋ฒ„ ์ „์šฉ API(์˜ˆ: fs ๋ชจ๋“ˆ)๋‚˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜(process.env)์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ๋ณด์•ˆ ๊ฐ•ํ™”: ๋ฏผ๊ฐํ•œ ์ •๋ณด(API ํ‚ค ๋“ฑ)๊ฐ€ ํด๋ผ์ด์–ธํŠธ์— ๋…ธ์ถœ๋  ์œ„ํ—˜์ด ์ค„์–ด๋“ค์–ด์š”.
  • ์ œ๋กœ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ: ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†ก๋˜๋Š” JavaScript๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ๊ฐ€ ๊ฐ์†Œํ•˜๊ณ  ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋นจ๋ผ์ ธ์š”.

์–ธ์ œ Server Components๋ฅผ ์‚ฌ์šฉํ•˜๋‚˜์š”?

  • ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ํ‘œ์‹œํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ (e.g., ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ, ์ƒํ’ˆ ๋ชฉ๋ก).
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ง์ ‘ ์ ‘๊ทผํ•ด์•ผ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ.
  • ์„œ๋ฒ„ ์ „์šฉ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•ด์•ผ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ.
  • ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์ด ํ•„์š” ์—†๋Š” ์ •์ ์ธ UI ๋ถ€๋ถ„.
  • SEO์— ์ค‘์š”ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋‚˜ ์ฝ˜ํ…์ธ ๋ฅผ ํฌํ•จํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ.

2๏ธโƒฃ Client Components์˜ ํŠน์ง•๊ณผ ์‚ฌ์šฉ

Client Components๋Š” Server Components์™€ ๋‹ฌ๋ฆฌ ํด๋ผ์ด์–ธํŠธ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜๊ณ  Hydration ๊ณผ์ •์„ ๊ฑฐ์ณ์š”.

  • ํด๋ผ์ด์–ธํŠธ์—์„œ ์‹คํ–‰: ๋ธŒ๋ผ์šฐ์ € API(e.g., window, localStorage)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ์ƒํ˜ธ์ž‘์šฉ ์ฒ˜๋ฆฌ: useState, useEffect, useRef ๋“ฑ์˜ React ํ›…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ ๊ด€๋ฆฌ, ์ƒ๋ช… ์ฃผ๊ธฐ ์ด๋ฒคํŠธ, ์‚ฌ์šฉ์ž ์ž…๋ ฅ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์š”.
  • ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ: onClick, onChange ๋“ฑ์˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ ์ธ UI๋ฅผ ๋งŒ๋“ค์–ด์š”.
  • ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ์ฆ๊ฐ€: ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค์— ํฌํ•จ๋˜๋ฏ€๋กœ ๋„ˆ๋ฌด ๋งŽ์€ Client Components๋Š” ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ์ฆ๊ฐ€๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์–ด์š”.

์–ธ์ œ Client Components๋ฅผ ์‚ฌ์šฉํ•˜๋‚˜์š”?

  • ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ (e.g., ์นด์šดํ„ฐ, ํผ ์ž…๋ ฅ).
  • ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ (e.g., ๋ฒ„ํŠผ ํด๋ฆญ, ๋“œ๋ž˜๊ทธ์•ค๋“œ๋กญ).
  • ๋ธŒ๋ผ์šฐ์ € API์— ์ ‘๊ทผํ•ด์•ผ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ (e.g., Geolocation, WebRTC).
  • Suspense๋ฅผ ํ™œ์šฉํ•œ ๋กœ๋”ฉ UI.
  • ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(e.g., ์ฐจํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ๋ชจ๋‹ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ.

3๏ธโƒฃ ์ƒํ˜ธ์ž‘์šฉ ๋ฐ ํ˜ผ์šฉ ๋ฐฉ๋ฒ•

Server Components์™€ Client Components๋Š” ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ๋•Œ ๊ฐ•๋ ฅํ•œ ์‹œ๋„ˆ์ง€๋ฅผ ๋ฐœํœ˜ํ•ด์š”. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ทœ์น™์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•„์š”.

  • Server Component๋Š” Client Component๋ฅผ ์ž„ํฌํŠธํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ทธ๋ฆฌ๊ณ  Client Component์—๊ฒŒ props๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • Client Component๋Š” Server Component๋ฅผ ์ง์ ‘ ์ž„ํฌํŠธํ•  ์ˆ˜ ์—†์–ด์š”. ๋Œ€์‹ , Server Component์—์„œ Client Component์˜ children prop์œผ๋กœ Server Component์˜ ๋‚ด์šฉ์„ ์ „๋‹ฌํ•˜๋Š” ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
๊ฒฝ๊ณ 

Client Component ๋‚ด๋ถ€์—์„œ "use client" ์ง€์‹œ์ž ์—†์ด Server Component์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ ์˜๋„ํ•˜์ง€ ์•Š์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์–ด์š”. ํŠนํžˆ ์„œ๋ฒ„ ์ „์šฉ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ ‘๊ทผ ๋“ฑ์€ Client Component์—์„œ ์ ˆ๋Œ€ ํ•˜๋ฉด ์•ˆ ๋ผ์š”.

๐Ÿงช ์˜ˆ์‹œ

0๏ธโƒฃ ์ฝ”๋“œ/์„ค์ • ์˜ˆ์‹œ

์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด Server Components์™€ Client Components์˜ ์‚ฌ์šฉ๋ฒ•๊ณผ ์ƒํ˜ธ์ž‘์šฉ ๋ฐฉ์‹์„ ์•Œ์•„๋ณผ๊ฒŒ์š”.

๐Ÿ“ app/page.tsx (Server Component)

์ด ์ปดํฌ๋„ŒํŠธ๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ํ‘œ์‹œํ•˜๊ณ , Client Component๋ฅผ ์ž์‹์œผ๋กœ ํฌํ•จํ•˜๊ณ  ์žˆ์–ด์š”. async ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”.

// app/page.tsx import ClientCounter from './client-counter'; // Client Component ์ž„ํฌํŠธ async function getMessage() { // ์‹ค์ œ ๋ฐฑ์—”๋“œ API ํ˜ธ์ถœ์ด๋‚˜ DB ์ ‘๊ทผ์ด ์ผ์–ด๋‚˜๋Š” ๋ถ€๋ถ„์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ด์š”. const response = await fetch('https://api.example.com/message'); const data = await response.json(); return data.message; } export default async function HomePage() { const message = await getMessage(); // ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ ํŽ˜์นญ console.log('Server Log: Rendering HomePage'); // ์„œ๋ฒ„ ์ฝ˜์†”์—๋งŒ ์ฐํ˜€์š”. return ( <main> <h1>Server Component์—์„œ ๊ฐ€์ ธ์˜จ ๋ฉ”์‹œ์ง€:</h1> <p>{message}</p> <ClientCounter initialCount={10} /> {/* Server Component๊ฐ€ Client Component๋ฅผ ๋ Œ๋”๋งํ•ด์š” */} <section> <h2>์ด ์„น์…˜์€ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋œ ์ •์ ์ธ ๋ถ€๋ถ„์ด์—์š”.</h2> <p>์–ด๋–ค ์ƒํ˜ธ์ž‘์šฉ๋„ ์—†์ด ๋น ๋ฅด๊ฒŒ ๋กœ๋“œ๋  ๊ฑฐ์˜ˆ์š”.</p> </section> </main> ); }

๐Ÿ“ app/client-counter.tsx (Client Component)

์ด ์ปดํฌ๋„ŒํŠธ๋Š” ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์ด ํ•„์š”ํ•œ ์นด์šดํ„ฐ ์ปดํฌ๋„ŒํŠธ์˜ˆ์š”. ๋ฐ˜๋“œ์‹œ ํŒŒ์ผ ์ƒ๋‹จ์— "use client" ์ง€์‹œ์ž๊ฐ€ ํ•„์š”ํ•ด์š”.

// app/client-counter.tsx 'use client'; // Client Component์ž„์„ ๋ช…์‹œํ•ด์š”. import { useState } from 'react'; export default function ClientCounter({ initialCount }: { initialCount: number }) { const [count, setCount] = useState(initialCount); console.log('Client Log: Rendering ClientCounter'); // ๋ธŒ๋ผ์šฐ์ € ์ฝ˜์†”์—๋งŒ ์ฐํ˜€์š”. return ( <div style={{ border: '1px solid gray', padding: '1rem', margin: '1rem 0' }}> <h2>Client Component (์ƒํ˜ธ์ž‘์šฉ ๊ฐ€๋Šฅ)</h2> <p>ํ˜„์žฌ ์นด์šดํŠธ: {count}</p> <button onClick={() => setCount(count + 1)}>์ฆ๊ฐ€</button> <button onClick={() => setCount(count - 1)}>๊ฐ์†Œ</button> </div> ); }

๐Ÿ“ app/layout.tsx (Root Layout, Server Component)

layout.tsx ํŒŒ์ผ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ Server Component๋กœ ๋™์ž‘ํ•ด์š”. ์ด๋Š” ์ „์ฒด ๋ ˆ์ด์•„์›ƒ์ด ์„œ๋ฒ„์—์„œ ํ•œ ๋ฒˆ ๊ตฌ์„ฑ๋˜๊ณ , ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ด์š”.

// app/layout.tsx import './globals.css'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="ko"> <body>{children}</body> </html> ); }

1๏ธโƒฃ ์ ์šฉ ๊ฒฐ๊ณผ ๋ฐ ์ฃผ์˜์‚ฌํ•ญ

  • ์ดˆ๊ธฐ ๋กœ๋”ฉ ์ตœ์ ํ™”: HomePage์˜ <main> ํƒœ๊ทธ์™€ <section> ํƒœ๊ทธ ๋‚ด์šฉ์€ ์„œ๋ฒ„์—์„œ HTML๋กœ ๋ฏธ๋ฆฌ ๋ Œ๋”๋ง๋˜์–ด ์ „์†ก๋˜๋ฏ€๋กœ, ์ดˆ๊ธฐ ๋กœ๋”ฉ ์‹œ JavaScript ๋ฒˆ๋“ค ์—†์ด ๋น ๋ฅด๊ฒŒ ํ™”๋ฉด์— ํ‘œ์‹œ๋ผ์š”. getMessage ํ•จ์ˆ˜๋Š” ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค์— ํฌํ•จ๋˜์ง€ ์•Š์•„์š”.
  • ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ ๊ฐ์†Œ: client-counter.tsx๋งŒ ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค์— ํฌํ•จ๋˜๊ณ , ๋‚˜๋จธ์ง€ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ์ฝ”๋“œ๋Š” ํฌํ•จ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ „๋ฐ˜์ ์ธ ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค ์‚ฌ์ด์ฆˆ๊ฐ€ ์ค„์–ด๋“ค์–ด์š”.
  • Hydration: ClientCounter ์ปดํฌ๋„ŒํŠธ๋งŒ ํด๋ผ์ด์–ธํŠธ์—์„œ Hydration ๊ณผ์ •์„ ๊ฑฐ์ณ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ผ์š”. HomePage์˜ ์ •์ ์ธ ๋ถ€๋ถ„์€ Hydration ์—†์ด๋„ ๋™์ž‘ํ•ด์š”.
์œ ์šฉํ•œ ํŒ

Server Component๊ฐ€ Client Component์˜ children์„ ๋ฐ›๋Š” ํŒจํ„ด์€ ๊ต‰์žฅํžˆ ๊ฐ•๋ ฅํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ClientWrapper๋ผ๋Š” Client Component๊ฐ€ ์žˆ๊ณ , ๊ทธ ์•ˆ์— ServerContent๋ผ๋Š” Server Component๋ฅผ ๋„ฃ๊ณ  ์‹ถ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”.

// app/client-wrapper.tsx 'use client'; import React from 'react'; export default function ClientWrapper({ children }: { children: React.ReactNode }) { // ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ ๊ด€๋ฆฌ ๋กœ์ง... return ( <div className="client-boundary"> <p>์ด๊ฒƒ์€ Client Component์ž…๋‹ˆ๋‹ค.</p> {children} {/* children์€ Server Component์ผ ์ˆ˜ ์žˆ์–ด์š”! */} </div> ); } // app/page.tsx (Server Component) import ClientWrapper from './client-wrapper'; export default function HomePage() { return ( <ClientWrapper> <p>์ด๊ฒƒ์€ ClientWrapper์˜ ์ž์‹์œผ๋กœ ๋“ค์–ด๊ฐ„ Server Component ๋‚ด์šฉ์ด์—์š”!</p> </ClientWrapper> ); }

์ด ํŒจํ„ด์€ Client Component์˜ ์ƒํ˜ธ์ž‘์šฉ ๋ฒ”์œ„ ๋‚ด์— Server Component์˜ ์ •์ ์ธ ์ตœ์ ํ™” ์ด์ ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด์„œ ๋งค์šฐ ์œ ์šฉํ•ด์š”.

๐Ÿ“ ์ •๋ฆฌ

0๏ธโƒฃ ํ•ต์‹ฌ ์š”์•ฝ

Next.js App Router์˜ Server Components์™€ Client Components๋Š” ์—ญํ• ์ด ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์–ด์š”.

  • Server Components:
    • ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋˜๊ณ  HTML๋กœ ์ „์†ก๋ผ์š”.
    • ๋ฐ์ดํ„ฐ ํŽ˜์นญ, ์„œ๋ฒ„ ์ „์šฉ ๋กœ์ง, ํŒŒ์ผ ์‹œ์Šคํ…œ ์ ‘๊ทผ์— ์œ ๋ฆฌํ•ด์š”.
    • ํด๋ผ์ด์–ธํŠธ ๋ฒˆ๋“ค ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ  ์ดˆ๊ธฐ ๋กœ๋”ฉ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œ์ผœ์š”.
    • ๊ธฐ๋ณธ๊ฐ’์ด์—์š”.
  • Client Components:
    • ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ Œ๋”๋ง๋˜๊ณ  Hydration์„ ๊ฑฐ์ณ ์ƒํ˜ธ์ž‘์šฉ์„ ์ฒ˜๋ฆฌํ•ด์š”.
    • useState, useEffect, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ, ๋ธŒ๋ผ์šฐ์ € API ์ ‘๊ทผ์— ์‚ฌ์šฉ๋ผ์š”.
    • ํŒŒ์ผ ์ƒ๋‹จ์— 'use client' ์ง€์‹œ์ž๊ฐ€ ํ•„์š”ํ•ด์š”.

์ด ๋‘˜์˜ ์ ์ ˆํ•œ ์กฐํ•ฉ์€ ์„ฑ๋Šฅ๊ณผ ๊ฐœ๋ฐœ ํŽธ์˜์„ฑ์„ ๋™์‹œ์— ์žก์„ ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์˜ˆ์š”. ์ตœ๋Œ€ํ•œ Server Components๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ , ์ƒํ˜ธ์ž‘์šฉ์ด ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ๋ถ€๋ถ„๋งŒ Client Components๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์ „๋žต์ด์—์š”.

1๏ธโƒฃ ๋‹ค์Œ ์•ก์…˜

  • Next.js ๊ณต์‹ ๋ฌธ์„œ์˜ Server Components ์„น์…˜์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ๊ผผ๊ผผํžˆ ์ฝ์–ด๋ณด์„ธ์š”.
  • Next.js ์บ์‹ฑ ์ „๋žต(๋ฐ์ดํ„ฐ ์บ์‹ฑ, Full Route Cache ๋“ฑ)๊ณผ Server Components๊ฐ€ ์–ด๋–ป๊ฒŒ ์‹œ๋„ˆ์ง€๋ฅผ ๋‚ด๋Š”์ง€ ์ถ”๊ฐ€์ ์œผ๋กœ ํ•™์Šตํ•ด ๋ณด์„ธ์š”.
  • ์ŠคํŠธ๋ฆฌ๋ฐ(Streaming)๊ณผ Suspense๊ฐ€ Server Components์˜ ์ ์ง„์  ๋ Œ๋”๋ง๊ณผ ์–ด๋–ป๊ฒŒ ์—ฐ๊ด€๋˜๋Š”์ง€ ์•Œ์•„๋ณด๋Š” ๊ฒƒ๋„ ํฐ ๋„์›€์ด ๋  ๊ฑฐ์˜ˆ์š”.

๐Ÿ“ฎ ์ฐธ๊ณ 

์—ฐ๊ด€๋œ ํฌ์ŠคํŠธ