캐싱 메커니즘으로 이해하는 Next.js 성능 최적화 가이드

Eddy·2024년 6월 3일
2

Next.js

목록 보기
4/13

이 글은 Next.js 문서 중 캐싱(Caching)에 관한 내용을 번역한 것으로, 참고용으로만 사용하시길 바랍니다. 실제 문서를 꼼꼼히 읽어보는 것을 권장드립니다.


Next.js는 렌더링 작업과 데이터 요청을 캐싱하여 애플리케이션의 성능을 향상시키고 비용을 절감합니다. 이 페이지에서는 Next.js 캐싱 메커니즘, 이를 구성할 수 있는 API 및 상호 작용 방식을 자세히 설명합니다.

참고: 이 페이지는 Next.js의 내부 동작 방식을 이해하는 데 도움이 되지만, Next.js를 생산적으로 사용하는 데 필수적인 지식은 아닙니다. 대부분의 Next.js 캐싱 휴리스틱은 API 사용에 따라 결정되며, 최소한의 구성으로 최고의 성능을 제공합니다.

개요

다음은 다양한 캐싱 메커니즘과 그 목적에 대한 개요입니다:
기본적으로 Next.js는 성능을 향상시키고 비용을 절감하기 위해 가능한 한 많은 것을 캐시합니다. 이는 경로가 정적으로 렌더링되고 데이터 요청이 캐시된다는 것을 의미하며, 사용자가 이를 옵트아웃하지 않는 한 그렇습니다. 아래 다이어그램은 빌드 시점과 정적 경로가 처음 방문되었을 때의 기본 캐싱 동작을 보여줍니다.
캐싱 동작은 경로가 정적으로 렌더링되는지 동적으로 렌더링되는지, 데이터가 캐시되는지 캐시되지 않는지, 요청이 초기 방문의 일부인지 후속 탐색의 일부인지에 따라 달라집니다. 사용 사례에 따라 개별 경로 및 데이터 요청에 대한 캐싱 동작을 구성할 수 있습니다.


요청 메모화

React는 동일한 URL과 옵션을 가진 요청을 자동으로 메모화하도록 fetch API를 확장합니다. 이는 React 컴포넌트 트리의 여러 위치에서 동일한 데이터를 요청해도 한 번만 실행됨을 의미합니다.
예를 들어, 경로 전체에서 동일한 데이터를 사용해야 하는 경우(예: 레이아웃, 페이지 및 여러 구성 요소에서) 트리의 최상위에서 데이터를 가져오고 구성 요소 간에 props를 전달할 필요가 없습니다. 대신, 동일한 데이터를 네트워크를 통해 여러 번 요청하는 것에 대한 성능 영향을 걱정하지 않고 데이터를 필요로 하는 구성 요소에서 데이터를 가져올 수 있습니다.

async function getItem() {
  // The `fetch` function is automatically memoized and the result
  // is cached
  const res = await fetch('https://.../item/1')
  return res.json()
}
 
// This function is called twice, but only executed the first time
const item = await getItem() // cache MISS
 
// The second call could be anywhere in your route
const item = await getItem() // cache HIT

How Request Memoization Works


1. 경로를 렌더링할 때, 특정 요청이 처음 호출될 때 그 결과는 메모리에 없으며 캐시 미스가 발생합니다.
2. 따라서 함수가 실행되고, 외부 소스에서 데이터를 가져와서 결과를 메모리에 저장합니다.
3. 같은 렌더링 패스에서 동일한 요청의 후속 함수 호출은 캐시 히트를 발생시키며, 함수가 실행되지 않고 메모리에서 데이터를 반환합니다.
4.경로가 렌더링되고 렌더링 패스가 완료되면 메모리가 "재설정"되고 모든 요청 메모화 항목이 지워집니다.

참고:

  • 요청 메모화는 React 기능이지 Next.js 기능이 아닙니다. 다른 캐싱 메커니즘과 상호 작용하는 방식을 보여주기 위해 여기에 포함되었습니다.
  • 메모화는 fetch 요청의 GET 메서드에만 적용됩니다.
  • 메모화는 React 구성 요소 트리에만 적용됩니다. 이는 다음을 의미합니다:
    • generateMetadata, generateStaticParams, 레이아웃, 페이지 및 기타 서버 구성 요소의 fetch 요청에 적용됩니다.
    • Route Handlers의 fetch 요청에는 적용되지 않습니다. 이는 React 구성 요소 트리의 일부가 아니기 때문입니다.
  • fetch가 적합하지 않은 경우(예: 일부 데이터베이스 클라이언트, CMS 클라이언트 또는 GraphQL 클라이언트)에는 React cache 함수를 사용하여 함수를 메모화할 수 있습니다.

