๐Ÿš€ Next.js 3์žฅ: App Router์˜ 3๋Œ€ ๋ Œ๋”๋ง ์ „๋žต (SSR, SSG, ISR)

๐Ÿ“‹ ๊ฐœ์š”

SSR, SSG, ISR ์„ธ ๊ฐ€์ง€ ๋ Œ๋”๋ง ์ „๋žต์˜ ์ฐจ์ด์™€ App Router์—์„œ ๊ฐ๊ฐ์„ ์–ธ์ œ ์จ์•ผ ํ•˜๋Š”์ง€ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ


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

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

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„
๋ Œ๋”๋ง ์‹œ์  ๋‘ ๊ฐ€์ง€ โ†’ ์ •์  ๋ Œ๋”๋ง(SSG) โ†’ ๋™์  ๋ Œ๋”๋ง(SSR) โ†’ ์ ์ง„์  ์žฌ์ƒ์„ฑ(ISR) โ†’ ๋นŒ๋“œ ๊ฒฐ๊ณผ ๊ฟ€ํŒ(์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ์˜ˆ์ œ)

๐ŸŽฏ ์ด ๋ฌธ์„œ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • ๊ฐ ํ™”๋ฉด ์„ฑ๊ฒฉ๊ณผ ์„œ๋น„์Šค ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถฐ ์ตœ์ ์˜ ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋ฐฉ์‹์„ ์Šค์Šค๋กœ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋นŒ๋“œ ๋กœ๊ทธ๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ๊ฐ€ ์˜๋„์น˜ ์•Š๊ฒŒ ์„œ๋ฒ„ ์ž์›์„ ๊ณ ๊ฐˆ์‹œํ‚ค๊ณ  ์žˆ์ง€ ์•Š์€์ง€ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

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

  • ์˜์ฒ (์ƒˆ๋กœ ์˜จ ์ฃผ๋‹ˆ์–ด): "์–ด? ๋ถ„๋ช…ํžˆ ๋กœ์ปฌ์—์„œ๋Š” ์ž˜ ๋๋Š”๋ฐ... ๋ฐฐํฌํ•˜๊ณ  ๋‚˜๋‹ˆ๊นŒ ํšŒ์‚ฌ ์†Œ๊ฐœ ํŽ˜์ด์ง€ ํ•˜๋‚˜ ์—ด ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„๊ฐ€ ๋น„๋ช…์„ ์งˆ๋Ÿฌ์š”! ๐Ÿ˜ญ"
  • ์˜ํ˜ธ(FE ๋ฆฌ๋“œ): "์˜์ฒ  ๋‹˜... ์†Œ๊ฐœ ํŽ˜์ด์ง€ ์ตœ์ƒ๋‹จ์— cookies() ํ•จ์ˆ˜๋ฅผ ๋ฐ•์•„๋„ฃ์œผ์…จ๋”๊ตฐ์š”. ๊ทธ ํ•œ ์ค„ ๋•Œ๋ฌธ์— ์ •์ ์œผ๋กœ ๊ตฌ์›Œ์ ธ์•ผ ํ•  ํŽ˜์ด์ง€๊ฐ€ ์‹ค์‹œ๊ฐ„ ํ–„๋ฒ„๊ฑฐ๊ฐ€ ๋œ ๊ฑฐ์˜ˆ์š”!"

๐Ÿค” ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€

์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋“œ๋””์–ด ์œ ์ž…์ž๊ฐ€ ๋ชฐ๋ฆฌ๊ธฐ ์‹œ์ž‘ํ–ˆ์–ด.

์˜์š• ๋„˜์น˜๋Š” ์˜์ฒ (์ƒˆ๋กœ ์˜จ ์ฃผ๋‹ˆ์–ด) ๋‹˜์€ ๋ฌด์ฒ™ ๊ธฐ๋ปค์ง€๋งŒ, ๊ธฐ์จ๋„ ์ž ์‹œ. ์Šคํ„ฐ๋”” ๋งค์นญ ์•ฑ์˜ "์†Œ๊ฐœ ํŽ˜์ด์ง€(/about)" ํ•˜๋‚˜ ๋ณด๋ ค๊ณ  ๋“ค์–ด์˜จ ์œ ์ €๋“ค ๋•Œ๋ฌธ์— DB ์„œ๋ฒ„ CPU๊ฐ€ 100%๋ฅผ ์ฐ์œผ๋ฉฐ ์ „์ฒด ์„œ๋น„์Šค๊ฐ€ ๋งˆ๋น„๋˜์–ด ๋ฒ„๋ ธ์–ด.

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

๋ฒ”์ธ์€ ์ด๋ฒˆ์—๋„ ์˜์ฒ  ๋‹˜. ๊ทธ๋Š” ์ฟ ํ‚ค ๊ธฐ๋ฐ˜ ๋‹ค๊ตญ์–ด ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ต์‹œ๊ณ  ์ตœ์ƒ์œ„ ์˜์—ญ์— cookies() ํ•จ์ˆ˜๋ฅผ ํ•œ ์ค„ ๋ฐ•์•„๋ฒ„๋ ธ๊ณ , ์ด๋กœ ์ธํ•ด Next.js๊ฐ€ ๋ฏธ๋ฆฌ ์•„์ฃผ ๋ง›์žˆ๊ฒŒ ๊ตฌ์›Œ๋‘์—ˆ๋˜(Static) ํŽ˜์ด์ง€๋“ค์„ ๋ชจ์กฐ๋ฆฌ ๋Ÿฐํƒ€์ž„ ์ฆ‰์„ ๋ Œ๋”๋ง(Dynamic)์œผ๋กœ ๊ฐ•๋“ฑ์‹œ์ผœ๋ฒ„๋ฆฐ ๊ฑฐ์•ผ. ๋ Œ๋”๋ง ์ „๋žต์„ ์ œ๋Œ€๋กœ ๋ชจ๋ฅด๋ฉด ์ด๋Ÿฐ '์„œ๋ฒ„ ํญํƒ„'์„ ๋งŒ๋“ค๊ฒŒ ๋ผ.


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

๐Ÿง’ 5์‚ด์—๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค๋ฉด? (์˜์ˆ˜๋„ค ๊ตญ๋ฐฅ์ง‘)

