๐ŸงŠ Next.js ์‹ฌํ™” 2์žฅ: `use cache`์™€ ๋ถ€๋ถ„ ์บ์‹ฑ (Next.js 15+ ์ตœ์‹  ํŠธ๋ Œ๋“œ)

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

๐Ÿ“‹ ๊ฐœ์š”

Next.js 15+์˜ use cache ์ง€์‹œ์–ด์™€ ๋ถ€๋ถ„ ์บ์‹ฑ์œผ๋กœ ์„ธ๋ฐ€ํ•œ ์บ์‹ฑ ์ „๋žต์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ


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

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

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

  • ์˜์ฒ (์‹ ์ž…): "Next.js 15+๋กœ ๋„˜์–ด์˜ค๋‹ˆ ๊ธฐ๋ณธ fetch๊ฐ€ ์˜ˆ์ „์ฒ˜๋Ÿผ ์•Œ์•„์„œ ์˜ค๋ž˜ ์บ์‹œ๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ์•ˆ ๋˜๊ฒ ๋”๋ผ๊ณ ์š”. ๋ฌด๊ฑฐ์šด ํ†ต๊ณ„ ์ปดํฌ๋„ŒํŠธ๋Š” ์žฌ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€๋ฐ, ์–ด๋””๊นŒ์ง€ ์บ์‹œํ•ด๋„ ์•ˆ์ „ํ•œ์ง€ ์ฝ”๋“œ์—์„œ ๋ช…ํ™•ํžˆ ํ‘œํ˜„ํ•  ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ์š”?"
  • ์˜ํ˜ธ(๋ฆฌ๋“œ): "๊ทธ๋•Œ ๋ณด๋Š” ๊ฒŒ Cache Components์™€ 'use cache'์˜ˆ์š”. next.config.ts์—์„œ cacheComponents: true๋ฅผ ์ผœ๊ณ , ํ•จ์ˆ˜๋‚˜ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ณ„์‚ฐ๋งŒ ์บ์‹œ ๋Œ€์ƒ์œผ๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, cacheLife, cacheTag, updateTag๊นŒ์ง€ ๊ฐ™์ด ์„ค๊ณ„ํ•ด์•ผ ์šด์˜์—์„œ ์•ˆ์ „ํ•ด์š”."

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„
Next 15์˜ ์บ์‹œ ์„ ์–ธํ˜• ์‹œ๋Œ€ โ†’ use cache์˜ ์Šค์ฝ”ํ”„ ์ ์šฉ๋ฒ• โ†’ ๋Œ€๋ง์˜ PPR (์ ˆ๋ฐ˜๋งŒ ํ™”์„ ๋งŒ๋“ค๊ธฐ) ๊ธฐ์ˆ 

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

  • ๋ฌด๊ฑฐ์šด ์จ๋“œํŒŒํ‹ฐ SDK๋‚˜ ์ง์ ‘ ์ง  ์Šฌ๋กœ์šฐ ์ฟผ๋ฆฌ ํ•จ์ˆ˜ ์ž์ฒด์— 'use cache' ์ง€์‹œ์ž๋ฅผ ๋‹ฌ์•„ ์ปดํฌ๋„ŒํŠธ ๋ ˆ๋ฒจ์˜ ์บ์‹ฑ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ง์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ •์ ์ธ ๊ป๋ฐ๊ธฐ ์•ˆ์— ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํ’ˆ์€ <Suspense> ๊ตฌ์—ญ์„ ์„ž์–ด, PPR ์•„ํ‚คํ…์ฒ˜์˜ ํ˜๋ช…์ ์ธ TTFB(0.1์ดˆ ์ดˆ๊ธฐ ๋กœ๋”ฉ)๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

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

์‹ฌํ™” 1์žฅ์—์„œ ์šฐ๋ฆฌ๋Š” ์บ์‹œ ์ˆ˜๋ช…์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋ฉด ํ™”๋ฉด์ด ๋‚ก์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑธ ๋ดค์–ด. ์ตœ์‹  Next.js์—์„œ๋Š” Cache Components ๋ชจ๋ธ์ด ๊ฐ•ํ™”๋˜๋ฉด์„œ "์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์กฐ๊ฐ์„ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•˜๊ณ , ๊ทธ ์กฐ๊ฐ์˜ ์ˆ˜๋ช…๊ณผ ๋ฌดํšจํ™” ๊ฒฝ๋กœ๋„ ํ•จ๊ป˜ ์ ๋Š”๋‹ค" ๋Š” ๋ฐฉํ–ฅ์ด ์ค‘์š”ํ•ด์กŒ์–ด.

์ด ์ƒˆ๋กœ์šด ์„ ์–ธ์  ์บ์‹ฑ ์‹œ๋Œ€์—์„œ ํ”„๋ก ํŠธ ์‹œ๋‹ˆ์–ด๋“ค์—๊ฒŒ ๊ฐ€์žฅ ํ•ซํ•œ ๋ฌด๊ธฐ๊ฐ€ ๋ฐ”๋กœ ์‹ฌํ™” 2์žฅ์˜ ์ฃผ์ œ์ธ 'use cache' ์˜ˆ์•ฝ์–ด์™€ PPR(๋ถ€๋ถ„ ๋ Œ๋”๋ง) ์ด์•ผ.

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


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

