๐Ÿง  Next.js ์‹ฌํ™” 1์žฅ: Caching Deep Dive โ€” 4์ค‘ ์บ์‹œ ์•„ํ‚คํ…์ฒ˜ ํŒŒํ—ค์น˜๊ธฐ

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

๐Ÿ“‹ ๊ฐœ์š”

4์ค‘ ์บ์‹œ ์•„ํ‚คํ…์ฒ˜(Request Memoization, Data Cache, Full Route Cache, Router Cache)๋ฅผ ์™„์ „ํžˆ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ


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

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

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

  • ์˜์ฒ (์‹ ์ž…): "์–ด? ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€์—์„œ ๊ณต์ง€์‚ฌํ•ญ ์ œ๋ชฉ์„ '๊ธด๊ธ‰ ํŒจ์น˜ 2.0'์œผ๋กœ ์ˆ˜์ •ํ•˜๊ณ  DB ์ €์žฅ(UPDATE)๊นŒ์ง€ ์„ฑ๊ณตํ–ˆ์–ด์š”. ๊ทธ๋Ÿฐ๋ฐ ๋ฉ”์ธ ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ€์„œ ์ƒˆ๋กœ๊ณ ์นจ(F5)์„ ํ•ด๋„ ์˜ˆ์ „ ์ œ๋ชฉ์ธ '๊ธด๊ธ‰ ํŒจ์น˜ 1.0'๋งŒ ๊ณ„์† ๋– ์š”. ์ œ๊ฐ€ ์บ์‹œ ๊ฐฑ์‹  ๊ฒฝ๋กœ๋ฅผ ๋†“์นœ ๊ฑธ๊นŒ์š”?"
  • ์˜ํ˜ธ(๋ฆฌ๋“œ): "์ข‹์€ ์˜์‹ฌ์ด์—์š”. Next.js๋Š” ๋ฒ„์ „๊ณผ ์„ค์ •์— ๋”ฐ๋ผ Data Cache, Full Route Cache, Router Cache๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ์ˆ˜๋ช…์œผ๋กœ ๋‚จ์Šต๋‹ˆ๋‹ค. ์ €์žฅ ๋กœ์ง์ด ์„ฑ๊ณตํ•ด๋„ ๊ด€๋ จ ์บ์‹œ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฌดํšจํ™”ํ• ์ง€ ์—ฐ๊ฒฐํ•˜์ง€ ์•Š์œผ๋ฉด ํ™”๋ฉด์€ ๋‚ก์€ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”."

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„
Next.js ์บ์‹œ์˜ ์•…๋ช… โ†’ 4๊ฐ€์ง€ ์บ์‹œ ๊ณ„์ธต ์™„๋ฒฝ ๋ถ„ํ•ด โ†’ ๊ฐ ์บ์‹œ์˜ ์ดˆ๊ธฐํ™”(Invalidate) ์›๋ฆฌ

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

  • ๋‚ด ์ฝ”๋“œ๊ฐ€ ์–ด๋А ๊ณ„์ธต์˜ ์บ์‹œ์— ๋ฌถ์—ฌ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐฑ์‹ ํ•˜์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋Š”์ง€, "๋ฒ”์ธ ๋ ˆ์ด์–ด"๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ง€๋ชฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Vercel ๋นŒ๋“œ ์‹œ ํ™”๋ฉด ์˜†์— ๋œจ๋Š” โ—‹ (Static) ๊ณผ ฦ’ (Dynamic) ์˜ ์ง„์งœ ๋‚ด๋ถ€ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.

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

Next.js App Router์˜ ์บ์‹œ๋Š” ๋ฒ„์ „๊ณผ ์„ค์ •์— ๋”ฐ๋ผ ๊ธฐ๋ณธ๊ฐ’์ด ๋‹ฌ๋ผ์กŒ์–ด. Next 13/14์˜ ์ด์ „ ๋ชจ๋ธ์—์„œ๋Š” fetch์™€ ์ •์  ๋ผ์šฐํŠธ๊ฐ€ ์ ๊ทน์ ์œผ๋กœ ์บ์‹œ๋˜์—ˆ๊ณ , Next 15+ ์ดํ›„์—๋Š” ๊ธฐ๋ณธ fetch๊ฐ€ ๋” ๋ณด์ˆ˜์ ์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ cacheComponents: true์™€ 'use cache'์ฒ˜๋Ÿผ ๋ช…์‹œ์ ์ธ ์„ ์–ธ์ด ์ค‘์š”ํ•ด์กŒ์ง€.

๊ทธ๋ž˜๋„ ํ•ต์‹ฌ ์งˆ๋ฌธ์€ ๊ทธ๋Œ€๋กœ์•ผ. "์ด ๊ฒฐ๊ณผ๋ฅผ ์–ธ์ œ๊นŒ์ง€ ์žฌ์‚ฌ์šฉํ•ด๋„ ๋˜๋Š”๊ฐ€?" ์„œ๋ฒ„ ๋ Œ๋”๋ง(SSR) ์œ„์ฃผ์˜ ์›น์€ ๊ตฌ์กฐ์ ์œผ๋กœ ๋น„์‹ธ๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ 1๋งŒ ๋ช… ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„๊ฐ€ 1๋งŒ ๊ฐœ์˜ HTML ๊ณต์žฅ์„ ๋Œ๋ฆฌ๊ณ  DB๋ฅผ ์ฐŒ๋ฅด๋ฉด ๋น„์šฉ๊ณผ ์ง€์—ฐ์ด ์ปค์ง€๊ธฐ ๋•Œ๋ฌธ์ด์•ผ.