๋ Œ๋”๋ง ์ „๋žต์€ ์Œ์‹์„ ๋งŒ๋“ค์–ด๋‘๋Š” ํƒ€์ด๋ฐ ์˜ ์ฐจ์ด์•ผ.

  1. Static Rendering (SSG): ์ƒˆ๋ฒฝ ์žฅ์‚ฌ ์ „(๋นŒ๋“œ ํƒ€์ž„)์— ๋Œ€ํ˜• ๊ฐ€๋งˆ์†ฅ์— ๊ตญ๋ฐฅ์„ ์‹น ๋‹ค ๋“์—ฌ๋‘๋Š” ๊ฑฐ์•ผ. ์†๋‹˜์ด ์˜ค๋ฉด 1์ดˆ ๋งŒ์— ํˆญ ๋˜์ ธ์ค˜. ์ œ์ผ ๋น ๋ฅด๊ณ  ์•Œ๋ฐ”์ƒ(์„œ๋ฒ„)๋„ ์•ˆ ํž˜๋“ค์–ด. (ํšŒ์‚ฌ ์†Œ๊ฐœ, ๋ธ”๋กœ๊ทธ)
  2. Dynamic Rendering (SSR): ์ด๊ฑด ์ฆ‰์„์—์„œ ๋ณถ๋Š” ์ œ์œก๋ณถ์Œ ์ด์•ผ. ์†๋‹˜์ด ์ฃผ๋ฌธ(์ ‘์†)ํ•  ๋•Œ๋งˆ๋‹ค ์•Œ๋ฐ”์ƒ์ด ๋ถˆ ์ผœ๊ณ  ๊ณ ๊ธฐ๋ฅผ ์ƒˆ๋กœ ๋ณถ์•„. ์„œ๋ฒ„๊ฐ€ ๊ณ ์ƒํ•˜์ง€๋งŒ, "์ „ ๋น„๊ณ„ ๋นผ์ฃผ์„ธ์š”(๊ฐœ์ธํ™” ์ฟ ํ‚ค)" ๊ฐ™์€ ์š”๊ตฌ๋ฅผ 100% ๋งž์ถฐ ์ค„ ์ˆ˜ ์žˆ์–ด. (๋งˆ์ดํŽ˜์ด์ง€, ์žฅ๋ฐ”๊ตฌ๋‹ˆ)
  3. ISR (Incremental Static Regeneration): "์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ์ƒˆ๋กœ ๋ฌด์ณ ๋‚˜์˜ค๋Š” ๊ฒ‰์ ˆ์ด" ๊ฐ™์€ ๊ฑฐ์•ผ. ๋ฏธ๋ฆฌ ๋ฌด์ณ๋‘์ง€๋งŒ, 10๋ถ„๋งˆ๋‹ค ์ฃผ๋ฐฉ์—์„œ ์ƒˆ ๊ฑธ๋กœ ๋ฌด์ณ์„œ ์ฑ„์›Œ ๋„ฃ์–ด. ์‹ ์„ ํ•จ๊ณผ ์†๋„๋ฅผ ๋‹ค ์žก๋Š” ๋ฐฉ๋ฒ•์ด์ง€.

๐Ÿ›‘ ๋ Œ๋”๋ง ์‹œ์ ์˜ ๋น„๋ฐ€: Build-time vs Run-time ๐ŸŸข

๐ŸŽฏ ์ด ์„น์…˜ ์ดํ›„์— ๋‹น์‹ ์€:

  • ๋นŒ๋“œ ํƒ€์ž„๊ณผ ๋Ÿฐํƒ€์ž„์˜ ๊ธฐ์ˆ ์  ์ฐจ์ด๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์™œ ๋นŒ๋“œ ํƒ€์ž„ ์ตœ์ ํ™”๊ฐ€ ์„œ๋ฒ„ ๋น„์šฉ ์ ˆ๊ฐ์˜ ํ•ต์‹ฌ์ธ์ง€ ์ดํ•ดํ•œ๋‹ค.

๊ฐ€์žฅ ํ•ต์‹ฌ์ด ๋˜๋Š” ๊ธฐ์ค€์€ ๊ฒฐ๊ตญ "HTML์„ ๋„๋Œ€์ฒด ์–ธ์ œ ๋งŒ๋“œ๋А๋ƒ?" ์•ผ.

  1. Build Time (๋นŒ๋“œ ํƒ€์ž„): ๊ฐœ๋ฐœ์ž๊ฐ€ ์„œ๋ฒ„์— ์ฝ”๋“œ ๋ฐฐํฌํ•˜๋ ค๊ณ  npm run build ๋ฅผ ์ณค์„ ๋•Œ.(์‚ฌ์šฉ์ž 0๋ช…)
  2. Run Time (๋Ÿฐํƒ€์ž„): ๋นŒ๋“œ ๋๋‚ด๊ณ  ์šด์˜ ์ค‘์ผ ๋•Œ, ์‚ฌ์šฉ์ž๊ฐ€ ์šฐ๋ฆฌ ์•ฑ ๋„๋ฉ”์ธ ์น˜๊ณ  ์ ‘์†ํ•œ ๋ฐ”๋กœ ๊ทธ ์ˆœ๊ฐ„.

๐Ÿงฉ 1. Static Rendering (๊ณผ๊ฑฐ์˜ SSG) ๐ŸŸข

๐ŸŽฏ ์ด ์„น์…˜ ์ดํ›„์— ๋‹น์‹ ์€:

  • Static Rendering์ด ๊ธฐ๋ณธ๊ฐ’(Default)์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ์›๋ฆฌ๋ฅผ ์•ˆ๋‹ค.
  • ์–ด๋–ค ์ฝ”๋“œ๊ฐ€ Static ์ตœ์ ํ™”๋ฅผ ๊นจ๋œจ๋ฆฌ๋Š”์ง€ ์ธ์ง€ํ•œ๋‹ค.

๐Ÿ“– ์šฉ์–ด: SSG(Static Site Generation) โ€” ์•ฑ์„ ๋ฐฐํฌ ์ „(๋นŒ๋“œ ํƒ€์ž„)์— ๋ฏธ๋ฆฌ HTML์„ ์‹น ๋‹ค ์ƒ์„ฑํ•ด๋‘๋Š” ๋ฐฉ์‹.

์ด๊ฒŒ ๋ญ”๊ฐ€? & ์™œ ํ•„์š”ํ•œ๊ฐ€?

