Next.js App Router / server, client - components

TH_velogยท2024๋…„ 3์›” 19์ผ
0

Nextjs

๋ชฉ๋ก ๋ณด๊ธฐ
2/2
post-thumbnail
post-custom-banner

โœ๏ธ ๊ธฐ๋ก.

๐Ÿ“Œ App Router

๐Ÿ“ ๋ฒ„์ „ 13์—์„œ Next.js ๊ณต์œ  ๋ ˆ์ด์•„์›ƒ, ์ค‘์ฒฉ ๋ผ์šฐํŒ…, ๋กœ๋”ฉ ์ƒํƒœ, ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๋“ฑ์„ ์ง€์›ํ•˜๋Š” React Server Components๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ์ƒˆ๋กœ์šด App Router๋ฅผ ๋„์ž….

๐Ÿ“— Tree ๊ตฌ์กฐ & URL Path

Subtree: ๋ฃจํŠธ(์ฒซ ๋ฒˆ์งธ)์—์„œ ์‹œ์ž‘ํ•˜์—ฌ ์žŽ(๋งˆ์ง€๋ง‰)์—์„œ ๋๋‚˜๋Š” ํŠธ๋ฆฌ์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค.
Root: ๋ฃจํŠธ ๋ ˆ์ด์•„์›ƒ๊ณผ ๊ฐ™์€ ํŠธ๋ฆฌ ๋˜๋Š” ํ•˜์œ„ ํŠธ๋ฆฌ์˜ ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ์ž…๋‹ˆ๋‹ค.
Leaf: URL ๊ฒฝ๋กœ์˜ ๋งˆ์ง€๋ง‰ ์„ธ๊ทธ๋จผํŠธ์™€ ๊ฐ™์ด ์ž์‹์ด ์—†๋Š” ํ•˜์œ„ ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ์ž…๋‹ˆ๋‹ค.

URL Segment : ์Šฌ๋ž˜์‹œ๋กœ ๊ตฌ๋ถ„๋œ URL ๊ฒฝ๋กœ์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค.
URL Path : ๋„๋ฉ”์ธ ๋’ค์— ์˜ค๋Š” URL์˜ ์ผ๋ถ€(์„ธ๊ทธ๋จผํŠธ๋กœ ๊ตฌ์„ฑ)

  • ํŒŒ์ผ ์‹œ์Šคํ…œ ๊ธฐ๋ฐ˜์˜ ๋ผ์šฐํŒ…
  • / ๋กœ ๊ตฌ๋ถ„๋œ ๊ฒฝ๋กœ์˜ ์ด๋ฆ„์€ Segment๋ผ ํ•˜๋ฉฐ ํด๋” ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • App directory ๋‚ด ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทœ์น™์— ๋งž๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋ฉด ํด๋” ์ด๋ฆ„์„ ๋”ฐ๋ฅด๋Š” URL Path๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“— ํŒŒ์ผ ๊ทœ์น™

โœ… Layout
-๋ฃจํŠธ ๋ ˆ์ด์•„์›ƒ์—๋งŒ ๋ฐ ํƒœ๊ทธ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์—ฌ๋Ÿฌ ๊ฒฝ๋กœ ๊ฐ„ ๊ณต์œ ๋˜๋Š” UI
  • ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ๋Œ€ํ™”ํ˜•์„ ์œ ์ง€ํ•˜๋ฉฐ ๋‹ค์‹œ ๋ Œ๋”๋ง๋˜์ง€ ์•Š๋Š”๋‹ค.
  • ๋ ˆ์ด์•„์›ƒ์€ ์ค‘์ฒฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ๋‚ด๋ถ€ ๊ฒฝ๋กœ page, ํ•˜์œ„ ํด๋” - ์„ธ๊ทธ๋จผํŠธ๋ฅผ ๋ž˜ํ•‘.
  • ์ƒ์œ„ ๋ ˆ์ด์•„์›ƒ๊ณผ ํ•ด๋‹น ํ•˜์œ„ ๋ ˆ์ด์•„์›ƒ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
    โœ… page
  • ํŽ˜์ด์ง€๋Š” ๊ฒฝ๋กœ์— ๊ณ ์œ ํ•œ UI.
  • ํŒŒ์ผ์—์„œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋‚ด๋ณด๋‚ด๋Š” ํŽ˜์ด์ง€๋ฅผ ์ •์˜
  • indexํŒŒ์ผ๊ณผ ๋™์ผ.

๐Ÿ“— ๊ณ„์ธต๊ตฌ์กฐ

๐Ÿ“ ์ค‘์ฒฉ ๊ฒฝ๋กœ์—์„œ๋Š” dashboard ์„ธ๊ทธ๋จผํŠธ์˜ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ƒ์œ„ ์„ธ๊ทธ๋จผํŠธ ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด์— ์ค‘์ฒฉ

  • URL Path : /dashboard/settings

โœ… EX)

dashboard ํด๋”(directory) ๋‚ด layout.tsx ์ƒ์„ฑํ•˜์˜€๊ณ 
settings ํด๋” ๋‚ด layout.tsx์™€ page.tsx๋ฅผ ์ƒ์„ฑ.