๐Ÿง’ 5์‚ด์—๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค๋ฉด? (์˜ํ˜ธ์˜ ๋น™๊ฒฐ ๋งˆ๋ฒ•์ฑ…)

โŒ ๊ณผ๊ฑฐ 14๋ฒ„์ „ (๋ˆˆ๋ณด๋ผ ๊ด‘์—ญ ๋งˆ๋ฒ•)
๋งˆ์„ ์ „์ฒด(ํŽ˜์ด์ง€ ํ†ต์งธ๋กœ)์— ๋ˆˆ๋ณด๋ผ๋ฅผ ๋‚ด๋ ค์„œ ์˜จ ๋™๋„ค๋ฅผ ์–ผ๋ ค๋ฒ„๋ ธ์–ด. ๋‹ค ๊ฝ๊ฝ ์–ผ์–ด๋ถ™์–ด์„œ ์žฅ์‚ฌ๋Š” ๋น ๋ฅธ๋ฐ ๋ˆˆ์‚ฌ๋žŒ์ด ์•ˆ ์›€์ง์—ฌ์„œ ๋‹ต๋‹ตํ–ˆ์–ด.

โœ… ํ˜„์žฌ 15๋ฒ„์ „ (ํ•€์…‹ ๋น™๊ฒฐ ๋งˆ๋ฒ• 'use cache')
์ด์ œ ์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ ์š”์ˆ  ์ง€ํŒก์ด ํ•˜๋‚˜๋ฅผ ๋“ค๊ณ  ๋‹ค๋…€.
"์–!" ํ•˜๊ณ  ์ง€ํŒก์ด('use cache')๋กœ ์น˜๋Š” ํŠน์ • ์ƒ์ž(ํ•จ์ˆ˜, ์ปดํฌ๋„ŒํŠธ)๋งŒ ๊ฝ๊ฝ ์–ผ์–ด๋ถ™์–ด์„œ (์บ์‹œ ์„œ๋ฒ„์— ์ €์žฅ), ๋‹ค์Œ๋ฒˆ ๋ถ€๋ฅผ ๋• ์—ฐ์‚ฐ 0์ดˆ ๋งŒ์— ์™„์ œํ’ˆ์ด ํŠ€์–ด๋‚˜์™€! ๋งˆ์„ ์‚ฌ๋žŒ๋“ค(๋‚˜๋จธ์ง€ ๋™์  ์š”์†Œ)์€ ์ถฅ์ง€ ์•Š๊ณ  ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ง‰ ๋›ฐ์–ด๋‹ค๋‹ ์ˆ˜ ์žˆ์ง€.


๐Ÿงฉ use cache ๋””๋ ‰ํ‹ฐ๋ธŒ: ํ•จ์ˆ˜ ์ˆ˜์ค€์˜ ์˜๊ตฌ ๋™๊ฒฐ ๐ŸŸข

'use client' ๋‚˜ 'use server' ์ฒ˜๋Ÿผ ํŒŒ์ผ, ์ปดํฌ๋„ŒํŠธ, ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„ ์ตœ์ƒ๋‹จ์— ๋ถ™์ด๋Š” ์ง€์‹œ์–ด์•ผ. ์ตœ์‹  ๊ณต์‹ ๋ฌธ์„œ ๊ธฐ์ค€์œผ๋กœ๋Š” Cache Components ๊ธฐ๋Šฅ์ด๋ฉฐ, next.config.ts์— cacheComponents: true๋ฅผ ์ผ  ๋’ค ์‚ฌ์šฉํ•œ๋‹ค.

๋จผ์ € ํ”„๋กœ์ ํŠธ ์„ค์ •์— ์บ์‹œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ช…์‹œํ•œ๋‹ค.

// next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  cacheComponents: true,
}
 
export default nextConfig

์ด ์„ค์ •์„ ์ผœ์•ผ 'use cache', cacheLife, cacheTag๋ฅผ ํ•˜๋‚˜์˜ ์บ์‹œ ๋ชจ๋ธ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ƒํ™ฉ: ๋ฌด๊ฑฐ์šด ํ†ต๊ณ„ ๋ถ„์„ ํ•จ์ˆ˜ (fetch๊ฐ€ ์•„๋‹˜!)

์˜์ฒ ์ด๊ฐ€ ์งœ๋†“์€ 5์ดˆ์งœ๋ฆฌ ์›”๊ฐ„ ์ง‘๊ณ„ ์ฟผ๋ฆฌ๊ฐ€ ์žˆ์–ด. fetch๋กœ ํ˜ธ์ถœํ•˜๋Š” ์™ธ๋ถ€ API๊ฐ€ ์•„๋‹ˆ๋ผ, Node.js ํ™˜๊ฒฝ์—์„œ DB ํด๋ผ์ด์–ธํŠธ(Prisma ๋“ฑ)์™€ ๋ฌด๊ฑฐ์šด ๊ณ„์‚ฐ์„ ์ง์ ‘ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜๋ผ๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