์•„๋ฌด๋Ÿฐ ํŠน์ด ์„ค์ • ์—†์ด ์ง  ์ˆœ์ˆ˜ Server Component๋Š” Next.js๊ฐ€ ์ž๋™์œผ๋กœ Static Rendering์œผ๋กœ ๊ฐ„์ฃผํ•ด.
์˜์ฒ  ๋‹˜์ด ์งœ๋˜ /about ํŽ˜์ด์ง€์ฒ˜๋Ÿผ ์ •์ ์ธ ๋ฌธ์„œ๋“ค์„ ํ•œ ๋ฒˆ๋งŒ ๊ตฌ์›Œ์„œ ์ „ ์„ธ๊ณ„ CDN ์— ๋ณต์‚ฌํ•ด๋‘๋ฉด, ์•„๋ฌด๋ฆฌ 10๋งŒ ๋ช…์ด ๋ชฐ๋ ค๋„ ์„œ๋ฒ„ ๋ถ€ํ•˜๊ฐ€ 0(Zero) ์ด๋ž€ ๋œป์ด์ง€.

โŒ ์ˆœ์ง„ํ•œ ์ฝ”๋“œ (Naive Approach)
ํŽ˜์ด์ง€๋ฅผ CSR(React) ๋กœ ๋งŒ๋“ค์–ด ๊ตณ์ด ํด๋ผ์ด์–ธํŠธ์˜ ํ†ต์‹  ๋Šฅ๋ ฅ์„ ๋‚ญ๋น„ํ•˜๊ฒŒ ํ•จ.

โœ… ์šฐ์•„ํ•œ ์ฝ”๋“œ (Pro Approach) - ์™„๋ฒฝํ•œ Static ์ตœ์ ํ™”

// app/about/page.tsx
// ๐Ÿฆ ์˜ํ˜ธ: "์•„๋ฌด๋Ÿฐ ๋™์  ํ•จ์ˆ˜๊ฐ€ ์—†์œผ๋‹ˆ, ์ด ํŽ˜์ด์ง€๋Š” ๋นŒ๋“œ ๋•Œ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ๊ตฌ์›Œ์ง‘๋‹ˆ๋‹ค."
 
export default function AboutPage() {
  return (
    <main>
      <h1>๋Œ€ํ•œ๋ฏผ๊ตญ No.1 ์Šคํ„ฐ๋”” ๋งค์นญ, ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ</h1>
    </main>
  )
}

๐Ÿงฉ 2. Dynamic Rendering (๊ณผ๊ฑฐ์˜ SSR) ๐ŸŸข

๐ŸŽฏ ์ด ์„น์…˜ ์ดํ›„์— ๋‹น์‹ ์€:

  • ์–ด๋–ค ํ•จ์ˆ˜๊ฐ€ ํŽ˜์ด์ง€๋ฅผ SSR๋กœ '๊ฐ•์ œ ๊ฐ•๋“ฑ'์‹œํ‚ค๋Š”์ง€ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ธฐ์–ตํ•œ๋‹ค.
  • Dynamic ๋ Œ๋”๋ง์ด ํ•„์š”ํ•œ ํ•„์—ฐ์ ์ธ ์ƒํ™ฉ์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“– ์šฉ์–ด: SSR(Server-Side Rendering) โ€” ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘์†ํ•˜๋Š” ๊ทธ ๋Ÿฐํƒ€์ž„ ์‹œ์  ์—, ๊ทธ ์‚ฌ๋žŒ๋งŒ์„ ์œ„ํ•œ ์ตœ์‹  ๋ฐ์ดํ„ฐ์™€ ํ—ค๋”๋กœ HTML์„ ๋ผˆ๋ถ€ํ„ฐ ๊ตฌ์›Œ์ฃผ๋Š” ๋ฐฉ์‹.

์–ธ์ œ ๊ฐ•์ œ ์ „ํ™˜๋˜๋Š”๊ฐ€?

๋‚ด ํŽ˜์ด์ง€๊ฐ€ Static์—์„œ ๋น„์‹ผ Dynamic SSR๋กœ ๊ฐ•๋“ฑ๋˜๋Š” ์กฐ๊ฑด์€ ๋ช…ํ™•ํ•ด. "Next.js๊ฐ€ ๋ฏธ๋ฆฌ ์•Œ ์ˆ˜ ์—†๋Š” ์‹ค์‹œ๊ฐ„ ์œ ์ € ์ •๋ณด"๋ฅผ ๊ฑด๋“œ๋ฆฌ๋Š” ์ˆœ๊ฐ„!

  • cookies() ์ฝ๊ธฐ
  • headers() (์œ ์ €์˜ Agent ๋“ฑ) ์ฝ๊ธฐ
  • searchParams๋ฅผ ํŽ˜์ด์ง€ ํ”„๋กญ์Šค๋กœ ๋ฐ›์•„ ๋ Œ๋”๋ง์— ์“ธ ๋•Œ
// app/dashboard/page.tsx
import { cookies } from 'next/headers'
 
export default async function DashboardPage() {
  // ๐Ÿฃ ์˜์ฒ : "์•„ํ•ญ, ์ฟ ํ‚ค๋ฅผ ์ฝ๋Š” ์ด ๋ผ์ธ์ด ์ถ”๊ฐ€๋˜๋Š” ์ˆœ๊ฐ„, 
  // ๋นŒ๋“œ ํƒ€์ž„์—๋Š” ์ด๊ฒŒ ๋ˆ„๊ตฌ ์ฟ ํ‚ค์ธ์ง€ ์•Œ ์ˆ˜๊ฐ€ ์—†์œผ๋‹ˆ ๋Ÿฐํƒ€์ž„ SSR ๋ Œ๋”๋ง์ด ๊ฐ•์ œ๋˜๋Š”๊ตฌ๋‚˜!"
  const cookieStore = cookies() 
  const userToken = cookieStore.get('auth_token')
 
  return (
    <main>
      <h1>๋‚ด ์Šคํ„ฐ๋”” ํ˜„ํ™ฉ</h1>
    </main>
  )
}

๐Ÿงฉ 3. ISR: ๋ฐ˜์ž๋™ ๋ Œ๋”๋ง์˜ ๋งˆ๋ฒ• ๐ŸŸก

๐ŸŽฏ ์ด ์„น์…˜ ์ดํ›„์— ๋‹น์‹ ์€:

  • revalidate ์˜ต์…˜์„ ํ†ตํ•ด ์ •์  ํŽ˜์ด์ง€๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Stale-While-Revalidate ์ „๋žต์˜ ์žฅ๋‹จ์ ์„ ์ดํ•ดํ•œ๋‹ค.