ํ•˜์ง€๋งŒ ์ด๊ฑธ ์™„๋ฒฝํ•˜๊ฒŒ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋ฉด, ์˜์ฒ ์ด์ฒ˜๋Ÿผ ํ•˜๋ฃจ ์ข…์ผ DB ๊ฐ’์ด ์—…๋ฐ์ดํŠธ ์•ˆ ๋˜๋Š” ๋Šช์—์„œ ํ—ค๋งค๊ฒŒ ๋ผ.
Next.js๋Š” ๋‹จ์ผ ์บ์‹œ๊ฐ€ ์•„๋‹ˆ๋ผ 4๊ฐœ์˜ ์บ์‹œ ๊ณ„์ธต(Layer)์ด ๋งˆ์น˜ ์–‘ํŒŒ ๊ป์งˆ์ฒ˜๋Ÿผ ์„œ๋กœ๋ฅผ ๋‘˜๋Ÿฌ์‹ธ๊ณ  ์žˆ์–ด. ์ด 4์ค‘ ์‰ด๋“œ์˜ ๋ฉ˜ํƒˆ ๋ชจ๋ธ์„ ๋จธ๋ฆฟ์†์— ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์ด ์‹œ๋‹ˆ์–ด์˜ ๊ฐ€์žฅ ์œ„๋Œ€ํ•œ ์—ฌ์ •์˜ ์‹œ์ž‘์ด์•ผ.


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

๐Ÿง’ 5์‚ด์—๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค๋ฉด? (์˜์ˆ˜๋„ค ํ–„๋ฒ„๊ฑฐ ๊ณต์žฅ์˜ 4์ค‘ ์Šคํ”ผ๋“œ ์‹œ์Šคํ…œ)

์†๋‹˜์ด "๋น…๋งฅ ํ•˜๋‚˜!" ์ฃผ๋ฌธํ–ˆ์„ ๋•Œ ๊ณต์žฅ ๋‚ด๋ถ€์—์„œ ์ผ์–ด๋‚˜๋Š” 4๋‹จ๊ณ„ ์ตœ์ ํ™”:

  • 1๋‹จ๊ณ„ (Router Cache - ๋‚ด ์Šค๋งˆํŠธํฐ): "์–ด? ๋‚˜ ๋ฐฉ๊ธˆ ๋น…๋งฅ ์‹œ์ผฐ์—ˆ๋Š”๋ฐ. ๋ฐฐ๋‹ฌ ์•ˆ ์‹œํ‚ค๊ณ  ๋‚ด ์ฃผ๋จธ๋‹ˆ์—์„œ ์•„๊นŒ ์‹œํ‚จ ๋น…๋งฅ(์‚ฌ์ง„) ๊บผ๋‚ด์„œ ๋ด์•ผ์ง•~" (์ƒˆ๋กœ๊ณ ์นจ ์ „๊นŒ์ง€ ์œ ์ง€)
  • 2๋‹จ๊ณ„ (Request Memoization - ํ•œ ๋ฒˆ ๋ฐฐ๋‹ฌํ•  ๋•Œ): "์ด๋ฒˆ์—” ์ง„์งœ ๋ฐฐ๋‹ฌ ์‹œ์ผฐ์–ด. ์ฃผ๋ฐฉ์žฅ์ด ๊ณ ๊ธฐ ๊ตฝ๋Š”๋ฐ, ๋‚ด๊ฐ€ ๊ณ ๊ธฐ(fetch) 2๋ฒˆ ๊ฐ–๋‹ค ๋‹ฌ๋ผ๊ณ  ํ•ด๋„ ์ฃผ๋ฐฉ์žฅ์ด ๋ฌด์‹œํ•˜๊ณ  ํ•œ ๋ฒˆ ๊ตฌ์šด ๊ณ ๊ธฐ๋ฅผ ๋ฐ˜๋ฐ˜ ๋‚˜๋ˆ ์คŒ!"
  • 3๋‹จ๊ณ„ (Data Cache - ์ฃผ๋ฐฉ์˜ ์˜๊ตฌ ๋ƒ‰๋™๊ณ ): "์–ด์ œ ๋“ค์–ด์˜จ ํŠน์ œ ์†Œ์Šค(DB ๊ฒฐ๊ณผ)๋ฅผ ์˜๊ตฌ ๋ƒ‰๋™๊ณ ์— ๋ณด๊ด€ํ•ด๋’€์–ด. ๋‚ด์ผ ์†๋‹˜์ด ์™€๋„, ๋ชจ๋ ˆ ์™€๋„ ์•ˆ ๋ฒ„๋ฆฌ๊ณ  ๋˜‘๊ฐ™์€ ์†Œ์Šค๋ฅผ ๊ณ„์† ๋ฟŒ๋ฆด ๊ฑฐ์•ผ!"
  • 4๋‹จ๊ณ„ (Full Route Cache - ์ง„์—ด์žฅ์˜ ๋ชจํ˜• ํ–„๋ฒ„๊ฑฐ): "์•„์˜ˆ ์†Œ์Šค, ๋นต, ์•ผ์ฑ„๋ฅผ ๋‹ค ์กฐ๋ฆฝํ•ด๋‘” ์™„์ œํ’ˆ ๋น…๋งฅ(HTML ํŒŒ์ผ ์ž์ฒด)์„ ๊ฐ€๊ฒŒ ์•ž์— ์œ ๋ฆฌ์žฅ์‹์œผ๋กœ ๊ฑธ์–ด๋’€์–ด! ์ฃผ๋ฌธ ์˜ค๋ฉด ์ฃผ๋ฐฉ์žฅ ์•ˆ ๊นจ์šฐ๊ณ  ์ € ๋ชจํ˜• ๋ฐ”๋กœ ๋˜์ ธ์คŒ ใ…‹ใ…‹ใ…‹"

