Next.js의 Request Memoization은 페이지 렌더링 과정 중 발생하는 중복 API 요청을 방지하고 데이터 페칭을 최적화하기 위해 설계된 기능이다. 이 기능은 하나의 페이지 렌더링 과정에서 중복된 API 요청을 캐싱하여 동일한 요청을 한 번만 실행되도록 보장한다.
Request Memoization이란, "요청을 기억한다"는 뜻으로 같은 API 요청을 반복적으로 호출하지 않도록 방지하는 기능이다.
여러개의 컴포넌트에서 발생하는 동일한 요청에 대해 데이터를 캐싱 후 재사용하여, 자동으로 데이터 페칭을 최적화시켜 불필요한 네트워크 트래픽을 줄임.
페이지 렌더링 중에만 적용되며, 렌더링이 종료되면 캐시가 소멸된다.
처음 API 요청이 발생했을 때 Request Memoization에는 아무 데이터도 캐싱되지 않은 상태이다.
요청 결과는 MISS
로 판정되고, 백엔드 서버에 요청이 전달된다.
응답 데이터를 받은 후, Request Memoization에 해당 데이터를 SET(저장)
한다.
동일한 API 요청이 반복될 경우 Request Memoization에 저장된 데이터를 먼저 확인한다.
캐싱된 데이터가 있다면(HIT
), 데이터를 다시 요청하지 않고 캐싱된 데이터를 그대로 사용해 페이지를 렌더링 한다. (이런 경우에는 요청을 아예 발송하지 않는다)
페이지 렌더링 종료 후 Request Memoization에 저장된 데이터는 자동으로 삭제된다.
새로고침이나 새로운 요청이 들어오면, 다시 MISS
상태로 돌아간다.
Request Memoization과 Data Cache는 목적과 사용 방식이 다르다.
특징 | Request Memoization | Data Cache |
---|---|---|
캐싱 범위 | 페이지 렌더링 중에만 존재 | 서버가 중단되기 전까지 영구적으로 유지 |
사용 목적 | 중복된 API 요청 방지 | 데이터의 영구 저장 및 활용 |
캐시 지속성 | 렌더링 종료 시 캐시 소멸 | 서버가 중단되기 전까지 데이터 보관 |
적용 사례 | 동일 페이지 내 중복 데이터 요청 방지 | 자주 변경되지 않는 데이터의 캐싱 |
중복된 API요청이야 안 보내면 그만인 거 아닌가? 라고 생각할 수 있는데 굳이 Next가 이런 추가적인 기능까지 제공해 주고 있는 이유가 무엇일까? 서버 컴포넌트의 도입으로 인해서 이제는 데이터를 페칭하는 패턴이 변화했기 때문이다.
Page Router버전의 Next앱은 서버 측에서 데이터를 페칭해 오려면 getServerSideProps
나 getStaticProps
같은 서버 측에서만 실행되는 함수를 통해서 데이터를 불러오고 페이지 컴포넌트에게 데이터들을 props로 넘겨주는 방식을 사용했지만,
App Router에서 도입된 서버 컴포넌트는 컴포넌트별로 데이터를 직접 페칭하는 방식을 사용한다.
이 방식은 컴포넌트가 독립적으로 데이터를 처리하도록 만들어 개발 편의성을 높였지만, 아래와 같은 문제가 발생할 수 있다.
서로 다른 컴포넌트가 동일한 데이터를 중복 요청하는 경우.
중복된 데이터 요청이 많아질수록, 불필요한 네트워크 비용이 발생.
Footer
컴포넌트에서 전체 도서의 개수를 표시하기 위해 /book
API를 호출.
AllBooks
컴포넌트에서도 동일한 /book
API를 호출하여 전체 도서 데이터를 표시.
// Footer 컴포넌트 // src/app/layout.tsx
async function Footer() {
const response = await fetch(`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book`);
const books = await response.json();
return <footer>{books.length}개의 도서가 등록되어 있습니다.</footer>;
}
// AllBooks 컴포넌트 // src/app/(with-searchbar)/page.tsx
async function AllBooks() {
const response = await fetch(`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book`);
const books = await response.json();
return (
<div>
{books.map((book) => (
<BookItem key={book.id} {...book} />
))}
</div>
);
}
/book
API가 동일한 페이지에서 두 번 호출되어, 불필요한 네트워크 비용이 발생.위 문제를 해결하기 위해 Request Memoization이 동작한다.
Request Memoization에 데이터가 없으므로 MISS
.
데이터를 백엔드 서버에서 가져와 캐시에 저장(SET
).
Request Memoization에서 캐싱된 데이터를 반환.
API 요청은 실제로 한 번만 발생.
APP Router버전의 Next앱에서는 이렇게 컴포넌트 내부에서 직접 데이터를 페칭해 오는 패턴으로 개발을 진행하기 때문에 API호출이 중복되는 경우가 자주 발생하게 된다. 그래서 이런 문제점을 해결해주기 위해 Next는 Request Memoization이라는 추가적인 캐싱 기능을 자동으로 제공하고 있다는 점을 기억하자.