동적 렌더링 페이지의 성능은 ‘데이터 캐시(Data Cache)‘를 얼마나 잘 활용하는지에 달려있는데요.
이것이 바로 API 서버 부하를 줄이고 렌더링 속도를 획기적으로 높이는 핵심 전략입니다.
왜 데이터 캐시가 필요할까#
지난 글에서 Next.js는 가능한 한 정적 렌더링을 사용하는 게 좋다고 말씀드렸거든요.
하지만 사용자 정보를 보여주는 페이지처럼, 어쩔 수 없이 동적 렌더링을 써야만 하는 경우도 분명히 있습니다.
동적 렌더링은 매 요청마다 화면을 새로 그리기 때문에, 렌더링 속도가 아주 빨라야만 하는데요.
이때 성능 저하의 가장 큰 주범이 되는 것이 바로 ‘데이터 페칭’ 과정입니다.
데이터 캐시를 활용한 최적화 전략#
‘데이터 캐시’는 API 응답 같은 데이터 페칭 결과를 서버에 영구적으로 저장하는 캐시인데요.
한번 저장되면 여러 사용자나 요청에 걸쳐 공유되는 아주 강력한 기능입니다.
동적 렌더링 페이지라고 해서 그 안에 있는 모든 데이터를 매번 새로 가져올 필요는 없거든요.
사용자마다 달라지는 데이터와 그렇지 않은 공통 데이터를 잘 분리하는 것이 핵심입니다.
바로 이 공통 데이터에 데이터 캐시를 적용하면, 동적 렌더링의 속도를 높이고 API 서버의 부담도 크게 줄일 수 있는 거죠.
따라서 데이터 페칭 로직마다 가장 적절한 캐시 설정을 해주는 습관이 아주 중요합니다.
Next.js에서 데이터 캐시 사용하기#
서버 환경에서 실행되는 fetch() 함수는 Next.js에 의해 기능이 확장되어 있는데요.
데이터 캐시를 제어할 수 있는 다양한 옵션이 바로 여기에 포함되어 있습니다.
fetch(`https://...`, {
cache: "force-cache", // "no-store"는 캐시를 사용하지 않음
});
fetch(`https://...`, {
next: {
revalidate: 60, // 60초마다 캐시를 갱신
},
});
fetch(`https://...`, {
next: {
tags: ["products"], // 캐시에 'products' 태그를 지정
},
});
v15부터 fetch의 기본 캐시 동작이 변경되었으니 이 점은 꼭 기억해두시는 게 좋은데요.
자세한 내용은 공식 문서를 참고하시는 것을 추천합니다.
fetch 외의 작업에 캐시 적용하기#
fetch()를 사용하지 않는 DB 직접 접근 같은 경우에도 데이터 캐시를 사용할 수 있는 방법이 있거든요.
바로 unstable_cache() 함수를 사용하는 것입니다.
import { getUser } from "./fetcher";
import { unstable_cache } from "next/cache";
const getCachedUser = unstable_cache(
getUser, // 캐싱할 함수 (DB 접근 등)
["my-app-user"], // 고유 키 배열
{
tags: ["users"], // 재검증을 위한 태그
revalidate: 60, // 60초
},
);
export default async function Component({ userID }) {
const user = await getCachedUser(userID);
// ...
}
참고로 이 unstable_cache() 함수는 미래에 "use cache"라는 새로운 기능으로 대체될 예정입니다.
필요할 때 캐시 갱신하기#
이 내용은 지난 글에서도 잠깐 다뤘는데요.
데이터가 변경되었을 때 이 캐시를 즉시 갱신할 수 있는 방법도 물론 있습니다.
바로 ‘서버 액션’이나 ‘라우트 핸들러’에서 revalidatePath()나 revalidateTag()를 호출하는 것인데요.
특히 데이터가 ‘수정’되었을 때, 관련된 캐시를 즉시 무효화하는 용도로 아주 유용하게 사용됩니다.
주의해야 할 점#
fetch() 옵션으로 cache: "no-store"를 설정하면 데이터 캐시를 사용하지 않게 되는데요.
여기에는 ‘해당 페이지가 동적 렌더링으로 전환된다’는 아주 중요한 부수 효과가 함께 따라옵니다.
단순히 ‘데이터 캐시를 끄고 싶다’는 생각만으로 이 옵션을 사용하기 전에, 이 페이지가 정말로 동적 렌더링이 되어도 괜찮은지, 그로 인한 성능 영향은 없는지 반드시 한 번 더 고민해봐야 합니다.