๐Ÿงฉ 1๋‹จ๊ณ„: Request Memoization (์ˆ˜๋ช… 1์ดˆ์˜ ํ•จ์ˆ˜ ์บ์‹œ) ๐ŸŸข

์ด๊ฑด ์ด๋ฏธ guide 6์žฅ์—์„œ ๋งˆ์Šคํ„ฐํ•œ ๋‚ด์šฉ์ด์•ผ. ๊ฐ€๋ณ๊ฒŒ ์งš๊ณ  ๋„˜์–ด๊ฐ€์ž.

ํŠน์ง• ์š”์•ฝ

  • ๋ชฉ์ : ๊นŠ๊ณ  ๋ณต์žกํ•œ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ํ•˜์œ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋˜‘๊ฐ™์ด ๋˜ ํ˜ธ์ถœํ•  ๋•Œ, ๋„คํฌ์›Œํฌ ๋ถ€ํ•˜ ๋ฐฉ์ง€ (Props Drilling ํšŒํ”ผ)
  • ๋Œ€์ƒ: ์˜ค๋กœ์ง€ GET ๋ฐฉ์‹์˜ fetch() ํ•จ์ˆ˜. (๊ทธ๋ฆฌ๊ณ  ์ˆ˜๋™์œผ๋กœ ๋ž˜ํ•‘ํ•œ React.cache)
  • ์ˆ˜๋ช…: ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์„ ๊ฐฑ์‹ ํ•˜๋Š” ๋”ฑ ๊ทธ "ํ•œ ๋ฒˆ์˜ ๋ Œ๋”๋ง ํ„ด(Lifecycle)" ๋™์•ˆ๋งŒ ์‚ด์•„์žˆ์Œ.
  • ์ดˆ๊ธฐํ™”(Revalidation) ๋ฐฉ๋ฒ•: ์—†์Œ. ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง์ด ๋”ฑ ๋๋‚˜๋Š” 1์ดˆ ๋’ค์— ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์—ฐ๊ธฐ์ฒ˜๋Ÿผ ์‚ฌ๋ผ์ง.

๐ŸŒฑ 2๋‹จ๊ณ„: Data Cache (DB ์ฟผ๋ฆฌ์˜ ์˜๊ตฌ ๋ณด์กด) ๐ŸŸก

์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ ์˜์ฒ ์ด๊ฐ€ ์‹ค์ œ๋กœ ๋””๋ฒ„๊น…ํ•ด์•ผ ํ•  ๋ฒ”์œ„๊ฐ€ ๋„“์–ด์ ธ. ์ €์žฅ์€ ๋๋Š”๋ฐ ํ™”๋ฉด์ด ๊ฐฑ์‹ ๋˜์ง€ ์•Š์„ ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ์˜์‹ฌํ•  ๊ณ„์ธต์ด์ง€.

ํŠน์ง•

  • ๋ชฉ์ : ๊ฐ™์€ URL๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋“ค์–ด์˜ค๋Š” ์™ธ๋ถ€ API ์‘๋‹ต์ด๋‚˜ ์บ์‹œ ๊ฐ€๋Šฅํ•œ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ์„œ๋ฒ„ ์บ์‹œ์— ์ €์žฅํ•ด ์žฌ์‚ฌ์šฉํ•จ.
  • ๋Œ€์ƒ: fetch() ์‘๋‹ต๊ฐ’ ๊ทธ ์ž์ฒด.
  • ์ˆ˜๋ช…: cache: 'force-cache', next.revalidate, cacheLife, ํƒœ๊ทธ ๋ฌดํšจํ™” ๊ฐ™์€ ์ •์ฑ…์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง.

โŒ ์˜์ฒ ์ด์˜ ํ•จ์ • (๊ธฐ๋ณธ ์บ์‹œ ๋Šช)

// app/notice/page.tsx
export default async function NoticeInfo() {
  // Next 13/14 ์ด์ „ ๋ชจ๋ธ์—์„œ๋Š” ๊ธฐ๋ณธ ์บ์‹œ ๋™์ž‘์„ ํŠนํžˆ ์กฐ์‹ฌํ•ด์•ผ ํ–ˆ๋‹ค.
  // ํ˜„์žฌ ๋ฒ„์ „์—์„œ๋„ force-cache๋‚˜ revalidate๋ฅผ ๋ช…์‹œํ•˜๋ฉด ๊ฐฑ์‹  ์ •์ฑ…์ด ํ•„์š”ํ•˜๋‹ค.
  const res = await fetch('https://db.api/api/notice/urgent', {
    next: { revalidate: 3600 },
  });
  const data = await res.json();
  return <div>{data.title}</div>
}