์˜์ˆ™(๋””์ž์ด๋„ˆ) ๋‹˜์ด ์š”๊ตฌํ–ˆ์–ด. "์˜ํ˜ธ ๋‹˜, ๋ฉ”์ธ ํ™”๋ฉด์˜ '์‹ค์‹œ๊ฐ„ ๊ธ‰์ƒ์Šน ์ธ๊ธฐ ์Šคํ„ฐ๋””' ๋ชฉ๋ก์€ ํ•œ 10๋ถ„์— ํ•œ ๋ฒˆ ์ •๋„๋งŒ ๊ฐฑ์‹ ๋ผ๋„ ์ถฉ๋ถ„ํ•  ๊ฑฐ ๊ฐ™์•„์š”. ์ ‘์†์ž ํญ์ฃผํ•  ๋•Œ ๋กœ๋”ฉ ๊ฑธ๋ฆฌ๋Š” ๊ฑด ์ ˆ๋Œ€ ์‹ซ๊ณ ์š”!"

์˜ํ˜ธ(FE ๋ฆฌ๋“œ) ๋‹˜์€ ์”ฉ ์›ƒ์œผ๋ฉฐ ๋Œ€๋‹ตํ–ˆ์–ด. "ISR๋กœ ์บ์‹œ๋ฅผ ์น˜๋ฉด ์™„๋ฒฝํ•˜์ฃ !"

ISR ๋™์ž‘ ์›๋ฆฌ

์ •์  ํŽ˜์ด์ง€์˜ ๊นกํŒจ ๊ฐ™์€ ์†๋„๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฃผ๊ธฐ์ ์œผ๋กœ ์บ์‹œ๋ฅผ ๊ฐฑ์‹ ํ•ด.

// app/trending/page.tsx
export default async function TrendingPage() {
  // โœ… next: { revalidate: 600 } -> 10๋ถ„(600์ดˆ)์งœ๋ฆฌ ISR ์ „๋žต ์„ ์–ธ!
  const res = await fetch('https://api.youngsu.com/bestsellers', {
    next: { revalidate: 600 } 
  })
  const trends = await res.json()
  
  // ๐Ÿฆ ์˜ํ˜ธ: "์‚ฌ์šฉ์ž๋Š” 10๋ถ„ ๋™์•ˆ ๊ตฌ์›Œ์ง„ HTML์„ ๊ด‘์†์œผ๋กœ ๋ฐ›๊ณ , 10๋ถ„์ด ์ง€๋‚˜๋ฉด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ƒˆ ๊ตญ๋ฐฅ์ด ๋“์—ฌ์ง‘๋‹ˆ๋‹ค."
  return <ul>{trends.map(t => <li key={t.id}>{t.title}</li>)}</ul>
}

[์‹œ๋‹ˆ์–ด ๊ด€์ ์˜ ISR์˜ ํ•จ์ • ์ฃผ์˜]
ISR์˜ ๋‹จ์ ์€ ์™„๋ฒฝํ•œ ์‹ค์‹œ๊ฐ„์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์—†๊ณ , ๋ˆ„๊ตฐ๊ฐ€ ํฌ์ƒ์–‘ 1๋ช…์ด ์ง€๋‚˜๊ฐ„ ์ดํ›„์—์•ผ ์ƒˆ ์ปจํ…์ธ ๋กœ ๋ฎ์–ด์”Œ์›Œ์ง„๋‹ค๋Š” ๊ฑฐ์•ผ(Stale-While-Revalidate ์•„ํ‚คํ…์ฒ˜ ํ•œ๊ณ„). ์ฆ‰๊ฐ ๋ฌดํšจํ™”๊ฐ€ ํ•„์š”ํ•  ๋• ํ›—๋‚  ๋‹ค๋ฃฐ revalidateTag ๋“ฑ ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•์ด ์š”๊ตฌ๋ผ.


๐Ÿงช ๋”ฐ๋ผํ•ด๋ณด๊ธฐ: ๋‚ด ๋ผ์šฐํŠธ๊ฐ€ Static์ธ์ง€ Dynamic์ธ์ง€ ํ™•์ธํ•˜๊ธฐ

๐ŸŽฏ ์ด ์„น์…˜ ์ดํ›„์— ๋‹น์‹ ์€:

  • npm run build ๊ฒฐ๊ณผ๋ฌผ์„ ๋ณด๊ณ  ๋‚ด ์ฝ”๋“œ์˜ ๋ Œ๋”๋ง ์ „๋žต์„ ํŒ๋…ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ํ˜ธ ๋‹˜์ด ์˜์ฒ  ๋‹˜์—๊ฒŒ ๊ฐ€์žฅ ๋จผ์ € ๊ฐ€๋ฅด์นœ ๊ฒƒ์€ ๋ฐ”๋กœ ๋นŒ๋“œ ๋กœ๊ทธ ์ฝ๋Š” ๋ฒ•์ด์—ˆ์–ด.

npm run build

๋‹ค ๋๋‚˜๋ฉด ๋Œ€์‹œ๋ณด๋“œ์— ์ด๋Ÿฐ ๋ฉ‹์ง„ ๊ฒฐ๊ณผ๊ฐ€ ๋– .

Route (app)                              Size     First Load JS
โ”Œ โ—‹ /                                    142 B    84.1 kB
โ”œ โ—‹ /about                               182 B    84.2 kB
โ”œ ฦ’ /dashboard                           312 B    84.3 kB
โ”” โ— /trending                            240 B    84.2 kB
 
โ—‹  (Static)  automatically rendered as static HTML (uses no initial props)
ฦ’  (Dynamic) server-rendered on demand using Node.js
โ—  (ISR)     incremental static regeneration (uses revalidate in fetch())
๊ธฐํ˜ธ์ „๋žต์„œ๋ฒ„ ๋ถ€ํ•˜ ์ˆ˜์ค€
โ—‹Static์‚ฌ์‹ค์ƒ ๋น„์šฉ ์ œ๋กœ(0).
ฦ’DynamicํŽ‘์…˜(ฦ’) ๋ชจ์–‘. ์š”์ฒญ ์‹œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋ฏ€๋กœ ํŠธ๋ž˜ํ”ฝ ํŠ€๋ฉด ์กฐ์‹ฌํ•ด์•ผ ํ•จ!
โ—ISR์Šค์œ„ํŠธ ์ŠคํŒŸ. ์ •์  ํŒŒ์ผ ๋ฐฐ๋‹ฌ + ๊ฐ„ํ—์  ๊ฐฑ์‹ 