지속 시간

캐시는 서버 요청의 수명 동안 유지되며, React 컴포넌트 트리가 렌더링될 때까지 지속됩니다.

재검증

메모화는 서버 요청 간에 공유되지 않으며 렌더링 중에만 적용되기 때문에 재검증이 필요하지 않습니다.

옵트 아웃

메모화는 fetch 요청의 GET 메소드에만 적용되며, POST 및 DELETE와 같은 다른 메소드에는 적용되지 않습니다. 이 기본 동작은 React 최적화이며, 옵트 아웃을 권장하지 않습니다.


데이터 캐시

Next.js에는 데이터 캐시가 내장되어 있어 서버 요청 및 배포 간에 데이터 가져오기 결과를 유지합니다. 이는 Next.js가 기본 fetch API를 확장하여 서버에서 각 요청이 고유한 지속 캐싱 의미론을 설정할 수 있게 합니다.

참고:
브라우저에서는 fetch의 캐시 옵션이 브라우저의 HTTP 캐시와 상호 작용하는 방식을 나타내는 반면, Next.js에서는 서버 측 요청이 서버의 데이터 캐시와 상호 작용하는 방식을 나타냅니다.
기본적으로 fetch를 사용하는 데이터 요청은 캐시됩니다. fetch의 캐시 및 next.revalidate 옵션을 사용하여 캐싱 동작을 구성할 수 있습니다.

How the Data Cache Works

  1. 렌더링 중에 fetch 요청이 처음 호출되면 Next.js는 데이터 캐시에서 캐시된 응답을 확인합니다.
  2. 캐시된 응답이 발견되면 즉시 반환되고 메모리에 저장됩니다.
  3. 캐시된 응답이 발견되지 않으면 데이터 소스에서 요청이 수행되고 결과가 데이터 캐시에 저장됩니다.
  4. 캐시되지 않은 데이터(예: { cache: 'no-store' })의 경우, 결과는 항상 데이터 소스에서 가져오고 메모리에 저장됩니다.
  5. 데이터가 캐시되었는지 여부와 상관없이 요청은 항상 메모화되어 동일한 데이터에 대한 중복 요청을 방지합니다.

데이터 캐시와 요청 메모화의 차이점

두 가지 캐싱 메커니즘 모두 캐시된 데이터를 재사용하여 성능을 향상시키지만, 데이터 캐시는 들어오는 요청과 배포 간에 지속되며, 메모화는 요청의 수명 동안만 지속됩니다.

메모화를 통해 렌더링 서버에서 데이터 캐시 서버(예: CDN 또는 Edge 네트워크) 또는 데이터 소스(예: 데이터베이스 또는 CMS)로의 네트워크 경계를 넘어야 하는 중복 요청 수를 줄일 수 있습니다. 데이터 캐시를 통해 원본 데이터 소스로의 요청 수를 줄일 수 있습니다.

지속 시간

데이터 캐시는 들어오는 요청과 배포 간에 지속되며, 재검증하거나 옵트 아웃하지 않는 한 유지됩니다.

재검증

캐시된 데이터는 두 가지 방법으로 재검증할 수 있습니다:

  • 시간 기반 재검증: 일정 시간이 경과한 후 새로운 요청이 있을 때 데이터를 재검증합니다. 이는 데이터가 자주 변경되지 않고 신선도가 중요한 경우에 유용합니다.
  • 온디맨드 재검증: 이벤트(예: 폼 제출)를 기반으로 데이터를 재검증합니다. 태그 기반 또는 경로 기반 접근 방식을 사용하여 데이터 그룹을 한 번에 재검증할 수 있습니다. 이는 콘텐츠가 업데이트될 때 최신 데이터를 가능한 빨리 표시하려는 경우에 유용합니다.

시간 기반 재검증

