Next.js에서는 Cache를 통해 성능향상과 비용 절감을 가능하게 합니다. Next.js에서는 Cache는
Request Memoization
,Data Cache
,Full Route Cache
,Router Cache
4개의 매커니즘이 존재합니다.
매커니즘 | 대상 | 위치 | 목적 | 지속 시간 |
---|---|---|---|---|
Request Memoization | 함수의 반환 값 | 서버 | React 컴포넌트 트리 내에서 데이터를 재사용 | 요청당 수명 주기 |
Data Cache | 데이터 | 서버 | 사용자 요청 및 배포 간에 데이터를 저장 | 지속적 (재검증 가능) |
Full Route Cache | HTML 및 RSC 페이로드 | 서버 | 렌더링 비용 감소 및 성능 향상 | 지속적 (재검증 가능) |
Router Cache | RSC 페이로드 | 클라이언트 | 탐색 시 서버 요청 감소 | 사용자 세션 또는 시간 기반 |
웹 서버로 페이지 요청이 들어오면 페이지에 필요한 데이터들을 fetch하게 되는데,
이때 동일한 endpoint로의 API fetch를 여러 컴포넌트에서 수행할 필요가 있다면 Request Memoization
이 동작합니다.
상위 컴포넌트에서 API fetch 결과를 중복 요청 하지 않고, 실제 API 요청은 최초 1회만 전송되고 나머지는 응답값을 재사용합니다.
https://nextjs.org/_next/image?url=%2Fdocs%2Flight%2Fdeduplicated-fetch-requests.png&w=1920&q=75
Request Memoization
은 서버에서 호출되는 GET 메서드에만 적용되므로, POST나 DELETE API 또는 클라이언트에서 호출되는 API에는 적용되지 않습니다.
그리고 한 번의 서버 렌더링 동안만 유효하기 때문에 따로 재검증할 필요가 없을 뿐 아니라 할 수도 없습니다.
Request Memoization
를 살펴보기 위해 별도의 벡엔드 서버를 만들어 벡엔드로 가는 요청을 살펴보겠습니다.
요청을 보낼때 헤더 값에 현재 페이지명 page
, layout
명을 추가하여 요청을 보냈습니다.
코드는 아래와 같이 같습니다.
backend
// app.js
import express from 'express';
const app = express();
app.get('/messages', (req, res) => {
const requestSource = req.headers['x-id'];
console.log(`${new Date().toISOString()}: EXECUTING /messages on backend from ${requestSource}`);
res.json([
{ id: 1, text: 'Hello World' },
{ id: 2, text: 'Another message from the separate backend' },
]);
});
app.listen(8080);
client
// app/messages/layout.js
export default async function MessagesLayout({ children }) {
const response = await fetch('<http://localhost:8080/messages>', {
headers: {
'X-ID': 'layout',
},
});
const messages = await response.json();
const totalMessages = messages.length;
return (
<>
<h1>Important Messages</h1>
<p>{totalMessages} messages found</p>
<hr />
{children}
</>
);
}
// app/messages/page.js
import Messages from '@/components/messages';
export default async function MessagesPage() {
const response = await fetch('<http://localhost:8080/messages>', {
headers: {
'X-ID': 'page',
},
});
const messages = await response.json();
if (!messages || messages.length === 0) {
return <p>No messages found</p>;
}
return <Messages messages={messages} />;
}