โœ… ์ œ์–ด๊ถŒ ๋˜์ฐพ๊ธฐ (Opting out)

์ˆ˜์ฒœ ๊ฐ€์ง€์˜ "์บ์‹œ ์•ˆ ํ•ด!" ํƒˆ์ถœ ๋ฐฉ๋ฒ•์ด ์žˆ์–ด.

1) ๋ถ€๋ถ„ ํƒˆ์ถœ (Fetch ๋ ˆ๋ฒจ)
fetch(url, { cache: 'no-store' }) // Next.js์•ผ, ์ œ๋ฐœ ์ด ์ฟผ๋ฆฌ๋งŒํผ์€ ๋งค๋ฒˆ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ฐ€์ ธ์˜ค๋ ด!

2) ํŒŒ์ผ ์ „์ฒด ํƒˆ์ถœ (Segment Configuration)

export const dynamic = 'force-dynamic' // ์ด ํŒŒ์ผ(page) ๋‚ด์˜ ๋ชจ๋“  ๋กœ์ง ์บ์‹œ ๊ฑฐ๋ถ€!
 
export default async function Page() { ... }

3) ์‹œ๊ฐ„์ œ ๋ณด๊ด€ (ISR - Time based Revalidation)
fetch(url, { next: { revalidate: 3600 } }) // Next.js์•ผ, ์ด๊ฑฐ 1์‹œ๊ฐ„(3600์ดˆ) ์นด์šดํŠธ๋‹ค์šดํ•˜๊ณ  ์บ์‹œ ํ๊ธฐํ•ด.


๐Ÿ›ก๏ธ 3๋‹จ๊ณ„: Full Route Cache (์™„์„ฑ๋œ HTML์˜ ํ™”์„ํ™”) ๐Ÿ”ด

Data Cache๊ฐ€ "DB ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ(JSON)"๋ฅผ ์กฐ๊ฐ์กฐ๊ฐ ์–ผ๋ ค๋‘๋Š” ๊ฑฐ๋ผ๋ฉด, Full Route Cache๋Š” ๋” ๊ทน๊ฐ•์˜ ๋ณ‘๊ธฐ์•ผ.
์•„์˜ˆ ํ™”๋ฉด ์ „์ฒด HTML/RSC ๊ฒฐ๊ณผ๋ฅผ ๋นŒ๋“œ ํƒ€์ž„์ด๋‚˜ ์žฌ๊ฒ€์ฆ ์‹œ์ ์— ๋งŒ๋“ค์–ด ๋‘๊ณ  ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ณ„์ธต์ด๋ผ๊ณ  ๋ณด๋ฉด ๋ผ.

ํŠน์ง•

  • ๋ชฉ์ : ์„œ๋ฒ„ ๊นกํ†ต CPU๋ฅผ ์•„๋ผ๊ธฐ ์œ„ํ•ด, 1์ดˆ์˜ ์ง€์—ฐ๋„ ์—†์ด ๋ฒˆ๊ฐœ์ฒ˜๋Ÿผ ํ™”๋ฉด์„ ์‘๋‹ตํ•˜๊ธฐ ์œ„ํ•œ ์™„์ œํ’ˆ ๋ณด๊ด€.
  • ์ˆ˜๋ช…: ์˜๊ตฌ์ . ๋‹ค์Œ ๋นŒ๋“œ(Build)๋ช…๋ น npm run build๋ฅผ ์ƒˆ๋กœ ์น˜๊ธฐ ์ „๊นŒ์ง€ ์‚ฌ๋ผ์ง€์ง€ ์•Š์Œ.
  • ์กฐ๊ฑด: ์š”์ฒญ๋งˆ๋‹ค ๋‹ฌ๋ผ์ง€๋Š” ์ž…๋ ฅ(cookies, headers, ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ๋“ฑ)์ด ์—†๊ณ , ๋ผ์šฐํŠธ๊ฐ€ ์ •์ ์œผ๋กœ ํ‰๊ฐ€๋  ์ˆ˜ ์žˆ์„ ๋•Œ.

๐Ÿ”„ Static vs Dynamic ๋ฃจํŠธ ํŒ๋…๊ธฐ

ํ„ฐ๋ฏธ๋„์—์„œ npm run build๋ฅผ ์ณค์„ ๋•Œ ๋œจ๋Š” ์„ฑ์ ํ‘œ๋ฅผ ์ž˜ ๋ด์•ผ ํ•ด.

Route (app)                       Size     First Load JS
โ”Œ โ—‹ /                             154 B    86.6 kB
โ”œ โ—‹ /about                        154 B    86.6 kB
โ”” ฦ’ /profile/[id]                 154 B    86.6 kB
 