// app/lib/stats.ts
// fetch๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ "์–ด๋–ค ์ˆ˜๋ช…์œผ๋กœ ์žฌ์‚ฌ์šฉํ• ์ง€"๋ฅผ ๋ณ„๋„๋กœ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค.
export async function getHeavyMonthlyStats(year: number, month: number) {
  const rawData = await db.query(...);
  const result = heavyCPUCalculate(rawData); // ์—ฌ๊ธฐ์„œ 5์ดˆ๊ฐ„ ๋™๋™๋Œ...
  return result;
}

โœ… ๋น™๊ฒฐ ๋ถ€์  ๋ถ™์ด๊ธฐ ('use cache')

์บ์‹œ ๊ฐ€๋Šฅํ•œ ์ž…๋ ฅ๊ณผ ๊ฐฑ์‹  ์กฐ๊ฑด์ด ๋ถ„๋ช…ํ•˜๋‹ค๋ฉด ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์บ์‹œ ์ •์ฑ…์„ ๊ฐ™์ด ์„ ์–ธํ•œ๋‹ค.

// app/lib/stats.ts
import { cacheLife, cacheTag } from 'next/cache'
 
export async function getHeavyMonthlyStats(year: number, month: number) {
  'use cache';
  cacheLife('hours');
  cacheTag(`monthly-stats-${year}-${month}`);
 
  const rawData = await db.query(...);
  const result = heavyCPUCalculate(rawData);
  return result;
}

'use cache'์˜ ์บ์‹œ ํ‚ค์—๋Š” ํ•จ์ˆ˜ ์œ„์น˜, ๋นŒ๋“œ ID, ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•œ ์ธ์ž ๋“ฑ์ด ๋“ค์–ด๊ฐ„๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ™์€ year, month๋กœ ํ˜ธ์ถœํ•  ๋•Œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ด€๋ฆฌ์ž ์ €์žฅ ์•ก์…˜์—์„œ๋Š” ๊ฐ™์€ ํƒœ๊ทธ๋ฅผ updateTag๋‚˜ revalidateTag๋กœ ๊ฐฑ์‹ ํ•ด์•ผ ํ•œ๋‹ค.

[์บ์‹œ์˜ ๋ถ€์ž‘์šฉ (๋ฌดํšจํ™”)]
์ด๊ฑฐ ์‹ฌํ™” 1์žฅ์˜ React.cache() (1์ดˆ ๋‹จ๋ฐœ์„ฑ ์ง€์šฐ๊ฐœ) ๋ž‘ ์ฐฉ๊ฐํ•˜๋ฉด ์•ˆ ๋ผ!
React.cache()๋Š” ๊ฐ™์€ ์š”์ฒญ ์•ˆ์˜ ์ค‘๋ณต ํ˜ธ์ถœ์„ ์ค„์ด๋Š” ๋ฉ”๋ชจ์ด์ œ์ด์…˜์ด๊ณ , 'use cache'๋Š” ์š”์ฒญ์„ ๋„˜์–ด ์žฌ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ์บ์‹œ ์ •์ฑ…์ด์•ผ.
์ฆ‰, ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€์—์„œ ๋งค์ถœ ๊ธฐ์ค€์„ ๊ฐฑ์‹ ํ•œ๋‹ค๋ฉด ์ €์žฅ ์•ก์…˜์—์„œ ๊ฐ™์€ ํƒœ๊ทธ๋ฅผ ๊ฐฑ์‹ ํ•ด์•ผ ์œ ์ €๊ฐ€ ๋‚ก์€ ํ†ต๊ณ„๋ฅผ ์˜ค๋ž˜ ๋ณด์ง€ ์•Š๋Š”๋‹ค.


๐ŸŒฑ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„ ์บ์‹ฑ (Cache Components) ๐ŸŸก

ํ•จ์ˆ˜ ๋ง๊ณ , HTML ํƒœ๊ทธ๋ฅผ ๋ฟœ์–ด๋‚ด๋Š” '๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ(export default function...)' ์ž์ฒด๋„ ํ†ต์งธ๋กœ ์–ผ๋ ค๋ฒ„๋ฆด ์ˆ˜ ์žˆ์–ด!

์ƒํ™ฉ: DB์—์„œ ๊ฐ€์ ธ์˜จ 1๋งŒ ๊ฐœ ๋ชฉ๋ก ๊ทธ๋ฆฌ๊ธฐ

// app/components/MegaList.tsx
 