타임 인터벌에서 데이터를 재검증하려면 fetch의 next.revalidate 옵션을 사용하여 리소스의 캐시 수명을 설정할 수 있습니다(초 단위).

// 최대 1시간마다 재검증
fetch('https://...', { next: { revalidate: 3600 } });

또한 Route Segment Config 옵션을 사용하여 세그먼트 내의 모든 fetch 요청을 구성하거나 fetch를 사용할 수 없는 경우를 처리할 수 있습니다.

시간 기반 재검증 작동 방식

  1. 재검증을 사용하여 fetch 요청이 처음 호출되면 데이터가 외부 데이터 소스에서 가져와지고 데이터 캐시에 저장됩니다.
  2. 지정된 시간 프레임(예: 60초) 내에 호출된 요청은 캐시된 데이터를 반환합니다.
  3. 시간 프레임이 지나면 다음 요청은 여전히 캐시된 (이제는 오래된) 데이터를 반환합니다.
  4. Next.js는 백그라운드에서 데이터를 재검증합니다.
  5. 데이터가 성공적으로 가져오면 Next.js는 데이터 캐시를 신선한 데이터로 업데이트합니다.
  6. 백그라운드 재검증이 실패하면 이전 데이터가 변경되지 않고 유지됩니다.

온디맨드 재검증

데이터는 경로(revalidatePath) 또는 캐시 태그(revalidateTag)로 온디맨드 재검증할 수 있습니다.

온디맨드 재검증 작동 방식

  1. fetch 요청이 처음 호출되면 데이터가 외부 데이터 소스에서 가져와지고 데이터 캐시에 저장됩니다.
  2. 온디맨드 재검증이 트리거되면 관련 캐시 항목이 캐시에서 제거됩니다.
  3. 이는 시간 기반 재검증과 달리, 새 데이터를 가져올 때까지 오래된 데이터를 캐시에 유지하지 않습니다.
  4. 다음 요청 시 캐시 MISS가 발생하며, 데이터는 외부 데이터 소스에서 다시 가져와져 데이터 캐시에 저장됩니다.

옵트 아웃

개별 데이터 요청에 대해 캐싱을 옵트 아웃하려면 cache 옵션을 no-store로 설정합니다. 이렇게 하면 fetch가 호출될 때마다 데이터를 가져옵니다.

// 개별 fetch 요청의 캐시 옵트 아웃
fetch(`https://...`, { cache: 'no-store' });

또는 특정 경로 세그먼트의 캐싱을 옵트 아웃하려면 Route Segment Config 옵션을 사용할 수 있습니다. 이는 경로 세그먼트의 모든 데이터 요청에 영향을 미칩니다.

// 경로 세그먼트의 모든 데이터 요청에 대해 캐시 옵트 아웃
export const dynamic = 'force-dynamic';

참고: 데이터 캐시는 현재 페이지/경로에서만 사용할 수 있습니다. 미들웨어 내부에서 수행된 fetch는 기본적으로 캐시되지 않습니다.


전체 경로 캐시 Full Route Cache

관련 용어:
자동 정적 최적화(Automatic Static Optimization), 정적 사이트 생성(Static Site Generation), 또는 정적 렌더링(Static Rendering)이라는 용어가 애플리케이션의 경로를 빌드 시 렌더링하고 캐싱하는 과정을 가리키기 위해 상호 교환적으로 사용되는 것을 볼 수 있습니다.

Next.js는 빌드 시 경로를 자동으로 렌더링하고 캐싱합니다. 이는 모든 요청마다 서버에서 렌더링하는 대신 캐시된 경로를 제공할 수 있게 해주는 최적화로, 더 빠른 페이지 로드를 가능하게 합니다.

전체 경로 캐시가 어떻게 작동하는지 이해하려면 React가 렌더링을 처리하는 방식과 Next.js가 결과를 캐싱하는 방식을 살펴보는 것이 유용합니다:

1. 서버에서의 React 렌더링

서버에서 Next.js는 React의 API를 사용하여 렌더링을 조정합니다. 렌더링 작업은 개별 경로 세그먼트와 Suspense 경계로 분할됩니다.

각 청크는 두 단계로 렌더링됩니다:

  1. React는 서버 컴포넌트를 스트리밍에 최적화된 특별한 데이터 형식인 React 서버 컴포넌트 페이로드로 렌더링합니다.
  2. Next.js는 React 서버 컴포넌트 페이로드와 클라이언트 컴포넌트 자바스크립트 지침을 사용하여 서버에서 HTML을 렌더링합니다.