โ—‹  (Static)   prerendered as static HTML (uses no initial data)
ฦ’  (Dynamic)  server-rendered on demand using Node.js
  • โ—‹ (Static) ํŒ์ •์˜ ๋น„๋ฐ€: ๋ผ์šฐํŠธ ๊ฒฐ๊ณผ๊ฐ€ ์š”์ฒญ๋ณ„ ์ž…๋ ฅ์— ์˜์กดํ•˜์ง€ ์•Š์„ ๋•Œ ํš๋“ํ•œ๋‹ค. ๊ณต๊ฐœ ๋งˆ์ผ€ํŒ… ํŽ˜์ด์ง€๋‚˜ ์ผ์ • ์‹œ๊ฐ„ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชฉ๋ก์ด ์—ฌ๊ธฐ์— ์–ด์šธ๋ฆฐ๋‹ค.
  • ฦ’ (Dynamic) ํŒ์ •: ๋กœ๊ทธ์ธ ์ธ์ฆ์ฒ˜๋Ÿผ cookies()๋‚˜ headers()์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์š”์ฒญ๋งˆ๋‹ค ๋‹ค์‹œ ํŒ๋‹จํ•ด์•ผ ํ•œ๋‹ค. ๊ฐœ์ธํ™” ๋ฐ์ดํ„ฐ๋ฅผ ์ •์  HTML์— ์„ž์œผ๋ฉด ์บ์‹œ ์˜ค์—ผ์ด ์ƒ๊ธด๋‹ค.

[์˜์ฒ ์ด ์—๋Ÿฌ์˜ ์ง„์ƒ ๊ทœ๋ช…]
์˜์ฒ ์ด์˜ ๊ณต์ง€์‚ฌํ•ญ ํŽ˜์ด์ง€๋Š” ๊ณต๊ฐœ ๋ฐ์ดํ„ฐ๋ผ ์บ์‹œ ํ›„๋ณด์˜€์–ด. DB ๊ฐ’ ์—…๋ฐ์ดํŠธ ๋กœ์ง(Admin)๋งŒ ๋งŒ๋“ค๊ณ , ์œ ์ €๊ฐ€ ๋ณด๋Š” ๋ผ์šฐํŠธ์™€ ๋ฐ์ดํ„ฐ ํƒœ๊ทธ๋ฅผ ๋‹ค์‹œ ๊ฒ€์ฆํ•˜๋ผ๋Š” ๋ช…๋ น(revalidatePath, revalidateTag, updateTag)์„ ์—ฐ๊ฒฐํ•˜์ง€ ์•Š์•˜๋˜ ๊ฑฐ์•ผ.


๐Ÿšฅ 4๋‹จ๊ณ„: Router Cache (ํด๋ผ์ด์–ธํŠธ ํƒญ ๋ฉ”๋ชจ๋ฆฌ) ๐ŸŸฃ

์„œ๋ฒ„๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์œ„ 3๊ฐœ์˜ ์บ์‹œ์™€ ๋‹ค๋ฅด๊ฒŒ, ๋งˆ์ง€๋ง‰ ๋ฐฉ์–ด์„ ์€ ์‚ฌํŒŒ๋ฆฌ/ํฌ๋กฌ ๋ธŒ๋ผ์šฐ์ € ์† ์‚ฌ์šฉ์ž ์ปดํ“จํ„ฐ์˜ ๋ฉ”๋ชจ๋ฆฌ(RAM) ์•ˆ์— ์‚ด์•„์žˆ์–ด.

๋ธŒ๋ผ์šฐ์ €๋Š” ๋˜‘๋˜‘ํ•˜๊ณ  ๊ฒŒ์œผ๋ฅด๋‹ค

Next.js App Router๋กœ ๋„ค๋น„๊ฒŒ์ด์…˜(Link ํƒœ๊ทธ ํด๋ฆญ)์„ ํ•˜๋ฉด, ๊ธฐ์กด ๋ฆฌ์•กํŠธ์ฒ˜๋Ÿผ ์„œ๋ฒ„๋กœ ์•ˆ ๊ฐ€๊ณ  ๋ธŒ๋ผ์šฐ์ € ์•ˆ์— ๊ฟ์ณ๋‘” ๋ Œ๋”๋ง ์กฐ๊ฐ ๋ชจ์Œ(RSC Payload)์„ ๊บผ๋‚ด์จ.

  • ์ˆ˜๋ช…: ๋ธŒ๋ผ์šฐ์ € ํƒญ์„ X๋กœ ๋‹ซ๊ฑฐ๋‚˜ ์ƒˆ๋กœ๊ณ ์นจ(F5)์„ ๋ˆ„๋ฅด๊ธฐ ์ „๊นŒ์ง€(๋˜๋Š” 30์ดˆ~5๋ถ„ ๋‚ด์™ธ ๋ฉ”๋ชจ๋ฆฌ ์ •์ฑ… ๋งŒ๋ฃŒ ์ „๊นŒ์ง€).
  • ์ด ๋Œ€์ƒ ๋•Œ๋ฌธ์— "๋‚˜ ๋ฐฉ๊ธˆ ๊ธ€ ์ผ๋Š”๋ฐ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ˆŒ๋ €๋”๋‹ˆ ์˜›๋‚  ๋ชฉ๋ก ๋œจ๋„ค?" ๊ฐ™์€ ๋ฒ„๊ทธ์„ฑ ์ฒด๊ฐ์ด ๊ฐ„ํ—์ ์œผ๋กœ ๋ฐœ์ƒํ•ด.

๐Ÿ”จ ๋ฌดํšจํ™”ํ•˜๊ธฐ (Invalidation)