๐ŸŽฏ ๊ฐœ์ธํ™” ํ”ผ๋“œ์™€ SSR ๊ฒฉ๋ฆฌ ์ „๋žต ๐ŸŸก

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

  • ๊ฐœ์ธํ™” ํ”ผ๋“œ๊ฐ€ ์™œ SSR์ด ํ•„์š”ํ•œ์ง€ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Suspense ๊ฒฝ๊ณ„๋กœ SSR ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ๊ฒฉ๋ฆฌํ•˜๊ณ  ๋‚˜๋จธ์ง€ Static์„ ์œ ์ง€ํ•˜๋Š” ํŒจํ„ด์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • useSearchParams ๋ฅผ ์“ธ ๋•Œ ์ „์ฒด ํŽ˜์ด์ง€๊ฐ€ Dynamic์œผ๋กœ ๊ฐ•๋“ฑ๋˜์ง€ ์•Š๋„๋ก ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•ˆ๋‹ค.

๊ฐœ์ธํ™” ํ”ผ๋“œ๋Š” ์™œ SSR์ด์–ด์•ผ ํ• ๊นŒ?

์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ฉ”์ธ ํ”ผ๋“œ ํŽ˜์ด์ง€๋Š” ๋กœ๊ทธ์ธํ•˜๋ฉด "๋‚ด๊ฐ€ ํŒ”๋กœ์šฐํ•˜๋Š” ์Šคํ„ฐ๋”” ๊ทธ๋ฃน" ์˜ ์ตœ์‹  ๊ฒŒ์‹œ๊ธ€๋งŒ ๋ณด์—ฌ์ค˜์•ผ ํ•ด. ์ด ํ”ผ๋“œ๋Š” ์•„๋ž˜ ์ด์œ ๋กœ ๋นŒ๋“œ ํƒ€์ž„์— ๋ฏธ๋ฆฌ ๊ตฌ์›Œ๋‘˜ ์ˆ˜๊ฐ€ ์—†์–ด:

  1. ์‚ฌ์šฉ์ž๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค โ€” ์˜์ฒ  ๋‹˜์˜ ํ”ผ๋“œ๋Š” "ํ”„๋ก ํŠธ์—”๋“œ" ์Šคํ„ฐ๋””๋งŒ ๋ณด์ด๊ณ , ์˜์ˆ™ ๋‹˜์˜ ํ”ผ๋“œ๋Š” "๋””์ž์ธ" ์Šคํ„ฐ๋””๋งŒ ๋ณด์—ฌ. ๋ฏธ๋ฆฌ ๊ตฌ์šธ ์ˆ˜๊ฐ€ ์—†์ง€.
  2. ์ฟ ํ‚ค/์„ธ์…˜์— ์˜์กดํ•œ๋‹ค โ€” ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ์„œ๋ฒ„์—์„œ ์ฟ ํ‚ค๋กœ ํ™•์ธํ•ด์•ผ ํ•ด. cookies() ํ•จ์ˆ˜๋ฅผ ์“ฐ๋Š” ์ˆœ๊ฐ„ Static ๋ถˆ๊ฐ€.
  3. ์‹ค์‹œ๊ฐ„์„ฑ์ด ํ•„์š”ํ•˜๋‹ค โ€” ๋ฐฉ๊ธˆ ์˜ฌ๋ผ์˜จ ๊ฒŒ์‹œ๊ธ€์ด ์žˆ์œผ๋ฉด ๋ฐ”๋กœ ๋ณด์—ฌ์•ผ ํ•ด.

์ด ๊ฒฝ์šฐ ํ”ผ๋“œ ์ปดํฌ๋„ŒํŠธ๋งŒํผ์€ SSR(Dynamic Rendering) ์ด ๋งž์•„. ์ ‘์†ํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„์—์„œ ์ฟ ํ‚ค๋ฅผ ์ฝ๊ณ , ํ•ด๋‹น ์œ ์ €์˜ ๊ตฌ๋… ์Šคํ„ฐ๋”” ๋ชฉ๋ก์„ DB์—์„œ ๊บผ๋‚ด์„œ HTML์„ ์ฆ‰์„์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•˜๊ฑฐ๋“ .

๋ฌธ์ œ: ํ”ผ๋“œ ํ•˜๋‚˜ ๋•Œ๋ฌธ์— ํŽ˜์ด์ง€ ์ „์ฒด๊ฐ€ Dynamic์œผ๋กœ ๊ฐ•๋“ฑ๋œ๋‹ค!

์ด ๊ฐœ์ธํ™” ํ”ผ๋“œ๋ฅผ page.tsx ์ตœ์ƒ๋‹จ์— ๋ฐ”๋กœ ๋„ฃ์œผ๋ฉด ํฐ์ผ ๋‚˜.

// โŒ ์ˆœ์ง„ํ•œ ์ฝ”๋“œ: ๋ฉ”์ธ ํŽ˜์ด์ง€ ์ „์ฒด๊ฐ€ Dynamic์œผ๋กœ ๊ฐ•๋“ฑ๋จ
// app/feed/page.tsx
export default async function FeedPage() {
  const cookieStore = await cookies() // ๐Ÿฃ ์˜์ฒ : "์•„๋ฌด ์ƒ๊ฐ ์—†์ด ์—ฌ๊ธฐ์„œ ์ฟ ํ‚ค๋ฅผ ์ฝ์—ˆ๋”๋‹ˆ..."
  const userId = cookieStore.get('user-id')?.value
  const feed = await db.posts.findMany({ where: { authorFollowedBy: userId } })
 
  return (
    <div>
      <HeroSection />        {/* Static์œผ๋กœ ์ถฉ๋ถ„ํ•œ๋ฐ, ๋ฉ๋‹ฌ์•„ Dynamic์œผ๋กœ ๊ฐ•๋“ฑ๋จ */}
      <TrendingTopics />     {/* ISR์ด๋ฉด ์ถฉ๋ถ„ํ•œ๋ฐ, ์—ญ์‹œ Dynamic์œผ๋กœ ๊ฐ•๋“ฑ๋จ */}
      <PersonalizedFeed feed={feed} />  {/* ์ด๊ฒƒ๋งŒ Dynamic์ด ํ•„์š”ํ•œ๋ฐ */}
    </div>
  )
}

๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด /feed ๊ฐ€ ฦ’ (Dynamic) ์œผ๋กœ ํ‘œ์‹œ๋˜์–ด, 1๋งŒ ๋ช…์ด ๋™์‹œ์— ์ ‘์†ํ•˜๋ฉด 1๋งŒ ๋ฒˆ ์ฆ‰์„ ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•ด. HeroSection ๊ณผ TrendingTopics ๋Š” Static์œผ๋กœ ์ถฉ๋ถ„ํ–ˆ๋Š”๋ฐ ์–ต์šธํ•˜๊ฒŒ ํฌ์ƒ๋œ ๊ฑฐ์•ผ.

ํ•ด๊ฒฐ์ฑ…: Suspense ๊ฒฝ๊ณ„๋กœ SSR ๋ถ€๋ถ„๋งŒ ์ •๋ฐ€ ๊ฒฉ๋ฆฌ

์˜ํ˜ธ ๋‹˜ ์ด ์ œ์‹œํ•œ ์‹ค์ „ ์•„ํ‚คํ…์ฒ˜์•ผ. SSR์ด ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋งŒ ๋น„๋™๊ธฐ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌํ•˜๊ณ , ๋‚˜๋จธ์ง€๋Š” Static์œผ๋กœ ์œ ์ง€ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์•ผ.

// โœ… ์šฐ์•„ํ•œ ์ฝ”๋“œ: SSR ๊ฒฉ๋ฆฌ + Static ๋ณด์กด
// app/feed/page.tsx
import { Suspense } from 'react'
import PersonalizedFeed from '@/components/PersonalizedFeed'
 
// ๐Ÿฆ ์˜ํ˜ธ: "page.tsx ์ž์ฒด๋Š” ์ •์ (Static)์œผ๋กœ ๋‚จ๊ฒจ๋‘๊ณ , ์ฟ ํ‚ค ์‚ฌ์šฉ์ฒ˜๋งŒ ๋„๋ ค๋ƒ…๋‹ˆ๋‹ค."
export default function FeedPage() {
  return (
    <div>
      <HeroSection />
      <TrendingTopics /> 
 
      <Suspense fallback={<FeedSkeleton />}>
        <PersonalizedFeed />  {/* ์ด ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ๋งŒ cookies() ์‚ฌ์šฉ */}
      </Suspense>
    </div>
  )
}
// app/components/PersonalizedFeed.tsx
// ์ด ์ปดํฌ๋„ŒํŠธ๋งŒ SSR (Dynamic)
import { cookies } from 'next/headers'
 
export default async function PersonalizedFeed() {
  const cookieStore = await cookies()  // โ† ์—ฌ๊ธฐ์„œ๋งŒ ์ฟ ํ‚ค ์ ‘๊ทผ
  const userId = cookieStore.get('user-id')?.value
 
  if (!userId) return <LoginPrompt />
 
  const posts = await db.posts.findMany({
    where: { authorFollowedBy: userId },
    orderBy: { createdAt: 'desc' },
    take: 20,
  })
 
  return <ul>{posts.map(p => <PostCard key={p.id} post={p} />)}</ul>
}

๋นŒ๋“œ ๊ฒฐ๊ณผ ๋น„๊ต:

์ˆœ์ง„ํ•œ ์ฝ”๋“œSuspense ๊ฒฉ๋ฆฌ ์ฝ”๋“œ
/feed ์ „์ฒดฦ’ Dynamic (๋งค๋ฒˆ ์„œ๋ฒ„ ์‹คํ–‰)โ—‹ Static + ์ŠคํŠธ๋ฆฌ๋ฐ
HeroSection๋งค๋ฒˆ ์žฌ๋ Œ๋”CDN์—์„œ ์ฆ‰์‹œ ์‘๋‹ต โœ…
PersonalizedFeedDynamicDynamic (ํ•˜์ง€๋งŒ ๋‚˜๋จธ์ง€๋Š” Static ์œ ์ง€) โœ…

useSearchParams ๋„ ๊ฐ™์€ ์›๋ฆฌ๋กœ ๊ฒฉ๋ฆฌํ•ด์•ผ ํ•ด

ํ€ด์ฆˆ 2๋ฒˆ ํ•ด์„ค์—์„œ ๋‚˜์˜จ searchParams ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์•ผ. useSearchParams() ๋ฅผ ์“ฐ๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ page.tsx ์ƒ๋‹จ์— ์žˆ์œผ๋ฉด ์ „์ฒด ํŽ˜์ด์ง€๊ฐ€ Dynamic์œผ๋กœ ๊ฐ•๋“ฑ๋ผ.

// โœ… searchParams ๊ฒฉ๋ฆฌ ํŒจํ„ด
// app/feed/page.tsx โ€” Static ์œ ์ง€
export default function FeedPage() {
  return (
    <div>
      <HeroSection />
      <Suspense fallback={<FilterSkeleton />}>
        <FilteredFeed />  {/* searchParams ์“ฐ๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฒฉ๋ฆฌ */}
      </Suspense>
    </div>
  )
}
// app/components/FilteredFeed.tsx
'use client'
import { useSearchParams } from 'next/navigation'
 
export default function FilteredFeed() {
  const searchParams = useSearchParams()
  const category = searchParams.get('category') // ?category=frontend
  // ...
}

โš ๏ธ ์ฃผ์˜: useSearchParams() ๋ฅผ ์“ฐ๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ Suspense๋กœ ๊ฐ์‹ธ์ง€ ์•Š์œผ๋ฉด Next.js๊ฐ€ ๋นŒ๋“œ ๊ฒฝ๊ณ ๋ฅผ ๋‚ด๋ณด๋‚ด. ๋ฐ˜๋“œ์‹œ <Suspense> ๊ฒฝ๊ณ„ ์•ˆ์— ๋„ฃ์–ด์•ผ ํ•ด.

๐Ÿ’ก ํ•œ ์ค„๋กœ ๊ธฐ์–ตํ•˜๊ธฐ
Dynamic์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ <Suspense> ์•ˆ์˜ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ(์ฟ ํ‚ค ์ ‘๊ทผ)๋‚˜ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ(searchParams)๋กœ ๊ฒฉ๋ฆฌํ•ด. ๋‚˜๋จธ์ง€๋Š” Static์ด ์œ ์ง€๋ผ์„œ CDN์ด ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด์ค„ ๊ฑฐ์•ผ.