// dashboard layout
export default function DashboardLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <div>
      1. Dashboard Layout
      <hr />
      {children}
    </div>
  );
}

// setting layout
export default function SettingLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <div>
      2. Settings Layout
      <hr />
      {children}
    </div>
  );
}

// setting page
export default function Setting(){
  return (
    <div>
      3. Settings Page
    </div>
  )
}

โœ… /dashboard/settings

โœ”๏ธ ์œ„์™€ ๊ฐ™์ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ… /dashboard

โœ”๏ธ dashboard ํด๋” ๋‚ด UI๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” page ํŒŒ์ผ์ด ์—†๊ธฐ์— 404 ์—๋Ÿฌ๊ฐ€ ๋‚˜์˜ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
โœ”๏ธ ์—๋Ÿฌ ํ™”๋ฉด์„ error.js๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โœ”๏ธ ๊ฒฝ๋กœ๋กœ ์ง€์ •์„ ํ•˜๊ธฐ ์œ„ํ•ด์„  page ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
โœ”๏ธ .js, .jsx, tsx ํ™•์žฅ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“— ๋™์  ๋ผ์šฐํŒ…, Dynamic Routes

๐Ÿ“ ๋™์  ๋ฐ์ดํ„ฐ์— ๋”ฐ๋ผ ๊ฒฝ๋กœ๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋Š” ๊ฒฝ์šฐ

  • ๋ชฉ๋ก, ์—ฌ๋Ÿฌ ์ƒํ’ˆ์˜ ์ƒ์„ธ ํŽ˜์ด์ง€ ๋“ฑ UI๋Š” ๊ฐ™๊ณ  ๋‚ด์šฉ๋งŒ ๋‹ค๋ฅผ ๊ฒฝ์šฐ
    page๋ฅผ ๋‹ค ๋งŒ๋“œ๋Š” ์ž‘์—…์€ ๋ถˆํ•„์š”ํ•˜๊ธฐ์— ์‚ฌ์šฉ.
  • [ํด๋”์ด๋ฆ„] ๐Ÿ‘ˆ ๋Œ€๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์  ์„ธ๊ทธ๋จผํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

โœ… EX)

โœ… ์ •์ƒ์ ์œผ๋กœ [id]/page.tsx๊ฐ€ ๋ณด์—ฌ์ง€๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • props๋ฅผ ํ†ตํ•ด params / searchParams ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • params id ๊ฐ’์„ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

http://localhost:3000/dashboard/settings/5?velog=NEXTJS

// ๐Ÿ‘‰ dashboard/settings/[id]/page.tsx
export default function SettingId(props) {
 console.log(props)
  return (
    <div>
      Page
    </div>
  )
}

โ€ป console.log ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ํ„ฐ๋ฏธ๋„์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ

โœ… 'use client' : ํด๋ผ์ด์–ธํŠธ์ผ ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ € ์ฝ˜์†”์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ.

export default function SettingId({
  params
} : {
  params : { id : string},
}) {
  return (
    <div>
      {params.id} Page
    </div>
  )
}

โœ… params id ๊ฐ’ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

โœ… [ํด๋”์ด๋ฆ„] ๋ณ€๊ฒฝํ•ด์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

๐Ÿ“— Route Groups

๐Ÿ“ Route Group์€ URL ๊ฒฝ๋กœ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š๋Š”๋‹ค.

  • Route Group์€ ํด๋” ์ด๋ฆ„์„ ๊ด„ํ˜ธ๋กœ ๋ฌถ์–ด ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ธฐ์ค€์œผ๋กœ ๊ฒฝ๋กœ๋ฅผ ๊ทธ๋ฃนํ•˜์—ฌ ๊ตฌ์„ฑํ•˜๊ธฐ ํŽธํ•ฉ๋‹ˆ๋‹ค.
  • ํŠน์ • ์„ธ๊ทธ๋จผํŠธ๋ฅผ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ์„ ํƒ
  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฃจํŠธ('/') ๋ ˆ์ด์•„์›ƒ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ

โœ… /account -> ๋ฃจํŠธ layout.js์™€ (shop) layout.js ํฌํ•จ account page
โœ… checkout -> ๋ฃจํŠธ layout.js๋งŒ ํฌํ•จํ•œ page

๐Ÿ“Œ Component

๐Ÿ“– ์ปดํฌ๋„ŒํŠธ(component)

  • ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปค์Šคํ…€ ์—˜๋ฆฌ๋จผํŠธ๋‚˜ UI ์ฝ”๋“œ ์กฐ๊ฐ์„ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌ์„ฑ๋œ ๋…๋ฆฝ๋œ ๋ชจ๋“ˆ์„ ์กฐํ•ฉํ•˜์—ฌ ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“– Next.js Component

โœ… Next.js์—์„œ๋Š” ์„œ๋ฒ„์—์„œ server component, client component ๋ชจ๋“  ํŽ˜์ด์ง€ per-render ๋œ๋‹ค.
: ์ดˆ๊ธฐ ํ™”๋ฉด์— ๋นˆ ๊ฐ’์ด ์•„๋‹Œ ๋งŒ๋“ค์–ด์ง„ ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“— RSC, RCC