์ด ์บ์‹œ๊ฐ€ ๋ฐฉํ•ด๊ฐ€ ๋  ๋•Œ๋Š” ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ "๋„ค์ž„ํŽœ์œผ๋กœ ์“ด ๋ฉ”๋ชจ ์ˆ˜์ฒฉ ๋น„์›Œ!"๋ผ๊ณ  ๋ช…๋ นํ•ด์•ผ ํ•ด.

'use client'
import { useRouter } from 'next/navigation'
 
export default function ReRouteButton() {
  const router = useRouter()
  return <button onClick={() => router.refresh()}>๊ฐ•์ œ ๊ฐฑ์‹ (๋ธŒ๋ผ์šฐ์ € ์บ์‹œ ๋ฌดํšจํ™”)!</button>
}

router.refresh() ๋Š” ํ™”๋ฉด ๋ฐฑ์ง€ํ™” ์—†์ด ์˜ค์ง ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ ์„œ๋ฒ„์˜ ์ตœ์‹  RSC Payload๋งŒ ์ƒˆ๋กœ ์‹น ๋‚ด๋ ค๋ฐ›์•„ ์น˜ํ™˜ํ•˜๋Š” ๋งˆ๋ฒ•์˜ ๊ณ ๊ธ‰ ํ›…์ด์•ผ.


๐Ÿ’ฅ ์—๋Ÿฌ ํ•ด๊ฒฐ ์นดํƒˆ๋กœ๊ทธ

์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ๋œจ๋ฉด Ctrl+F๋กœ ๊ฒ€์ƒ‰ํ•ด๋ด.

โŒ Dynamic server usage: cookies ์—๋Ÿฌ๊ฐ€ ๋œจ๋ฉด์„œ ๋นŒ๋“œ๊ฐ€ ์‹คํŒจํ•ด์š”!

์›์ธ: generateStaticParams ์™€ ๊ฐ™์ด '๋ฏธ๋ฆฌ ์ •์ ์œผ๋กœ(Static) ๊ตฌ์›Œ๋‘๋ ค๊ณ  ์ž‘์ •'ํ•œ ํŒŒ์ผ ๊ณต๊ฐ„ ๋‚ด๋ถ€์—์„œ, cookies() ๋‚˜ URL ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ™์ด ์‹ค์‹œ๊ฐ„ ๋Ÿฐํƒ€์ž„์—๋งŒ ์•Œ ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ๋ฌด๋ฆฌํ•˜๊ฒŒ ๊บผ๋‚ด ์“ฐ๋ ค๋‹ค ๋ชจ์ˆœ์ด ๋ฐœ์ƒํ•œ ๊ฒƒ.
ํ•ด๊ฒฐ์ฑ…: ํŽ˜์ด์ง€์— export const dynamic = 'force-dynamic' ์„ ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•˜์—ฌ ์ด ํŒŒ์ผ์€ ์ ˆ๋Œ€ ํ™”์„(Static)์œผ๋กœ ๋‚จ์„ ์ˆ˜ ์—†๋Š” ์šด๋ช…์ž„์„ Next.js์—๊ฒŒ ์ž๋ฐฑํ•ด๋ผ.


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

์ด ๊ฑฐ๋Œ€ํ•œ 4์ค‘ ์žฅ๋ฒฝ์˜ ๋ฐฉ์–ด ์ˆœ์„œ! ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์„ ๋‹ฌ๋ผ๊ณ  ์กฐ๋ฅด๋ฉด...

๊ป์งˆ ๊ณ„์ธต ์ˆœ์„œํŠ•๊ฒจ๋‚ด๋Š” ๋‹จ๊ณ„์บ์‹œ ์œ„์น˜๋ฌด๋ ฅํ™” ๋ฐฉ๋ฒ•
1๋ฒˆ ๋ฐฉ์–ด๋ง‰Router Cache: "์•ผ ๋ธŒ๋ผ์šฐ์ €์•ผ, ๋„ˆ ์•„๊นŒ ์ด๊ฑฐ ๋ฐฉ๋ฌธํ–ˆ์—ˆ์ž–์•„. ๋‚ด RAM์— ์ €์žฅ๋œ ๊ฑฐ ์ค„๊ฒŒ."ํด๋ผ์ด์–ธํŠธ (๋ธŒ๋ผ์šฐ์ €)router.refresh() / ํŽ˜์ด์ง€ ์ฐฝ ๋‹ซ๊ธฐ / F5 ๊ฐ•์ œ ์„ธ๋กœ๊ณ ์นจ
2๋ฒˆ ๋ฐฉ์–ด๋ง‰Full Route Cache: (์„œ๋ฒ„ ๋„๋‹ฌ) "์–ด? ๋„ˆ๊ฐ€ ์ฐพ๋Š” HTML, ๋‚ด๊ฐ€ ์ €๋ฒˆ ๋นŒ๋“œ ๋•Œ ์™„์ œํ’ˆ ํ™”์„์œผ๋กœ ๊ตฌ์›Œ๋†จ์ง€!"์„œ๋ฒ„ (๋””์Šคํฌ)์žฌ๋นŒ๋“œ(build) / revalidatePath ์„œ๋ฒ„์•ก์…˜ ํƒ€๊ฒฉ
3๋ฒˆ ๋ฐฉ์–ด๋ง‰Request Memoization: (์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง ์ค‘) "์•— ๋˜‘๊ฐ™์€ fetch ๋„ค? ์ฃผ๋ฐฉ์žฅ ๊ณ ์ƒํ•˜์ง€ ๋ง๊ณ  ๋‚ด ๊ธฐ์–ต(๋ฉ”๋ชจ๋ฆฌ)์—์„œ ๋ณต์‚ฌํ•ด์ค„๊ฒŒ."์„œ๋ฒ„ (๋ฉ”๋ชจ๋ฆฌ ๋‹จ๋ฐœ์„ฑ)์กฐ์น˜ ํ•„์š” ์—†์Œ (1 ๋Ÿฐํƒ€์ž„ ์ข…๋ฃŒ ์‹œ ์ž๋™ ํ๊ธฐ)
4๋ฒˆ ๋ฐฉ์–ด๋ง‰Data Cache: "๊ฒฐ๊ตญ ์ง„์งœ ๋ฐ์ดํ„ฐ ์ฐŒ๋ฅด๋ ค ์™”๋„ค? ๊ทผ๋ฐ ๊ทธ API ๊ฒฐ๊ณผ๊ฐ’ 5์‹œ๊ฐ„ ๋™์•ˆ ์–ผ๋ ค๋‘” ๋‚ด DB ์บ์‹œ ์ฐฝ๊ณ ์—์„œ ์ค„๊ฒŒ ใ…‹ใ…‹ใ…‹"์„œ๋ฒ„ (๋””์Šคํฌ)fetch { cache: no-store } / revalidateTag ๋“ฑ

