
Next.js는 대부분의 영역에서 fetch 함수를 기반으로 캐싱을 한다!
Next.js의 fetch는 브라우저 API가 아닌 Next.js에서 확장한 새로운 API다.
그 중에서도 크게 두가지 포인트에서 캐싱을 진행하게 된다.
Next.js의 두가지 캐싱 포인트
Full Route Cache (build 시)
- 빌드 시점에 페이지를 렌더링하고 그 결과를 캐싱하는 기능
- 서버는 매 요청마다 페이지를 다시 렌더링할 필요 없이, 미리 생성된 HTML과 데이터를 빠르게 제공할 수 있어 페이지 로딩속도가 크게 향상됨
- 서버에서 React의 API를 활용하여 렌더링 작업을 수행함
- 기본적으로 Full Route Cache는 지속적이며, 사용자 요청에 의한 렌더링 결과가 캐싱되어 있음
- 따라서 동일한 페이지에 대한 요청이 있을 때마다 서버가 빠르게 응답할 수 있는 것
- 하지만 데이터가 변경되거나, 실시간 정보가 필요한 페이지의 경우 이 캐시를 무효화하거나 동적 렌더링을 선택할 수 있음 ( revalidate 옵션 등의 기능을 통해 제어)
1) React Server Component Payload 생성
- React는 서버 컴포넌트들을 스트리밍에 최적화된 특별한 데이터 형식으로 렌더링
- 이 데이터는 클라이언트에서 사용할 컴포넌트의 정보와 상태를 포함
2) HTML 생성
- Next.js는 Payload와 클라이언트 컴포넌트의 JS 코드를 사용해 서버에서 최종 HTML을 생성
Data Cache (요청할 때)
- Next.js의 fetch는 브라우저의 fetch API를 확장한 것으로, 서버 측에서 각 요청에 맞는 캐싱 전략을 설정할 수 있음
- 기본적으로 fetch 함수를 사용하면 데이터가 자동으로 캐싱되며, 이는 동일한 데이터에 대한 중복 요청을 방지
- fetch 함수를 기반으로 데이터를 캐싱하여, 서버 요청 간에도 데이터를 지속적으로 활용할 수 있게 함
- 이는 외부 데이터 소스에 대한 요청 수를 줄이고, 응답 시간을 개선하는 데 큰 도움이 됨
const res = await fetch('<https://api.example.com/data>', { next: { revalidate: 3600 } });
const data = await res.json();
- 위는 3600초(1시간)동안 재검증 없이 캐시된 데이터를 사용하도록 설정한 것
const res = await fetch('<https://api.example.com/data>', { cache: 'no-store' });
const data = await res.json();
- 특정 데이터를 캐싱하지 않고 매번 최신 데이터를 가져오고 싶다면, 다음과 같이 옵션을 설정할 수 있음
- 페이지에 no-store 옵션의 fetch 함수가 하나라도 있으면 해당 페이지는 정적 페이지로 처리되지 않는다
Request Memoization
서버 컴포넌트 렌더링 중 동일한 fetch 요청이 여러번 호출되더라도, 실제로는 한번만 실행되도록 하는 기능
불필요한 중복 네트워크 요청을 방지하고, 서버 자원과 응답 시간을 최적화할 수 있음
async function getCommonData() {
const res = await fetch('<https://api.example.com/common-data>');
return res.json();
}
// 컴포넌트 A에서 데이터 호출
const dataA = await getCommonData();
// 컴포넌트 B에서 동일한 데이터 호출
const dataB = await getCommonData();
위처럼 동일한 fetch 요청을 하는 경우, 두번째 호출에서는 첫번째 호출의 결과를 재사용하게 됨
Next.js 캐싱 메서드
generateStaticParams
- 빌드 타임에 모든 동적 경로에 해당하는 페이지를 미리 생성할 수 있도록 Next.js에 알려 빠른 페이지 로드와 서버 부담을 줄이기위한 목적!
예시) 제품 id로 동적 경로가 있을 때, generateStaticParams를 사용 -> 데이터를 받아와 반복문으로 모든 products의 id로 모든 상세 페이지를 미리 빌드할 수 있도록 했다
// app/products/[id]/page.tsx
import { getProducts } from '@/lib/api'; // 제품 데이터를 가져오는 가상의 함수
// generateStaticParams 함수 정의
export async function generateStaticParams() {
const products = await getProducts(); // 모든 제품 데이터를 가져온다고 가정
return products.map((product) => ({
id: product.id, // 각 제품의 ID를 사용해 경로 파라미터 생성
}));
}
// 동적 페이지 컴포넌트
export default function ProductPage({ params }: { params: { id: string } }) {
return <div>Product ID: {params.id}</div>;
}
tags
Next.js에서 캐시된 데이터를 식별하고 관리하기 위해 사용하는 개념
특정 데이터나 페이지에 태그를 부여하여, 해당 태그와 관련된 데이터를 효율적으로 무효화할 수 있음
fetch('/api/data', {
next: {
revalidate: 60,
tags: ['product', 'category']
}
})
위 예시는 '/api/data' 에대한 요청을 product, category 태그를 붙인 예시이다.
기본적으로 캐시된 데이터를 사용하지만, 필요한 경우 revalidateTag('category') 혹은 revalidateTag('product') 메서드를 호출해 캐시된 데이터를 무효화하고 fetch 요청을 하여 유효한 데이터를 새로 받아올 수 있다.
+ revalidatePath 메서드를 사용하면 페이지 전체의 캐시를 무효화하고 새로 요청을 보내 유효한 값을 받아올 수 있다.
'Next.js' 카테고리의 다른 글
[Next.js] Auth와 Middleware (0) | 2024.09.30 |
---|---|
[Next.js] Parallel Routes & Intercepting Routes (1) | 2024.09.29 |
[Next.js] Router Handler & Server Action (0) | 2024.09.27 |
[Next.js] Asset 최적화 (1) | 2024.09.27 |
[Next.js] Error UI, Error Handling (0) | 2024.09.27 |