2. 서버에서의 Next.js 캐싱 (전체 경로 캐시)

Next.js의 기본 동작은 서버에서 경로의 렌더링 결과(React 서버 컴포넌트 페이로드와 HTML)를 캐싱하는 것입니다. 이는 빌드 시점에 정적으로 렌더링된 경로 또는 재검증 중에 적용됩니다.

3. 클라이언트에서의 React 하이드레이션 및 조정

요청 시 클라이언트에서:

  1. HTML은 클라이언트 및 서버 컴포넌트의 빠른 비상호작용 초기 미리보기를 즉시 보여주기 위해 사용됩니다.
  2. React 서버 컴포넌트 페이로드는 클라이언트 및 렌더링된 서버 컴포넌트 트리를 조정하고 DOM을 업데이트하는 데 사용됩니다.
  3. 자바스크립트 지침은 클라이언트 컴포넌트를 하이드레이션하여 애플리케이션을 상호작용 가능하게 만듭니다.

4. 클라이언트에서의 Next.js 캐싱 (라우터 캐시)

React 서버 컴포넌트 페이로드는 클라이언트 측 라우터 캐시에 저장됩니다. 이 캐시는 개별 경로 세그먼트로 분할되어 사용자 세션 동안 유지됩니다. 이는 이전에 방문한 경로를 저장하고 미래 경로를 프리페치하여 내비게이션 경험을 개선합니다.

5. 후속 내비게이션

후속 내비게이션이나 프리페치 중 Next.js는 React 서버 컴포넌트 페이로드가 라우터 캐시에 저장되어 있는지 확인합니다. 만약 그렇다면, 서버에 새로운 요청을 보내지 않습니다.

경로 세그먼트가 캐시에 없으면, Next.js는 서버에서 React 서버 컴포넌트 페이로드를 가져와 클라이언트의 라우터 캐시에 저장합니다.

정적 및 동적 렌더링

경로가 빌드 시점에 캐시되는지 여부는 정적 렌더링 또는 동적 렌더링 여부에 따라 달라집니다. 정적 경로는 기본적으로 캐시되며, 동적 경로는 요청 시점에 렌더링되어 캐시되지 않습니다.

정적 경로는 빌드 시점 또는 데이터 재검증 후에 캐시되며, 동적 경로는 요청 시점에 캐시되지 않습니다.

지속 시간

기본적으로 전체 경로 캐시는 지속적입니다. 즉, 렌더링 출력은 사용자 요청 간에 캐시됩니다.

무효화

전체 경로 캐시를 무효화하는 방법은 두 가지가 있습니다:

  • 데이터 재검증: 데이터 캐시를 재검증하면 라우터 캐시를 무효화하고 서버에서 컴포넌트를 다시 렌더링하여 새로운 렌더링 출력을 캐시합니다.
  • 재배포: 데이터 캐시는 배포 간에 지속되지만, 전체 경로 캐시는 새로운 배포 시 지워집니다.

옵트 아웃

전체 경로 캐시를 옵트 아웃하거나, 즉, 들어오는 모든 요청에 대해 동적으로 컴포넌트를 렌더링하려면:

  • 동적 함수를 사용: 이는 경로를 전체 경로 캐시에서 옵트 아웃하고 요청 시점에 동적으로 렌더링합니다. 데이터 캐시는 여전히 사용할 수 있습니다.
  • dynamic = 'force-dynamic' 또는 revalidate = 0 경로 세그먼트 구성 옵션을 사용: 이는 전체 경로 캐시와 데이터 캐시를 건너뛰고, 모든 들어오는 요청에 대해 컴포넌트를 렌더링하고 데이터를 가져옵니다. 라우터 캐시는 여전히 적용됩니다.
  • 데이터 캐시의 옵트 아웃: 경로에 캐시되지 않는 fetch 요청이 있으면, 이는 전체 경로 캐시에서 경로를 옵트 아웃합니다. 특정 fetch 요청에 대한 데이터는 모든 들어오는 요청에 대해 가져옵니다. 캐싱을 옵트 아웃하지 않은 다른 fetch 요청의 데이터는 여전히 데이터 캐시에 캐시됩니다. 이는 캐시된 데이터와 캐시되지 않은 데이터를 혼합하여 사용할 수 있게 합니다.