// ๐ŸงŠ ์ด ์ปดํฌ๋„ŒํŠธ ๋ฉ์–ด๋ฆฌ๊ฐ€ ๋ฟœ์–ด๋‚ด๋Š” "HTML ๊ตฌ์กฐ" ๊ฒฐ๊ณผ๋ฌผ ์ž์ฒด๋ฅผ ํ†ต์งธ๋กœ ์–ผ๋ ค๋ฒ„๋ฆฐ๋‹ค!
export default async function MegaList({ categoryId }: { categoryId: string }) {
  'use cache';
 
  // 1๋งŒ ๊ฐœ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์ˆ˜๋งŒ ๊ฐœ์˜ <li> ํƒœ๊ทธ๋กœ ์กฐ๋ฆฝํ•˜๋Š” ๊ฑฐ๋Œ€ํ•œ CPU ์—ฐ์‚ฐ
  const data = await db.getItems(categoryId);
 
  return (
    <ul>
      {data.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  )
}

์ด์ œ page.tsx ๋“ฑ ์•„๋ฌด ๊ณณ์—์„œ๋‚˜ ์ € <MegaList /> ๋ฅผ ์ˆ˜๋ฐฑ ๋ฒˆ ๋ Œ๋”๋งํ•˜๋„๋ก ํ˜ธ์ถœํ•ด๋ด๋„, ์„œ๋ฒ„๋Š” HTML ํƒœ๊ทธ ๋ฌธ์ž์—ด ์กฐ๋ฆฝ์„ ์•„์˜ˆ ์ƒ๋žตํ•˜๊ณ  ๋””์Šคํฌ ์–ด๋”˜๊ฐ€ ์บ์‹œ ์ฐฝ๊ณ ์—์„œ ๊บผ๋‚ธ ์™„์„ฑํ’ˆ ํ…์ŠคํŠธ ๋ฉ์–ด๋ฆฌ๋ฅผ 0.01์ดˆ ๋งŒ์— ๋ธŒ๋ผ์šฐ์ €์— ๋ฐฐ๋‹ฌํ•ด์ค˜.
ํ”„๋ก ํŠธ ์„œ๋ฒ„ ์š”๊ธˆ์„ ํš๊ธฐ์ ์œผ๋กœ ๋‚ฎ์ถ”๋Š” 2026 ํŠธ๋ Œ๋“œ์˜ ํ•ต์‹ฌ ๊ธฐ๋ฒ•์ด์ง€.


๐Ÿ›ก๏ธ PPR (Partial Pre-Rendering): ์ •์  ๊ป๋ฐ๊ธฐ + ๋™์  ์†์‚ด ๐Ÿ”ด

์ž, ์ด์ œ ๊ถ๊ทน์˜ ํ€˜์ŠคํŠธ. "Next.js ๋ Œ๋”๋ง ์ตœ์ •์ ์˜ ๊ธฐ์ˆ "๋กœ ๋„˜์–ด๊ฐ€์ž.

๋ชจ์ˆœ๋˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ

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

์‹ฌํ™” 1์žฅ์—์„œ ๋ฐฐ์› ์ง€? "๋‹จ ํ•œ ์ค„์˜ ์‹ค์‹œ๊ฐ„ ์ฟ ํ‚ค๋ผ๋„ ์ฝ์œผ๋ฉด ๊ทธ ํŽ˜์ด์ง€์˜ ํ™”์„(Static)์€ ์˜์›ํžˆ ํ›ผ์†๋˜๊ณ  ์ „์ฒด๊ฐ€ SSR(Dynamic)๋กœ ๊ฐ•๋“ฑ๋œ๋‹ค" ๊ณ !

โœ… PPR (๋ถ€๋ถ„ ์‚ฌ์ „ ๋ Œ๋”๋ง) ์ด๋ผ๋Š” ์ด๋‹จ์•„

Vercel ์ฒœ์žฌ๋“ค์ด ์ด๊ฑธ ๊ทน๋ณตํ•ด๋ƒˆ์–ด!
์šฐ๋ฆฌ๊ฐ€ ๊ฐ€์ด๋“œ 7์žฅ์—์„œ ๋ฐฐ์šด <Suspense> ๊ตฌ๋ฉ ๋šซ๊ธฐ ๊ธฐ์ˆ ๊ณผ ๊ฒฐํ•ฉ ๋œ ๊ดด๋ฌผ ์‚ฌ์–‘์ด์•ผ.

// app/page.tsx
// โš ๏ธ ์ด ํŽ˜์ด์ง€ ์•ˆ์— ์‹ค์‹œ๊ฐ„ ์ •๋ณด(์ฟ ํ‚ค ๋“ฑ)๊ฐ€ ์žˆ์ง€๋งŒ ๋‚œ ์ ˆ๋Œ€ ์†๋„ ๊ฐ•๋“ฑ์„ ๋‹นํ•˜์ง€ ์•Š์„ ํ…Œ๋‹ค!
 
import { Suspense } from 'react'
import { cookies } from 'next/headers'
import StaticHeader from './StaticHeader'
 
// 1. ์—ฌ๊ธฐ์„œ ๋™์  (๋งค ์ ‘์†๋งˆ๋‹ค ๋‹ฌ๋ผ์ง€๋Š” ๊ฐœ์ธํ™”) ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋ฉ์–ด๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•œ๋‹ค!
async function PersonalCart() {
  const token = (await cookies()).get('token'); // ๐Ÿ’ฃ ์›๋ž˜๋ผ๋ฉด ์ „์ฒด ๋ผ์šฐํŠธ๋ฅผ ๋™์ ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์š”์ฒญ ์‹œ์  API!!
  const cartInfo = await fetchCart(token);
  return <div>๋‚ด ์žฅ๋ฐ”๊ตฌ๋‹ˆ: {cartInfo.count}๊ฐœ</div>
}
 
 
// 2. ์ „์ฒด ์กฐํ•ฉํ•˜๋Š” ๋ฉ”์ธ ์ปดํฌ๋„ŒํŠธ ๋ ˆ์ด์•„์›ƒ
export default function HomePage() {
  return (
    <main>
      {/* ๐ŸŒŸ ์—ฌ๊ธฐ๋Š” ๋นŒ๋“œ ํƒ€์ž„์— ํ‰์ƒ ๋ณด์กด๋˜๋Š” ํ™”์„(Static)์œผ๋กœ ๊นก๊นก ์–ผ์–ด์„œ 0.1์ดˆ ๋งŒ์— ์„œ๋น™๋จ! */}
      <StaticHeader />
 
      {/* ๐ŸŒŸ ๋™์  ๊ตฌ์—ญ์„ Suspense ์บก์А๋กœ ๊ฒฉ๋ฆฌํ•ด ๊ฐ€๋‘ฌ๋ฒ„๋ ธ๋‹ค! */}
      <Suspense fallback={<div>์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋กœ๋”ฉ์ค‘...</div>}>
        <PersonalCart />
      </Suspense>
 
      {/* ๐ŸŒŸ ์—ฌ๊ธฐ๋„ Static! */}
      <Footer />
    </main>
  )
}

[๋งˆ๋ฒ•์˜ ์ž‘๋™ ์›๋ฆฌ (PPR ์บ์‹ฑ ๊ฒฐํ•ฉ)]

  1. ๋นŒ๋“œ ๋ช…๋ น(next build) ์‹œ, ๋„ฅ์ŠคํŠธ ๋ด‡์ด ํŠธ๋ฆฌ๋ฅผ ์ˆœํšŒํ•˜๋‹ค๊ฐ€ Suspense ์บก์А์„ ๋งŒ๋‚˜๋ฉด "์•„ํ•˜! ์ด ๊ตฌ๋ฉ(Hole) ์•ˆ์ชฝ์€ ๋™์  ๊ตฌ์—ญ๋‹ˆ๊นŒ ๋‚ด๊ฐ€ ๊ฑด๋“œ๋ฆฌ๋ฉด ์•ˆ ๋˜๊ฒ ๊ตฐ. ๋Œ€์‹  ์บก์А ๋ฐ”๊นฅ์˜ ๊ป๋ฐ๊ธฐ ๋ ˆ์ด์•„์›ƒ๋“ค์€ ๋ชจ์กฐ๋ฆฌ ์ •์  ํ™”์„ ์Šค์ผˆ๋ ˆํ†ค(Static)์œผ๋กœ ์ž”๋œฉ ๊ตฌ์›Œ๋‘์ž!" ํ•˜๊ณ  ๋ถ€๋ถ„ ํ™”์„์„ ๋งŒ๋“ค์–ด๋‚ด.
  2. ์œ ์ €๊ฐ€ ์ ‘์†ํ•˜๋ฉด? ๊ฐ€์šด๋ฐ ๋™์  ๊ตฌ์—ญ์€ fallback์œผ๋กœ ๋‚จ๊ฒจ๋‘” ์ฑ„ ์ •์  ์…ธ(GNB + Footer + ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋กœ๋”ฉ์ค‘ ๊ธ€์”จ)์ด ๋น ๋ฅธ TTFB๋กœ ๋จผ์ € ์ „๋‹ฌ๋œ๋‹ค.
  3. ๊ทธ์™€ ๋™์‹œ์— ์บก์А ์•ˆ์ชฝ์˜ ์‚ด์‚ด ๋…น๋Š” ๋™์  ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋’ค๋Šฆ๊ฒŒ ์ฟ ํ‚ค๋ฅผ ๊นŒ๋ณด๊ณ  ์„œ๋ฒ„ ์—ฐ์‚ฐ์„ ๋งˆ์นœ ๋’ค ๊ทธ ๋นˆ ๊ตฌ๋ฉ์„ ์ฑ„์šฐ๋Ÿฌ Stream ์ „์†ก๋œ๋‹ค.

์ด๊ฒƒ์ด Next.js๊ฐ€ ๋ฐ€์–ด๋ถ™์ด๋Š” ๊ถ๊ทน์˜ ์•„ํ‚คํ…์ฒ˜, ๊ป๋ฐ๊ธฐ๋Š” ํ™”์„์œผ๋กœ! ์†์‚ด์€ ๋ฌดํ•œํ•œ ๋™์  ๋ฐ์ดํ„ฐ๋กœ! "Partial Pre-Rendering(PPR)" ์˜ ์‹ค์ฒด์•ผ.


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

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

โŒ 'use cache'๋ฅผ ๋ถ™์˜€๋Š”๋ฐ ์บ์‹œ๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์Œ

์›์ธ: next.config.ts์— cacheComponents: true๊ฐ€ ์—†๊ฑฐ๋‚˜, ์บ์‹œ ํ•จ์ˆ˜์˜ ์ธ์ž๊ฐ€ ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์—†๋Š” ๊ฐ’(Class ์ธ์Šคํ„ด์Šค, ํ•จ์ˆ˜, Symbol ๋“ฑ)์„ ํฌํ•จํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.
ํ•ด๊ฒฐ์ฑ…: ์„ค์ •์„ ๋จผ์ € ํ™•์ธํ•˜๊ณ , ์บ์‹œ ์Šค์ฝ”ํ”„์—๋Š” ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•œ ์ธ์ž๋งŒ ๋„˜๊ธด๋‹ค. ์š”์ฒญ ์‹œ์  ๊ฐ’(cookies, headers)์ด ํ•„์š”ํ•˜๋‹ค๋ฉด ์บ์‹œ ๋ฐ–์—์„œ ์ฝ์–ด ์ธ์ž๋กœ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜, ์ •๋ง ์‚ฌ์šฉ์ž๋ณ„ ์บ์‹œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ณ„๋„ ์ง€์‹œ์–ด๋ฅผ ๊ฒ€ํ† ํ•œ๋‹ค.

โŒ Suspense ์บก์А์„ ์ž˜ ์”Œ์› ๋Š”๋ฐ ๋นŒ๋“œํ•ด๋ณด๋ฉด ์ž๊พธ ์†์‚ด๊นŒ์ง€ ๋‹ค ๊นŒ๋ฐœ๋ ค์ง„ ์ฑ„ ์ „์ฒด ํŽ˜์ด์ง€๊ฐ€ Dynamic์œผ๋กœ ๊ฐ•๋“ฑ๋‹นํ•ด๋ฒ„๋ ค์š” ใ… ใ… 

์›์ธ: ์•„์ฃผ ํ”ํ•œ ์‹ค์ˆ˜.
์œ„ํ—˜ํ•œ ์ฝ”๋“œ(const t = cookies().get())๋ฅผ ์บก์А์˜ ๋ฐ”๊นฅ(๋ถ€๋ชจ)์ธ page.tsx ๋‚ด๋ถ€ ์Šค์ฝ”ํ”„์— ๋ฉ๊ทธ๋Ÿฌ๋‹ˆ ์„ ์–ธํ•ด ๋‘๊ณ , ๊ทธ๊ฑธ ์†์‚ด ์ปดํฌ๋„ŒํŠธ์˜ Props๋กœ ๋‚ด๋ ค๋ณด๋‚ด๋Š” ์šฐ๋ฅผ ๋ฒ”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ.
๋ถ€๋ชจ๊ฐ€ ์š”์ฒญ ์‹œ์  API์— ๋…ธ์ถœ๋œ ์ˆœ๊ฐ„ ๋ถ€๋ชจ์˜ ๊ป๋ฐ๊ธฐ๋„ ํ•จ๊ป˜ ์˜ค์—ผ๋˜์–ด ์˜์›ํžˆ ํ™”์„ ๊ธฐ๋Šฅ์„ ์ƒ์‹คํ•œ๋‹ค.
ํ•ด๊ฒฐ์ฑ…: ๋ฌด์กฐ๊ฑด ์†์‚ด ์ปดํฌ๋„ŒํŠธ ์Šค์ฝ”ํ”„ ๋‚ด๋ถ€ ์•ˆ์ชฝ์œผ๋กœ cookies()๋‚˜ ๋ฆฌํ€˜์ŠคํŠธ ํ—ค๋” ์ฝ๊ธฐ ๋ช…๋ น๋ฌธ์„ ํ†ต์งธ๋กœ ๊ฒฉ๋ฆฌ/์ด์ „์‹œ์ผœ์•ผ PPR์ด ๋™์  ๊ตฌ์—ญ์„ ์ œ๋Œ€๋กœ ๋ถ„๋ฆฌํ•œ๋‹ค.


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

๊ธฐ์ˆ  ๋„๊ตฌํšจ๊ณผ์žฅ๋‹จ์  ๋ฐ ์‚ฌ์šฉ์ฒ˜
'use cache'๋А๋ฆฐ API๋‚˜ ๋ฌด๊ฑฐ์šด ํ•จ์ˆ˜, ์ปดํฌ๋„ŒํŠธ UI ๊ฒฐ๊ณผ๋ฅผ ์žฌ์‚ฌ์šฉํ•œ๋‹คcacheComponents: true, cacheLife, cacheTag์™€ ํ•จ๊ป˜ ์„ค๊ณ„ํ•ด์•ผ ํ•จ
Suspense ์บก์Аํ™” (PPR)๋ Œ๋”๋ง ํ™”์„ ํŒ์ •๊ธฐ์—์„œ "์—ฌ๊ธฐ๋งŒ ๊ตฌ๋ฉ ๋šซ์–ด์ฃผ์‡ผ" ์‹œ์ „. (์ฒด๊ฐ์†๋„ ๋น›)๊ฒ‰๋ฐ”์†์ด‰ ๋ Œ๋”๋ง. ํŽ˜์ด์ง€ ํ•˜๋‚˜์— ์ •์  ์บ์‹œ์™€ ๋™์  ํ†ต์‹ ์ด ์ถค์„ ์ถ”๋Š” Next.js ๊ถ๊ทน์˜ ๋ชจ๋ฒ” ์•„ํ‚คํ…์ฒ˜
React.cache (๋ณต์Šต)์ด๋ฒˆ ํ•œ ๋ฒˆ ๋ฐฉ๋ฌธ ๋™์•ˆ ๋˜‘๊ฐ™์€ ํ˜ธ์ถœ ๋ฐฉ์–ด (์บ์‹œ ์ฐฝ๊ณ  ์ €์žฅ X)1์ดˆ์‚ด. Props Drilling ๋ฐฉ์–ด์šฉ

๐Ÿ’ก ์‹œ๋‹ˆ์–ด์˜ ๋ฉ˜ํƒˆ ๋ชจ๋ธ
14๋ฒ„์ „๊นŒ์ง€๋Š” fetch ์— ๋‹ฌ๋ฆฐ ํŒŒ๋ผ๋ฏธํ„ฐ ์˜ต์…˜์— ๋ชฉ์„ ๋งธ๋‹ค๋ฉด, 15๋ฒ„์ „๋ถ€ํ„ฐ๋Š” ํ•จ์ˆ˜ ๋ฌถ์Œ์ด๋‚˜ UI ์กฐ๊ฐ ๋ฉ์–ด๋ฆฌ ์ž์ฒด๋ฅผ ํ•€์…‹์œผ๋กœ ์ง‘์–ด ์–ผ๋ ค๋ฒ„๋ฆฌ๋Š” ์šฐ์•„ํ•œ ์‹œ๋Œ€์— ์ง„์ž…ํ–ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์–ด๋”” ๋ถ€๋ถ„๊นŒ์ง€ ์ •์ ์ธ์ง€ ์บก์А ๊ตฌ๋ฉ ๋šซ๊ธฐ(Suspense)๋งŒ ์ž˜ํ•ด๋„ ๋‹น์‹ ์€ ์‹ ์˜ ๊ฒฝ์ง€!


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

Q1. 'use cache'๋ฅผ ํ•จ์ˆ˜ ์•ˆ์— ๋ถ™์˜€์„ ๋•Œ ์บ์‹œ ํ‚ค๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ํ•ต์‹ฌ ์ž…๋ ฅ์€ ๋ฌด์—‡์ธ๊ฐ€?

โœ… ์ •๋‹ต: ํ•จ์ˆ˜์˜ ์ธ์ž์™€ ์บ์‹œ ๊ฐ€๋Šฅํ•œ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: 'use cache'๋Š” "์ด ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ ์žฌ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค"๊ณ  ์„ ์–ธํ•˜๋Š” ๋””๋ ‰ํ‹ฐ๋ธŒ๋‹ค. ๊ฐ™์€ ์ธ์ž๋กœ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ์•ˆ์ „ํ•˜๋‹ค. ์š”์ฒญ๋งˆ๋‹ค ๋‹ฌ๋ผ์ง€๋Š” cookies(), headers() ๊ฐ™์€ ๊ฐ’์— ๊ธฐ๋Œ€๋Š” ๋กœ์ง์€ ์บ์‹œ ๋ฒ”์œ„์— ๋„ฃ์œผ๋ฉด ์•ˆ ๋œ๋‹ค. ์˜ํ˜ธ๊ฐ€ ๋ณด๋Š” ๊ธฐ์ค€์€ ์ˆœ์ˆ˜์„ฑ์ด๋‹ค. ์ž…๋ ฅ์ด ๊ฐ™์œผ๋ฉด ๊ฒฐ๊ณผ๋„ ๊ฐ™๋‹ค๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.


Q2. ์˜์ˆ™์ด ์›”๊ฐ„ ์ถ”์ฒœ ์ƒํ’ˆ์„ ์–ด๋“œ๋ฏผ์—์„œ ๋ฐ”๊ฟจ๋‹ค. 'use cache'๋กœ ์บ์‹œํ•œ getMonthlyPicks()๊ฐ€ ์žˆ๋‹ค๋ฉด ์–ด๋–ค ๋ณด๊ฐ•์ด ํ•„์š”ํ• ๊นŒ?

โœ… ์ •๋‹ต: cacheTag('monthly-picks')์ฒ˜๋Ÿผ ํƒœ๊ทธ๋ฅผ ๋ถ™์ด๊ณ , ์ €์žฅ ์•ก์…˜์—์„œ revalidateTag ๋˜๋Š” ์ฆ‰์‹œ ์ผ๊ด€์„ฑ์ด ํ•„์š”ํ•˜๋ฉด updateTag๋กœ ๊ฐฑ์‹ ํ•œ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: ์บ์‹œ๋Š” ๋งŒ๋“œ๋Š” ์ˆœ๊ฐ„๋ณด๋‹ค ๊นจ๋Š” ์ˆœ๊ฐ„์ด ๋” ์ค‘์š”ํ•˜๋‹ค. ์ตœ์‹  ๊ณต์‹ ๋ฌธ์„œ ๊ธฐ์ค€์œผ๋กœ Cache Components์—์„œ๋Š” cacheLife๋กœ ์‹œ๊ฐ„ ์ •์ฑ…์„, cacheTag๋กœ ์˜จ๋””๋งจ๋“œ ๊ฐฑ์‹  ๋Œ€์ƒ์„ ์„ ์–ธํ•œ๋‹ค. revalidateTag๋Š” stale-while-revalidate ์„ฑ๊ฒฉ์œผ๋กœ ๋ฐฐ๊ฒฝ ๊ฐฑ์‹ ์— ์ ํ•ฉํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ๋ฐฉ๊ธˆ ์“ด ๊ฒฐ๊ณผ๋ฅผ ์ฆ‰์‹œ ๋ด์•ผ ํ•˜๋Š” read-your-own-writes ์ƒํ™ฉ์€ updateTag๊ฐ€ ๋” ๋งž๋‹ค.


Q3. ์˜์ฒ ์ด์˜ ํ…Œ์ŠคํŠธ ํƒ€์ž„: ๋Œ€์‹œ๋ณด๋“œ ์ƒ๋‹จ ์„ค๋ช…, ์ธ๊ธฐ ๊ธ€ ๋ชฉ๋ก, ๋‚ด ์•Œ๋ฆผ ์นด์šดํŠธ๋ฅผ ํ•œ ํŽ˜์ด์ง€์— ๋ฐฐ์น˜ํ•œ๋‹ค. 'use cache'๋ฅผ ์–ด๋””์— ์ ์šฉํ•ด์•ผ ํ• ๊นŒ?

โœ… ์ •๋‹ต: ์„ค๋ช…๊ณผ ์ธ๊ธฐ ๊ธ€์ฒ˜๋Ÿผ ์‚ฌ์šฉ์ž์™€ ๋ฌด๊ด€ํ•˜๊ณ  ์ผ์ • ์‹œ๊ฐ„ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„์—๋งŒ ์ ์šฉํ•œ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: ๋‚ด ์•Œ๋ฆผ ์นด์šดํŠธ๋Š” ์„ธ์…˜๊ณผ ์‹ค์‹œ๊ฐ„์„ฑ์— ๋ฌถ์—ฌ ์žˆ์œผ๋ฏ€๋กœ ์บ์‹œํ•˜๋ฉด ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์˜ ๊ฐ’์ด ์„ž์ด๊ฑฐ๋‚˜ ๋‚ก์€ ์ˆซ์ž๊ฐ€ ๋ณด์ผ ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ ๋งˆ์ผ€ํŒ… ์„ค๋ช… ๋ฌธ๊ตฌ๋‚˜ ์ธ๊ธฐ ๊ธ€ ๋ชฉ๋ก์€ cacheLife('hours') ๊ฐ™์€ ์ •์ฑ…๊ณผ ํƒœ๊ทธ ๊ฐฑ์‹ ์„ ๋ถ™์ด๋ฉด ๋น„์šฉ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค. PPR๊ณผ ํ•จ๊ป˜ ์“ธ ๋•Œ๋„ ์ •์  ์…ธ๊ณผ ๋™์  ๊ตฌ๋ฉ์˜ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒŒ ํ•ต์‹ฌ์ด๋‹ค.

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

์˜ค๋Š˜์€ 'use cache'๋ฅผ "๋น ๋ฅด๊ฒŒ ํ•ด์ฃผ๋Š” ์ฃผ๋ฌธ"์ด ์•„๋‹ˆ๋ผ "์žฌ์‚ฌ์šฉํ•ด๋„ ๋˜๋Š” ์•ฝ์†"์œผ๋กœ ๋‹ค์‹œ ๋ฐฐ์› ๋‹ค. ์บ์‹œ๋ฅผ ํ•จ์ˆ˜๋‚˜ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑด ํŽธํ•˜์ง€๋งŒ, ๊ทธ๋งŒํผ ๋‚ด๊ฐ€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ ์ •์‹œํ‚ค๋Š”์ง€ ๋” ๋ถ„๋ช…ํžˆ ์•Œ์•„์•ผ ํ–ˆ๋‹ค.

๐Ÿ’ก "์บ์‹œ ๊ฐ€๋Šฅํ•œ ์กฐ๊ฐ์€ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์—์„œ ๋…๋ฆฝ์ ์ด๊ณ , ๊ฐฑ์‹  ์ด๋ฒคํŠธ๋ฅผ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค."

๋‹ค์Œ ์ฝ”๋“œ ๋ฆฌ๋ทฐ์—์„œ๋Š” 'use cache'๊ฐ€ ๋ณด์ด๋ฉด ์„ธ ๊ฐ€์ง€๋ฅผ ํ™•์ธํ•˜๊ฒ ๋‹ค. ์š”์ฒญ ์‹œ์  API๋ฅผ ์ฝ๋Š”์ง€, cacheLife๊ฐ€ ์‹ค์ œ ์‹ ์„ ๋„ ์š”๊ตฌ์™€ ๋งž๋Š”์ง€, ๊ด€๋ฆฌ์ž ์ €์žฅ์ด๋‚˜ ์„œ๋ฒ„ ์•ก์…˜์—์„œ ํƒœ๊ทธ ๊ฐฑ์‹ ์ด ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€. ์ด์ œ ์„ฑ๋Šฅ์„ ์˜ฌ๋ฆฌ๋Š” ์ œ์•ˆ๋„ ์šด์˜์ž๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๊พธ๋Š” ์ˆœ๊ฐ„๊นŒ์ง€ ํฌํ•จํ•ด์„œ ๋งํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

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