๐Ÿ“Next.js์—์„œ๋Š” React 18 ์ถœ์‹œ ํ›„ ๋„์ž…๋œ ๊ธฐ์ˆ  RSC(React Server Component) / RCC(React Client Component) ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

โœ… ๊ณต์‹๋ฌธ์„œ RSC์™€ RCC์˜ ์—ญํ• ์ด ๊ตฌ๋ถ„๋˜์–ด ์žˆ๊ธฐ์— ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“– Server component

๐Ÿ“ App directory ๋‚ด๋ถ€์— ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ์‹œ ๊ธฐ๋ณธ์œผ๋กœ ์„œ๋ฒ„์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋˜๋ฉฐ, ๋ณ„๋„ ์ง€์ •์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. (๊ธฐ๋ณธ ํŒŒ์ผ server component)

  • javascript ๋ฒˆ๋“ค ํฌ๊ธฐ ๊ฐ์†Œ ๋กœ๋”ฉ ์†๋„์— ์žฅ์ 
  • React hook & Event Listener ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • hook, event listener ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด client component ์ƒ์„ฑ ํ›„ prop ํ˜•ํƒœ๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ํŒจํ„ด์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • async ํ•จ์ˆ˜๋กœ ์„ ์–ธํ•˜๊ณ  ๋‚ด๋ถ€์—์„œ await ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ด๋ฅผ ๋ Œ๋”๋ง ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ํŒจ์นญ, ๋ณด์•ˆ, ์บ์‹ฑ, SEO ์ตœ์ ํ™” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
export default function ServerComponent() {
  return (
    <div>
      <p>Server Component</p>
    </div>
  );
}

โœ… Server Component

๐Ÿ“– client compoent

๐Ÿ“ ์„œ๋ฒ„์—์„œ ๊ธฐ๋ณธ html ๋ Œ๋”๋ง ํ›„ Hydrate ๊ณผ์ •์„ ๊ฑฐ์ณ React hook, Event Listener๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋งŒ๋“ค์–ด์ง„๋‹ค.

  • ์ตœ์ƒ๋‹จ์— 'use client' ์ž‘์„ฑํ•˜๋ฉฐ ์ค‘๊ฐ„์— 'use client' ์ž‘์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • use client๋Š” client์—์„œ๋งŒ render ํ•œ๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ์•„๋‹Œ ์„œ๋ฒ„์—์„œ ๊ธฐ๋ณธ ๋ Œ๋”๋ง ํ›„ client์—์„œ๋„ render ์ด๋ฃจ์–ด์ง„๋‹ค.
  • client component๋Š” ์ƒํƒœ ๋ฐ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž์—๊ฒŒ ์ฆ‰๊ฐ์ ์ธ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณต ๋ฐ UI ์—…๋ฐ์ดํŠธ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒํƒœ, ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋“ฑ ์‚ฌ์šฉ์ด ํŽธํ•˜๊ธฐ์— ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ client component๋กœ ๋งŒ๋“ค ์ˆ˜๋Š” ์žˆ์ง€๋งŒ javascript ๋‹ค์šด ํ›„ hydration ๊ณผ์ •์ด ์ด๋ฃจ์–ด์ง€๋ฉด์„œ ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋Š๋ ค์ง„๋‹ค.
  • client component๋Š” ์ตœ๋Œ€ํ•œ ์•„๋ž˜์ชฝ(๋ง๋‹จ)์œผ๋กœ ์ด๋™์‹œํ‚ค๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  • client component ๋‚ด server component๋ฅผ import๊ฐ€ ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ์ƒํ™ฉ์—์„œ๋Š” children๊ณผ ๊ฐ™์ด props๋กœ ์ „๋‹ฌํ•ด์„œ ์‚ฌ์šฉ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
'use client' // ๐Ÿ‘ˆ client component
 
import { useState } from 'react'
 
export default function Counter() {
  const [state, setState] = useState(0) // React hook 
 
  return (
    <div>
      <p>{state}</p>
      <button onClick={() => setState(state + 1)}>
        Click Event Listener
      </button>
    </div>
  )
}

โœ… 'use client' Client Component ๋งŒ๋“ค๊ธฐ


// Client Component 
'use client'

export default function ClientComponent({
  children, // Server component ์ž์‹ ์š”์†Œ๋กœ ์ „๋‹ฌ.
} : {
  children: React.ReactNode
}) {
  return (
    <div>
      <p>Client Component</p>
      <button onClick={()=>console.log("Client component")}>๋ฒ„ํŠผ</button>
      <p>๐Ÿ‘‡ Server Component</p>
      {children} 
    </div>
  );
}

// Parent Component
// ๐Ÿ‘‡ Client Component children์œผ๋กœ ์ „๋‹ฌ
...
<ClientComponent>
  <ServerComponent />
</ClientComponent>
...

โœ… Client Component์—์„œ Server Component props๋กœ ์‚ฌ์šฉ.

๐Ÿ”—
Nextjs org
RSC,RCC ์ฐธ๊ณ 

profile
๊ณต๋ถ€&๊ธฐ๋ก
post-custom-banner

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