๐Ÿ’ก ์‹œ๋‹ˆ์–ด์˜ ๋ฉ˜ํƒˆ ๋ชจ๋ธ
๋นŒ๋“œ ์‹œ โ—‹ (Static) ๋กœ ๊ตณ์–ด๋ฒ„๋ฆฐ ๋ผ์šฐํŠธ๋Š” Data Cache๋ฅผ ๋ฌดํšจํ™”ํ•˜๊ธฐ ์ „๊นŒ์ง€ ์ ˆ๋Œ€ ์ž๊ธฐ ์Šค์Šค๋กœ ๊ฐฑ์‹ ๋˜์ง€ ์•Š๋Š”๋‹ค.
"๋ฐ์ดํ„ฐ๊ฐ€ ์•ˆ ๋ฐ”๋€Œ์–ด์š”!" ๋ผ๋Š” ์งˆ๋ฌธ์— ๋‹นํ™ฉํ•˜์ง€ ๋ง๊ณ , ๊ฐ€์žฅ ๋จผ์ € Vercel ๋นŒ๋“œ ํ„ฐ๋ฏธ๋„ ์ฐฝ์„ ์—ด๊ณ  ๊ทธ ํŽ˜์ด์ง€๊ฐ€ โ—‹ ์ธ์ง€ ฦ’ ์ธ์ง€๋ถ€ํ„ฐ ์ƒ‰์ถœํ•˜๋ผ!


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

Q1. ์˜์ฒ ์ด๊ฐ€ /profile/me ํŽ˜์ด์ง€์—์„œ cookies()๋กœ ์„ธ์…˜์„ ์ฝ๊ณ  ์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ๋ Œ๋”๋งํ•œ๋‹ค. ์ด ํŽ˜์ด์ง€๋ฅผ Full Route Cache๋กœ ์ •์ ์œผ๋กœ ๊ตฌ์›Œ๋„ ๋ ๊นŒ?

โœ… ์ •๋‹ต: ์•ˆ ๋œ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: /profile/me๋Š” ์š”์ฒญ ์ฟ ํ‚ค์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์ง€๋Š” ๊ฐœ์ธํ™” ํŽ˜์ด์ง€๋‹ค. cookies(), headers() ๊ฐ™์€ ์š”์ฒญ ์‹œ์  API๋ฅผ ์“ฐ๋ฉด ์ •์  HTML ํ•˜๋‚˜๋ฅผ ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์—†๋‹ค. ์˜ํ˜ธ๊ฐ€ ๊ฐ•์กฐํ•œ ๊ธฐ์ค€์€ ๊ฐ„๋‹จํ•˜๋‹ค. ์š”์ฒญ๋งˆ๋‹ค ๋‹ฌ๋ผ์ง€๋Š” ์ž…๋ ฅ์ด ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”๊พธ๋ฉด Full Route Cache ๋Œ€์ƒ์ด ์•„๋‹ˆ๋‹ค. ๊ณต๊ฐœ ํ”„๋กœํ•„์ฒ˜๋Ÿผ URL ํŒŒ๋ผ๋ฏธํ„ฐ๋งŒ์œผ๋กœ ๊ฒฐ๊ณผ๊ฐ€ ๊ฒฐ์ •๋˜๋Š” ๊ตฌ์กฐ์™€ ๋ถ„๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.


Q2. ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€์—์„œ ๊ณต์ง€ ์ œ๋ชฉ์„ ์ˆ˜์ •ํ–ˆ๋Š”๋ฐ ๋ฉ”์ธ ๊ณต์ง€ ๋ชฉ๋ก์ด ๊ณ„์† ์˜ˆ์ „ ์ œ๋ชฉ์„ ๋ณด์—ฌ์ค€๋‹ค. ์„œ๋ฒ„์— ๋‚จ์•„ ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๊ฐ€์žฅ ํฐ ์บ์‹œ๋Š” ๋ฌด์—‡์ธ๊ฐ€?