라우터 캐시

Next.js는 사용자 세션 동안 React 서버 컴포넌트 페이로드를 개별 경로 세그먼트로 분할하여 저장하는 클라이언트 측 인메모리 캐시를 가지고 있습니다. 이를 라우터 캐시라고 합니다.

라우터 캐시 작동 방식


사용자가 경로 간을 탐색할 때, Next.js는 방문한 경로 세그먼트를 캐시하고 사용자가 탐색할 가능성이 있는 경로를 프리페치합니다( <Link> 컴포넌트의 뷰포트 내에 있는 경로).

이로 인해 사용자는 다음과 같은 개선된 내비게이션 경험을 할 수 있습니다:

  • 방문한 경로가 캐시되고 프리페치된 경로로 인해 즉시 앞뒤 탐색이 가능합니다.
  • 내비게이션 간 전체 페이지가 새로고침되지 않으며, React 상태와 브라우저 상태가 보존됩니다.

라우터 캐시와 전체 경로 캐시의 차이점:

라우터 캐시는 사용자의 세션 동안 브라우저에서 React 서버 컴포넌트 페이로드를 일시적으로 저장하며, 전체 경로 캐시는 서버에서 여러 사용자 요청 간에 React 서버 컴포넌트 페이로드와 HTML을 지속적으로 저장합니다.

전체 경로 캐시는 정적으로 렌더링된 경로만 캐시하는 반면, 라우터 캐시는 정적 및 동적으로 렌더링된 경로 모두에 적용됩니다.

지속 시간

라우터 캐시는 브라우저의 임시 메모리에 저장됩니다. 두 가지 요소가 라우터 캐시의 지속 시간을 결정합니다:

  • 세션: 캐시는 내비게이션 간에 지속되지만, 페이지 새로고침 시 지워집니다.
  • 자동 무효화 기간: 개별 세그먼트의 캐시는 특정 시간 후 자동으로 무효화됩니다. 지속 시간은 리소스가 프리페치된 방법에 따라 다릅니다:
    • 기본 프리페칭 (prefetch={null} 또는 명시되지 않은 경우): 30초
    • 전체 프리페칭 (prefetch={true} 또는 router.prefetch): 5분

페이지 새로고침은 모든 캐시된 세그먼트를 지우지만, 자동 무효화 기간은 프리페칭된 개별 세그먼트에만 영향을 미칩니다.

옵트 아웃

라우터 캐시에서 옵트 아웃하는 것은 불가능하지만, router.refresh, revalidatePath, 또는 revalidateTag를 호출하여 무효화할 수 있습니다. 이를 통해 캐시가 지워지고 서버에 새로운 요청이 전송되어 최신 데이터를 표시합니다.

또한 <Link> 컴포넌트의 prefetch 속성을 false로 설정하여 프리페칭을 옵트 아웃할 수 있습니다. 그러나 이는 임시로 30초 동안 경로 세그먼트를 저장하여 중첩된 세그먼트 간 빠른 내비게이션을 가능하게 합니다. 방문한 경로는 여전히 캐시됩니다.

무효화

라우터 캐시를 무효화하는 두 가지 방법이 있습니다:

  • 서버 액션에서:

    • 경로(revalidatePath) 또는 캐시 태그(revalidateTag)로 온디맨드 재검증
    • cookies.set 또는 cookies.delete를 사용하여 쿠키를 사용하는 경로가 오래되지 않도록 라우터 캐시를 무효화 (예: 인증 상태 반영).
  • router.refresh를 호출하여 현재 경로에 대한 서버 요청을 새로 고칩니다.

캐시 상호작용

다양한 캐싱 메커니즘을 구성할 때 이들이 서로 어떻게 상호작용하는지 이해하는 것이 중요합니다:

데이터 캐시와 전체 경로 캐시

  • 데이터 캐시를 재검증하거나 옵트 아웃하면, 렌더링 출력이 데이터에 따라 달라지기 때문에 전체 경로 캐시가 무효화됩니다.
  • 전체 경로 캐시를 무효화하거나 옵트 아웃해도 데이터 캐시는 영향을 받지 않습니다. 경로를 동적으로 렌더링하면서도 일부 데이터는 캐시된 상태를 유지할 수 있습니다. 이는 페이지 대부분이 캐시된 데이터를 사용하고 일부 컴포넌트만 요청 시 데이터를 가져와야 하는 경우에 유용합니다.
    데이터 캐시와 클라이언트 측 라우터 캐시
  • 경로 핸들러에서 데이터 캐시를 재검증해도 라우터 캐시가 즉시 무효화되지 않습니다. 이는 경로 핸들러가 특정 경로와 연결되어 있지 않기 때문입니다. 라우터 캐시는 하드 새로고침 또는 자동 무효화 기간이 경과할 때까지 이전 페이로드를 계속 제공합니다.
  • 서버 액션에서 revalidatePath 또는 revalidateTag를 사용하여 데이터 캐시와 라우터 캐시를 즉시 무효화할 수 있습니다.

API

다음은 다양한 Next.js API가 캐싱에 어떻게 영향을 미치는지에 대한 개요입니다:

기본적으로 <Link> 컴포넌트는 전체 경로 캐시에서 경로를 자동으로 프리페치하고 React 서버 컴포넌트 페이로드를 라우터 캐시에 추가합니다.

프리페칭을 비활성화하려면 prefetch 속성을 false로 설정할 수 있습니다. 그러나 이는 임시로 30초 동안 경로 세그먼트를 저장하여 중첩된 세그먼트 간 빠른 내비게이션을 가능하게 합니다. 방문한 경로는 여전히 캐시됩니다.

router.prefetch

useRouter 훅의 prefetch 옵션을 사용하여 경로를 수동으로 프리페치할 수 있습니다. 이는 React 서버 컴포넌트 페이로드를 라우터 캐시에 추가합니다.

router.refresh

useRouter 훅의 refresh 옵션을 사용하여 경로를 수동으로 새로 고칠 수 있습니다. 이는 라우터 캐시를 완전히 지우고 현재 경로에 대해 서버에 새로운 요청을 보냅니다. refresh는 데이터 캐시나 전체 경로 캐시에 영향을 미치지 않습니다.

fetch

fetch로 반환된 데이터는 자동으로 데이터 캐시에 캐시됩니다.

// 기본적으로 캐시됨. `force-cache`는 기본 옵션이므로 생략 가능합니다.
fetch(`https://...`, { cache: 'force-cache' });

추가 옵션은 fetch API 레퍼런스를 참조하세요.

fetch options.cache

개별 fetch 요청의 데이터를 캐시하지 않으려면 cache 옵션을 no-store로 설정할 수 있습니다:

// 캐시 옵트 아웃
fetch(`https://...`, { cache: 'no-store' });

렌더링 출력이 데이터에 의존하기 때문에 cache: 'no-store'를 사용하면 해당 경로의 전체 경로 캐시도 건너뛰게 됩니다. 즉, 해당 경로는 모든 요청 시점에 동적으로 렌더링됩니다.

fetch options.next.revalidate

fetch의 next.revalidate 옵션을 사용하여 개별 fetch 요청의 재검증 기간(초 단위)을 설정할 수 있습니다. 이는 데이터 캐시를 재검증하며, 이는 전체 경로 캐시를 재검증합니다. 새로운 데이터가 가져오고, 서버에서 컴포넌트를 다시 렌더링하여 새로운 렌더링 출력을 캐시합니다.

// 최대 1시간마다 재검증
fetch(`https://...`, { next: { revalidate: 3600 } });

fetch options.next.tags 및 revalidateTag

Next.js에는 세분화된 데이터 캐싱과 재검증을 위한 캐시 태그 시스템이 있습니다.

fetch 또는 unstable_cache를 사용할 때 하나 이상의 태그로 캐시 항목을 태그할 수 있습니다. 그런 다음, revalidateTag를 호출하여 해당 태그와 연결된 캐시 항목을 제거할 수 있습니다.

예를 들어, 데이터를 가져올 때 태그를 설정할 수 있습니다:

// 태그로 데이터 캐시
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } });

그런 다음, revalidateTag를 호출하여 태그와 연결된 캐시 항목을 제거할 수 있습니다:

// 특정 태그로 항목 재검증
revalidateTag('a');