๐Ÿ ์ด๋ฒˆ์— ๋ฐฐ์šด ๋‚ด์šฉ ์ด์ •๋ฆฌ

  • SSG (โ—‹): ๋ณ€ํ•˜์ง€ ์•Š๋Š” ํ…์ŠคํŠธ์˜ ํšŒ์‚ฌ ์†Œ๊ฐœ๋‚˜ ์—๋Ÿฌ ํผ. ์ตœ์ƒ์˜ ์†๋„.
  • SSR (ฦ’): ์ฟ ํ‚ค ๋“ฑ ๊ฐœ์ธํ™”๊ฐ€ ๋ฌด์กฐ๊ฑด ํ•„์š”ํ•œ ๋Œ€์‹œ๋ณด๋“œ.
  • ISR (โ—): ์ค€-์‹ค์‹œ๊ฐ„์ด ํ•„์š”ํ•œ ์‡ผํ•‘๋ชฐ ๋ฒ ์ŠคํŠธ์…€๋Ÿฌ, ์ปค๋ฎค๋‹ˆํ‹ฐ ์ธ๊ธฐ๊ธ€.

๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

๋ฐฐ์› ์œผ๋ฉด ํ•œ ๋ฒˆ ๋น„ํ‹€์–ด์„œ ํ™•์ธํ•ด๋ด์•ผ ํ•ด. ์‹œ๋‹ˆ์–ด ๊ด€์ ์œผ๋กœ ํ’€์–ด๋ณด์ž.

Q1. ์˜์ฒ  ๋‹˜์ด ๋งˆ์ดํŽ˜์ด์ง€(SSR ํ•„์ˆ˜)์—์„œ ๋‚ด ๊ฐœ์ธ์ •๋ณด๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์งฐ๋‹ค. ์ด ํŽ˜์ด์ง€ ์ตœ์ƒ๋‹จ ์ปดํฌ๋„ŒํŠธ์ธ app/dashboard/layout.tsx ์— export const dynamic = "force-static" ์„ ๋ถ™์—ฌ์„œ ๊ณ ์˜๋กœ ์–ต์ง€ ์ตœ์ ํ™”๋ฅผ ๊ฐํ–‰ํ•˜๋ ค ์‹œ๋„ํ–ˆ๋‹ค. ์˜์ฒ  ๋‹˜์˜ ์ˆœ์ง„ํ•œ ์ฝ”๋“œ๋Š” ๋นŒ๋“œ ์‹œ์ ์— ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ๋งˆ์ฃผ์น˜๊ฒŒ ๋  ๊ฒƒ์ด๋ฉฐ ๊ทธ ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€?

โœ… ์ •๋‹ต: Dynamic server usage: cookies ์—๋Ÿฌ๋ฅผ ๋ฟœ์œผ๋ฉฐ ๋นŒ๋“œ๋ฅผ ๊ฑฐ๋ถ€ํ•œ๋‹ค.

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

  • ์›๋ฆฌ ์„ค๋ช…: ๊ฐ•์ œ๋กœ force-static(SSG)์„ ์ง€์ •ํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์ž์‹ ์ปดํฌ๋„ŒํŠธ ์–ด๋”˜๊ฐ€์—์„œ cookies() ๋‚˜ headers() ๊ฐ™์€ ๋Ÿฐํƒ€์ž„ ์ œ์•ฝ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด Next.js๋Š” ์ฆ‰์‹œ ์—๋Ÿฌ๋ฅผ ๋ฟœ์œผ๋ฉฐ ๋นŒ๋“œ๋ฅผ ๊ฑฐ๋ถ€ํ•ด.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: ์˜์ฒ  ๋‹˜, "์ฟ ํ‚ค๋Š” ์œ ์ €๊ฐ€ ๋ธŒ๋ผ์šฐ์ €๋กœ ์ ‘์†ํ•ด์•ผ๋งŒ ์ƒ๊ฒจ๋‚˜๋Š” ์ •๋ณด์ธ๋ฐ, ์™œ ๋‚˜ํ•œํ…Œ ์ ‘์†์ž๋„ ์—†๋Š” ๋นŒ๋“œ ํƒ€์ž„์— ๋ฏธ๋ฆฌ ์ •์ ์œผ๋กœ ๊ตฌ์›Œ๋†“์œผ๋ผ๊ณ  ๊ฐ•์š”ํ•˜๋ƒ?" ๋ผ๋ฉฐ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ฐ•๋ ฅํžˆ ํ•ญ์˜ํ•˜๋Š” ๋…ผ๋ฆฌ ๊ตฌ์กฐ์•ผ. SSR ๊ธฐ๋Šฅ๊ณผ Static ๊ฐ•์ œํ™”๋Š” ๋™์‹œ์— ์„ฑ๋ฆฝ๋  ์ˆ˜ ์—†๋Š” ๋ชจ์ˆœ์ด์ง€.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ์ •์ (Static)๊ณผ ๋™์ (Dynamic)์€ ๋ฌผ๊ณผ ๊ธฐ๋ฆ„ ๊ฐ™์€ ๊ฒƒ!

Q2. ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ฉ”์ธ ๋Œ€๋ฌธ(/) ์€ ์™„๋ฒฝํ•œ โ—‹ (Static) ํŒ์ •์„ ๋ฐ›์•˜๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์–ด๋А ๋‚  ์˜์ฒ  ๋‹˜์ด "๋ฉ”์ธ ํŽ˜์ด์ง€ ์ตœ์ƒ๋‹จ์— ์˜ค๋Š˜ ์ ‘์†์ž๋“ค์ด ๊ฒ€์ƒ‰ํ•œ ํŠธ๋ Œ๋“œ ํ‚ค์›Œ๋“œ๋ฅผ ์‹ค์‹œ๊ฐ„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ถ™์—ฌ์„œ ๋…ธ์ถœํ•ฉ์‹œ๋‹ค!" ๋ผ๋ฉฐ ์ปดํฌ๋„ŒํŠธ Props๋กœ searchParams ๋ฅผ ๋‚ด๋ ค๋ฐ›๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋„ฃ์—ˆ๋‹ค. ์ด ์ฝ”๋“œ ํ•œ ์ค„์€ ๋ฉ”์ธ ์„œ๋ฒ„์— ์–ด๋–ค ์น˜๋ช…์ ์ธ ๋ฆฌ์†Œ์Šค ๋ณ€ํ™”๋ฅผ ๋ชฐ๊ณ  ์˜ฌ๊นŒ?

