3. 요청 데이터 캐싱
다음은 서버에서 블로그 포스트에 대한 목록 데이터를 가져오는 예시 코드
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog');
const posts = await data.json();
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}만약 사용자가 브라우저를 통해 위 페이지를 지속적으로 새로고침할 경우,
Next.js는 다음의 코드로 인해 URL 엔드포인트에 해당하는 서버로 데이터를 가져오는 요청을 반복적으로 전송하게 됨
// ...
const data = await fetch('https://api.vercel.app/blog');
// ...이처럼 블로그 포스트와 같이 거의 변경되지 않는 데이터에 대해 반복적인 요청을 수행하는 것은 불필요한 자원 낭비라고 볼 수 있음
1. 데이터 캐시, Data Cache
따라서 Next.js 서버 프로세스가 보유한 메모리 공간을 활용하여 동일한 요청에 대해 미리 응답 결과 데이터를 보관해둘 경우 자원을 절약할 수 있음
Next.js는 특정 요청에 대한 응답 데이터를 임시로 보관해두는 공간을 제공하는데, 이를 데이터 캐시라고 함
이를 통해 동일한 요청 경로에 대해 동일한 네트워크 요청 로직이 수행되더라도,
서버는 요청을 다시 수행하지 않고 데이터 캐시에 저장된 데이터를 통해 응답하기 때문에 애플리케이션의 성능을 개선할 수 있음
2. 데이터 캐시의 동작 과정
Next.js의 데이터 캐시가 동작하는 과정은 다음과 같음

Step 1
Next.js에서 fetch API를 통해 캐싱을 수행하도록 적용하기 위해서는 force-cache옵션을 활용할 수 있음
fetch API를 통해 초기 요청이 발생하였을 경우, Next.js는 데이터 캐시에서 캐싱된 결과값이 이미 존재하는지 먼저 확인함
export default async function ProductsPage() {
const response = await fetch("http://localhost:3001/products", {
cache: 'force-cache',
// 기본값은 캐싱을 수행하지 않는 'no-store'로 동작
});
const products = await response.json();
// return ( ... )
}Github issue: React의 캐시 동작 변경
Next.js 14 초기 버전에서는 다음과 같이 fetch API를 통해 데이터 가져오기 요청 수행 시 기본적으로 응답 결과 데이터에 대해 캐싱을 수행하였음
현재 Next.js 15 버전에서는 fetch API를 통해 데이터 가져오기 요청을 수행할 경우 기본값으로 캐싱을 수행하지 않는 것으로 변경됨
Step 2
만약 데이터 캐시에 캐싱된 결과가 이미 존재할 경우, Next.js는 해당 값을 가지고 즉각 응답하며 요청 기록은 메모리에 기억됨(memoized)
Step 3
반대로 캐싱된 결과가 존재하지 않을 경우, 요청은 데이터베이스(DB)까지 도달하여 실제 요청 및 응답 처리가 수행되며,
응답 결과 값은 데이터 캐시에 저장되고, 요청 기록 역시 메모리에 기억됨
Step 4
만약 캐싱을 수행하지 않도록 적용하는 no-store 옵션으로 요청이 수행될 경우,
모든 요청은 항상 실제 데이터베이스(DB)까지 도달하여 실제 요청 및 응답 처리가 수행됨
Step 5
캐시를 수행하는 옵션을 적용하든 하지 않든 간에,
모든 데이터 가져오기(Data fetching) 요청들은 동일한 데이터 요청에 대해 렌더링 과정 내에서 중복 요청으로 처리되지 않도록 메모리에 기억됨
데이터 캐시와 요청 메모이제이션의 차이
공통점
두 캐싱 메커니즘 모두 캐시된 데이터를 재사용하여 성능 향상에 도움이 됨
차이점
데이터 캐시는 서버로 들어오는 요청과 배포 과정에서 지속적으로 유지되지만,
메모이제이션은 요청 수명주기 동안만 유지됨