[NextJs] NextJs가 말아주는 캐시(Data-level cache)

개잼·2026년 4월 23일

1. 인사

안녕하세요. 오늘은 NextJs의 2026 캐싱에 대해 글을 작성하려고 합니다.


2. 기본 설정

먼저, 가장 최근에 업데이트된 NextJs의 cache를 사용하려면 다음과 같은 내용을 설정해줘야 합니다.

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

3. use cache

최근에는 use cache라는 지시문이 업데이트 되었습니다. 물론 실험적인 기능으로 보이지만, 안정화가 되면 바로 사용할 수 있을 것 같습니다.

use cache는 두 가지 수준에서 적용할 수 있습니다.

a. Data-level

Server action이나 Route API를 통해 Fetch를 한 데이터를 캐싱하는 것
(ex getProducts(), getUser(id))

b. UI-level

Component 전체를 cache할 수도 있습니다.


4. Data-level cache

데이터를 가져오는 비동기 함수를 캐시하기 위해 use cache 함수를 함수 내부의 가장 상단에 작성합니다.

// app/lib/data.ts
import { cacheLife } from 'next/cache'
 
export async function getUsers() {
  'use cache'
  cacheLife('hours')
  return db.query('SELECT * FROM users')
}

Data-level cache는 동일한 데이터가 여러 구성 요소에서 사용되거나 UI와 별도로 데이터를 캐시하려는 경우 유용합니다.

5. Data-level cache 심화

export async function getCollectionProducts({
  collection,
  reverse,
  sortKey,
}: {
  collection: string;
  reverse?: boolean;
  sortKey?: string;
}): Promise<Product[]> {
  "use cache";
  cacheTag(TAGS.collections, TAGS.products);
  cacheLife("days");

  if (!endpoint) {
    console.log(
      `Skipping getCollectionProducts for '${collection}' - Shopify not configured`
    );
    return [];
  }

  const res = await shopifyFetch<ShopifyCollectionProductsOperation>({
    query: getCollectionProductsQuery,
    variables: {
      handle: collection,
      reverse,
      sortKey: sortKey === "CREATED_AT" ? "CREATED" : sortKey,
    },
  });

  if (!res.body.data.collection) {
    console.log(`No collection found for \`${collection}\``);
    return [];
  }

  return reshapeProducts(
    removeEdgesAndNodes(res.body.data.collection.products)
  );
}

해당 코드는 Vercel에서 공식 Repository로 올린 commerce code의 일부분 입니다. 즉, Vercel에서 사용하는 방식이라고 보시면 됩니다.

중요한 것은 cacheTag와 cacheLife입니다.

6. cacheLife

캐시의 수명을 정의할 수 있게함

단, use cache 지시어가 있는 곳에서만 사용 가능.

6.1 주요 속성

  • stale
    클라이언트 브라우저가 서버에 확인하지 않고 캐시된 데이터를 사용할 수 있는 기간.
  • revalidate
    서버에서 캐시를 백그라운드에서 갱신(Revalidation)하기 시작하는 주기
  • expire
    캐시가 완전히 만료되는 시점. 이 시간이 지나면 다음 요청은 반드시 새 데이터를 가져와야 함.

6.2 사용법

특정 함수나 컴포넌트 내부에서 바로 시간을 지정할 수 있음.
(단, use cache 지시어가 반드시 필요.)

import { unstable_cacheLife as cacheLife } from 'next/cache';

async function getStockPrice() {
  'use cache';
  // 1분(60초) 후 재검증, 5분(300초) 후 만료
  cacheLife({ revalidate: 60, expire: 300 }); 
  
  const res = await fetch('https://api.example.com/stock');
  return res.json();
}

혹은 NextJs가 제공하는 문자열을 사용함.
ex) 'seconds', 'minutes', 'hours', 'days', 'weeks' 등
async function getNews() {
  'use cache';
  cacheLife('hours'); // 미리 정의된 'hours' 프로필 사용 (약 1시간 주기)
  // ...데이터 fetching
}

7. cacheTag

특정 데이터에 태그를 붙여두고, 나중에 해당 태그가 붙은 데이터만 골라서 최신 상태로 업데이트

cacheTag 함수는 하나 이상의 문자열 값을 입력으로 받습니다.

import { cacheTag } from 'next/cache'
 
export async function getData() {
  'use cache'
  cacheTag('my-data')
  const data = await fetch('/api/data')
  return data
}

만약 이전에 지정한 my-data에 대한 cache를 무효화 하고 싶다면,

'use server'
 
import { revalidateTag } from 'next/cache'
 
export default async function submit() {
  await addPost()
  revalidateTag('my-data')
}

에서 처럼 revalidateTag를 활용하여 캐시를 삭제할 수 있습니다.


8. 마무리

이렇게 오늘은 NextJs가 말아주는 캐싱에 대해 알아봤는데요, 갑자기 왜 이런 글을 쓰게 되었냐면 제가 오픈소스를 공부하다가 재밌어 보여서 이것을 글로 정리하면 좋을 것 같아 글로 작성해보았습니다.

여러분들도 이 글을 읽고 NextJs를 사용하시면서 캐싱을 맛있게 잘 사용하셨으면 좋겠습니다.
Tanstack query쓸거 알지만서도요

profile
천천히 나아가는 중

0개의 댓글