โœ… ์ •๋‹ต: ๋น„์šฉ์ด 0์ด์—ˆ๋˜ ๋ฉ”์ธ ํ™ˆํŽ˜์ด์ง€ ์ „์ฒด๊ฐ€ ๋งค ์ ‘์†๋งˆ๋‹ค ์„œ๋ฒ„ CPU๋ฅผ ์†Œ๋ชจํ•˜๋Š” ฦ’ (Dynamic) ๋ Œ๋”๋ง์œผ๋กœ ๊ฐ•๋“ฑ๋œ๋‹ค.

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

  • ์›๋ฆฌ ์„ค๋ช…: searchParams ๋Š” ๋ธŒ๋ผ์šฐ์ € ์ฃผ์†Œ์ฐฝ ํŒŒ๋ผ๋ฏธํ„ฐ(?query=123)๋ฅผ ์ถ”์ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋Ÿฐํƒ€์ž„์—๋งŒ ์•Œ ์ˆ˜ ์žˆ๋Š” Dynamic ์ •๋ณด์•ผ.
    ๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:
  • ์›๋ฆฌ ์„ค๋ช…: searchParams ๋Š” ๋ธŒ๋ผ์šฐ์ € ์ฃผ์†Œ์ฐฝ ํŒŒ๋ผ๋ฏธํ„ฐ(?query=123)๋ฅผ ์ถ”์ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋Ÿฐํƒ€์ž„์—๋งŒ ์•Œ ์ˆ˜ ์žˆ๋Š” Dynamic ์ •๋ณด์•ผ.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: ์ด๊ฒƒ์„ ๋ถ€๋ชจ ๋ ˆ๋ฒจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ฝ๋Š” ์ˆœ๊ฐ„, ๋น„์šฉ์ด 0(Zero)์ด์—ˆ๋˜ ๊ฑฐ๋Œ€ํ•œ ๋ฉ”์ธ ํ™ˆํŽ˜์ด์ง€ ์ „์ฒด๊ฐ€ ๋งค ์ ‘์†๋งˆ๋‹ค ์„œ๋ฒ„ CPU๋ฅผ ๊นŽ์•„๋จน๋Š” ฦ’ (Dynamic) ๋ Œ๋”๋ง์œผ๋กœ ๋ชฝ๋•… ํฌ์ƒ ๊ฐ•๋“ฑ ์ฒ˜๋ฆฌ๋ผ.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ์˜ํ˜ธ ๋ฆฌ๋“œ ๋‹˜ ์ด๋ผ๋ฉด ์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ Leaf ๋ถ€๋ถ„์œผ๋กœ ๊ฒ€์ƒ‰ ํŒŒ๋ผ๋ฏธํ„ฐ ๋กœ์ง๋งŒ ๊ฒฉ๋ฆฌ์‹œ์ผœ ๋ฉ”์ธ page.tsx ์˜ Static ์†์„ฑ์„ ๋ˆ์งˆ๊ธฐ๊ฒŒ ์ˆ˜ํ˜ธํ–ˆ์„ ๊ฑฐ์•ผ.

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

์˜ค๋Š˜ ๋‹ค์–‘ํ•œ ๋ Œ๋”๋ง ์ „๋žต์„ ๋ฐฐ์šฐ๋ฉด์„œ ์ƒํ™ฉ์— ๋งž๋Š” ๋„๊ตฌ๋ฅผ ๊ณ ๋ฅด๋Š” ๊ฒŒ ์–ผ๋งˆ๋‚˜ ์ค‘์š”ํ•œ์ง€ ๊นจ๋‹ฌ์•˜์–ด! ํŠนํžˆ '๋ฏธ๋ฆฌ ๋“์—ฌ๋†“๋Š” ์œก์ˆ˜(Static)' ์™€ '์ฃผ๋ฌธ ์ฆ‰์‹œ ๋ณถ์•„๋‚ด๋Š” ์š”๋ฆฌ(Dynamic)' ์˜ ๋น„์œ ๋Š” ์˜์›ํžˆ ์žŠ์ง€ ๋ชปํ•  ๊ฒƒ ๊ฐ™์•„.

๐Ÿ’ก ์˜ค๋Š˜์˜ ๊ตํ›ˆ: "์„œ๋ฒ„์˜ ํ‰ํ™”๋ฅผ ์œ„ํ•ด, Dynamic ํ•จ์ˆ˜๋Š” ๊ผญ ํ•„์š”ํ•œ ๊ณณ์—๋งŒ Suspense๋กœ ๊ฒฉ๋ฆฌํ•˜์ž!"

๋‚ด๊ฐ€ ๋ฌด์‹ฌ์ฝ” ์ถ”๊ฐ€ํ•œ cookies() ํ•œ ์ค„์ด ์„œ๋ฒ„ ๋น„์šฉ์„ ํญ์ฆ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒŒ ์ •๋ง ๋ฌด์„ญ๋”๋ผ. ์•ž์œผ๋กœ๋Š” ๋นŒ๋“œ ๋กœ๊ทธ์˜ โ—‹ ์™€ ฦ’ ์•„์ด์ฝ˜์„ ์—ฐ์ธ ์–ผ๊ตด ๋ณด๋“ฏ ๊ผผ๊ผผํžˆ ์ฑ™๊ฒจ๋ด์•ผ๊ฒ ์–ด. ์˜ค๋Š˜์€ ๋จธ๋ฆฌ๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ์ผ๋”๋‹ˆ ๋‹น์ด ๋–จ์–ด์ง€๋„ค. ์ง‘์— ๊ฐ€๋Š” ๊ธธ์— ๋‹ฌ๋‹ฌํ•œ ์ดˆ์ฝ” ์šฐ์œ  ํ•˜๋‚˜ ์‚ฌ์„œ ๋งˆ์…”์•ผ์ง€! ๋น„๋ก ์ง€๊ธˆ์€ ์‹ค์ˆ˜ํˆฌ์„ฑ์ด ์˜์ฒ ์ด์ง€๋งŒ, ๋‚ด์ผ์€ ์˜ค๋Š˜๋ณด๋‹ค ๋” '์ •์ (Static)'์ด๊ณ  ์šฐ์•„ํ•œ ์ฝ”๋“œ๋ฅผ ์งœ๋ณด๊ฒ ์–ด! ๐Ÿฃ


๐Ÿ”— ๋” ์•Œ์•„๋ณด๊ธฐ