โœ… ์ •๋‹ต: Data Cache ๋˜๋Š” ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•ด ๋งŒ๋“ค์–ด์ง„ Full Route Cache๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: Request Memoization์€ ํ•œ ๋ฒˆ์˜ ๋ Œ๋”๋ง ๋™์•ˆ๋งŒ ์ค‘๋ณต fetch๋ฅผ ํ•ฉ์น˜๋Š” ์ž„์‹œ ๊ธฐ์–ต์ด๊ณ , Router Cache๋Š” ๋ธŒ๋ผ์šฐ์ € ์„ธ์…˜์˜ RSC Payload ๊ธฐ์–ต์ด๋‹ค. ์ƒˆ ์š”์ฒญ์—์„œ๋„ ๋‚ก์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ˜๋ณต๋œ๋‹ค๋ฉด ์„œ๋ฒ„ ์ชฝ Data Cache๊ฐ€ ๊ฐฑ์‹ ๋˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜, ๊ทธ ๋ฐ์ดํ„ฐ๋กœ ๋งŒ๋“  Full Route Cache๊ฐ€ ์•„์ง ์žฌ๊ฒ€์ฆ๋˜์ง€ ์•Š์•˜์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค. ์ˆ˜์ • ์•ก์…˜์—๋Š” revalidateTag๋‚˜ revalidatePath ๊ฐ™์€ ๋ฌดํšจํ™” ์ „๋žต์ด ํ•จ๊ป˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.


Q3. ์˜์ฒ ์ด์˜ ํ…Œ์ŠคํŠธ ํƒ€์ž„: ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ํ™ˆ์€ ๊ณต๊ฐœ ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก๊ณผ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ์•Œ๋ฆผ ๋ฐฐ์ง€๋ฅผ ํ•จ๊ป˜ ๋ณด์—ฌ์ค€๋‹ค. ์ „์ฒด ํŽ˜์ด์ง€๋ฅผ Dynamic์œผ๋กœ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ๋น ๋ฅธ ์ฒซ ํ™”๋ฉด๋„ ์ง€ํ‚ค๊ณ  ์‹ถ๋‹ค. ์–ด๋–ค ์„ค๊ณ„๊ฐ€ ๋” ์•ˆ์ „ํ• ๊นŒ?

โœ… ์ •๋‹ต: ๊ณต๊ฐœ ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์€ ์บ์‹œ ๊ฐ€๋Šฅํ•œ ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋กœ ๋‘๊ณ , ์•Œ๋ฆผ ๋ฐฐ์ง€๋Š” ์š”์ฒญ ์‹œ์  ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๋ณ„๋„ ๊ฒฝ๊ณ„๋กœ ๋ถ„๋ฆฌํ•œ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: ๊ณต๊ฐœ ๋ชฉ๋ก์€ ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฏ€๋กœ Data Cache๋‚˜ Full Route Cache์˜ ํ›„๋ณด๊ฐ€ ๋œ๋‹ค. ๋ฐ˜๋ฉด ์•Œ๋ฆผ ๋ฐฐ์ง€๋Š” ์ฟ ํ‚ค์™€ ์‚ฌ์šฉ์ž๋ณ„ ๊ถŒํ•œ์— ์˜์กดํ•˜๋ฏ€๋กœ ์ •์  ์…ธ ์•ˆ์— ์„ž์œผ๋ฉด ์บ์‹œ ์˜ค์—ผ์ด ์ƒ๊ธด๋‹ค. ์˜ํ˜ธ๋ผ๋ฉด "๋ฌด์—‡์„ ์บ์‹œํ• ์ง€"๋ณด๋‹ค ๋จผ์ € ์–ด๋–ค ์ž…๋ ฅ์ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”๊พธ๋Š”์ง€๋ฅผ ํ‘œ๋กœ ๋‚˜๋ˆ„๋ผ๊ณ  ๋ฆฌ๋ทฐํ•  ๊ฒƒ์ด๋‹ค.

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

์˜ค๋Š˜์€ ์บ์‹œ๋ฅผ ํ•˜๋‚˜์˜ ์Šค์œ„์น˜์ฒ˜๋Ÿผ ๋ณด๋˜ ์Šต๊ด€์„ ๋ฒ„๋ ธ๋‹ค. Request Memoization, Data Cache, Full Route Cache, Router Cache๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ์ˆ˜๋ช…๊ณผ ์œ„์น˜๋ฅผ ๊ฐ€์ง„๋‹ค๋Š” ๊ฑธ ์•Œ๊ณ  ๋‚˜๋‹ˆ, "์™œ ์ƒˆ๋กœ๊ณ ์นจํ–ˆ๋Š”๋ฐ๋„ ๊ทธ๋Œ€๋กœ์ง€?"๋ผ๋Š” ์งˆ๋ฌธ๋„ ํ›จ์”ฌ ์ •ํ™•ํ•ด์กŒ๋‹ค.

๐Ÿ’ก "์บ์‹œ๋Š” ๋น ๋ฅด๊ฒŒ ๋งŒ๋“œ๋Š” ์žฅ์น˜๊ฐ€ ์•„๋‹ˆ๋ผ, ๊ฐ™์€ ๊ฒฐ๊ณผ๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„๋ฅผ ์„ ์–ธํ•˜๋Š” ์žฅ์น˜๋‹ค."

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

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