revalidateTag를 사용할 수 있는 두 가지 장소가 있으며, 이를 통해 달성하려는 목표에 따라 다릅니다:

  • 경로 핸들러: 서드 파티 이벤트(예: 웹훅)에 대한 응답으로 데이터를 재검증합니다. 이는 라우터 캐시를 즉시 무효화하지 않습니다.
  • 서버 액션: 사용자 액션(예: 폼 제출) 후 데이터를 재검증합니다. 이는 해당 경로에 대한 라우터 캐시를 무효화합니다.

revalidatePath

revalidatePath를 사용하면 단일 작업에서 특정 경로 아래의 데이터와 경로 세그먼트를 수동으로 재검증하고 다시 렌더링할 수 있습니다. revalidatePath 메서드를 호출하면 데이터 캐시를 재검증하여 전체 경로 캐시를 무효화합니다.

revalidatePath('/');

revalidatePath를 사용할 수 있는 두 가지 장소가 있으며, 이를 통해 달성하려는 목표에 따라 다릅니다:

  • 경로 핸들러: 서드 파티 이벤트(예: 웹훅)에 대한 응답으로 데이터를 재검증합니다.
  • 서버 액션: 사용자 인터랙션(예: 폼 제출, 버튼 클릭) 후 데이터를 재검증합니다.

revalidatePath와 router.refresh의 차이점

router.refresh를 호출하면 라우터 캐시가 지워지고 서버에서 현재 경로에 대한 새로운 요청이 이루어지지만, 데이터 캐시나 전체 경로 캐시에는 영향을 미치지 않습니다.

차이점은 revalidatePath가 데이터 캐시와 전체 경로 캐시를 무효화하는 반면, router.refresh는 클라이언트 측 API로 데이터 캐시와 전체 경로 캐시를 변경하지 않습니다.

동적 함수

cookies, headers, searchParams와 같은 동적 함수 및 Pages의 searchParams prop은 런타임의 요청 정보를 기반으로 합니다. 이를 사용하면 전체 경로 캐시를 옵트 아웃합니다. 즉, 경로는 동적으로 렌더링됩니다.

cookies

서버 액션에서 cookies.set 또는 cookies.delete를 사용하면 쿠키를 사용하는 경로가 오래되지 않도록 라우터 캐시를 무효화합니다 (예: 인증 상태를 반영).

세그먼트 구성 옵션

Route Segment Config 옵션을 사용하면 경로 세그먼트 기본값을 재정의하거나 fetch API를 사용할 수 없는 경우를 처리할 수 있습니다(예: 데이터베이스 클라이언트 또는 타사 라이브러리).

다음 Route Segment Config 옵션은 데이터 캐시와 전체 경로 캐시를 옵트 아웃합니다:

export const dynamic = 'force-dynamic';
export const revalidate = 0;

generateStaticParams

동적 세그먼트(예: app/blog/[slug]/page.js)의 경우 generateStaticParams에 의해 제공된 경로는 빌드 시 전체 경로 캐시에 캐시됩니다. 요청 시점에는 빌드 시점에 알려지지 않은 경로도 첫 번째 방문 시 캐시됩니다.

요청 시점의 캐싱을 비활성화하려면 경로 세그먼트에서 dynamicParams = false 옵션을 사용할 수 있습니다. 이 구성 옵션이 사용되면 generateStaticParams에 의해 제공된 경로만 제공되며, 다른 경로는 404로 처리되거나 일치(포괄적 경로의 경우)됩니다.

추가 정보는 generateStaticParams API 레퍼런스를 참조하세요.

React cache 함수

React cache 함수는 함수의 반환 값을 메모화하여 동일한 함수를 여러 번 호출할 때 한 번만 실행되도록 합니다.

fetch 요청은 자동으로 메모화되기 때문에 이를 React cache로 감쌀 필요가 없습니다. 그러나 fetch API가 적합하지 않은 경우 수동으로 데이터 요청을 메모화할 수 있습니다. 예를 들어, 일부 데이터베이스 클라이언트, CMS 클라이언트 또는 GraphQL 클라이언트의 경우입니다.

// utils/get-item.ts
import { cache } from 'react';
import db from '@/lib/db';

export const getItem = cache(async (id: string) => {
  const item = await db.item.findUnique({ id });
  return item;
});

0개의 댓글

관련 채용 정보