고백하자면 저는 next.js13 버전만 사용해봤습니다.😅 14버전이 나왔을 때도 공부해야지 공부해야지 미루기만 하고 최근에서야 앱라우터 와 서버 컴포넌트를 사용하는 중입니다...ㅎㅎ
막상 사용해보니 이렇게 효율적일 수가 없더라구요 진작에 공부해서 써볼껄 이라는 후회가 들었습니다. next.js 15버전을 공부하던 중에 가장 인상 깊었던 것은 캐시 기능이었고 새로워진 next.js는 같은 일 계속 시키는거 정말 싫어하는 구나라고 느꼈습니다.
그래서 오늘은 next.js의 데이터 캐시하는 방법에 대해서 정리해보려고 합니다~!
먼저, 데이터 페칭에 대해서 어떻게 이뤄지는지 간략히 알아보도록 하겠습니다.
async - await
키워드와 fetch
메서드를 활용해서 데이터를 직접 불러오는 데이터 페칭 로직을 만들 수 있습니다. export async function Page(props){
const data = await fetch('...');
return <div>...</div>
}
async - await
키워드 를 사용할 수 없습니다. 🧐 async - await 키워드 사용이 서버 컴포넌트에서는 되지만, 클라이언트 컴포넌트에서는 안되는 이유
- 서버 컴포넌트는 서버에서 데이터를 미리 가져와서 HTML을 렌더링할 수 있기 때문입니다. 서버 측에서는 비동기 작업이 완료된 후 렌더링을 처리하므로, 비동기 작업을 문제없이 사용할 수 있습니다.
- 반면, 클라이언트 컴포넌트는 브라우저에서 실행되며, 랜더링 시에 비동기 작업을 바로 처리할 수 없기 때문에 제대로 렌더링이 이루어지지 않을 수 있습니다.
☝🏻 주의사항
데이터 패칭을 위한 환경 변수를 설정할 때 .env 파일에서NEXT_PUBLIC
이라는 접두사를 붙이지 않으면 next 는 자동으로 해당 환경변수를 서버측에서만 접근 가능한 것으로 인식하여 해당 환경변수에 대해 클라언트 컴포넌트에서는 접근이 불가능합니다!
📢 Next 서버에서 발생하는 데이터 패칭을 로그로 남기는 설정
import type { NextConfig } from "next"; const nextConfig: NextConfig = { logging: { fetches: { fullUrl: true, }, }, }; export default nextConfig;
- next.config.ts 파일을 위와 같으 설정하면 터미널에서 데이터 패칭에 대한 로그를 확인할 수 있습니다!
const response = await fetch('~/api', {cache: "force-cache});
{cache: "force-cache"}
{cache: "no-store"}
{next: {revalidate: 3}}
{next: {tags: ['a']}}
책 리스트 불러오는 API로 예시를 살펴보도록 하겠습니다!
async function AllBooks() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book`,
{ cache: "no-store" } // 이 부분을 원하는 캐시 옵션으로 설정합니다!
);
if (!response.ok) {
return <div>오류가 발생했습니다...</div>;
}
const allBooks: BookData[] = await response.json();
return (
<div>
{allBooks.map((book) => (
<BookItem key={book.id} {...book} />
))}
</div>
);
}
export default function Home() {
return (
<div>
<section>
<h3>등록된 모든 도서</h3>
<AllBooks />
</section>
</div>
);
}
{cache: "force-cache"}
로 설정했을 때
{cache: "no-store"}
로 설정했을 때
마지막으로 리퀘스트 메모이제이션이란 "요청을 기억한다." 라는 뜻으로, 중복된 요청이 발생하지 않도록 캐싱하는 것을 말합니다. 그렇다면 여기서 "데이터 캐시랑 뭐가 다른거지?" 라는 의문을 생길 수 있습니다.
데이터 케시는 백엔드 서버로부터 불러온 데이터를 거의 영구적으로 보관하기 위해 사용됩니다. 따라서 서버 가동중에는 영구적으로 보관됩니다.
리퀘스트 메모이제이션은 하나의 페이지를 렌더링 하는 동안에 중복된 API 요청을 캐싱하기 위해 존재합니다. 따라서, 랜더링이 종료되면 모든 캐시가 소멸됩니다.
결론적으로 데이터 캐시는 지속적으로 유지되는 반면, 리퀘스트 메모이제이션은 렌더링 동안에만 유지된다고 정리할 수 있습니다.
리퀘스트 메모이제이션이 필요한 이유는 서버 컴포넌트의 도입 때문인데요 하나의 페이지에서 컴포넌트가 각각 자신이 필요한 데이터를 페칭하기 때문에 한 페이지에서 서로 다른 컴포넌트에서 동일한 API를 요청하는 경우가 발생할 수 있기 때문입니다.
그리고 리퀘스트 메모이제이션은 Next.js에서 자동으로 제공하는 기능으로 별도의 설정은 필요하지 않습니다!
📚 참고
한 입 크기로 잘라먹는 next.js