팀 사이드 프로젝트를 진행하던 중 fetch()를 사용해 SSR로 데이터를 호출하는 부분이 있었다.
STATUS 값에 따라 분기처리를 해야하는 페이지였는데 Postman으로 직접 API를 호출하면 최신 데이터가 잘 조회가 되고 React-query로 호출한 경우에도 제대로 전달이 되었는데 SSR인 경우에만 예전 데이터가 전달되고 있었다.
//브라우저 측 fetch 결과
{"id": "01JV43P29J0HT0F9NR5Z8TA4PY",
"title": "5월 13일 5월 13일 5월 13일 5월 13일 5월 13일 5월 13일 5월 13일 ~!3일 5월 13일 5월 13일 ~!",
...,
"status": "INACTIVE"}
//SSR 시 fetch 결과
{
"id": "01JV43P29J0HT0F9NR5Z8TA4PY",
"title": "5월 13일 5월 13일 5월 13일 5월 13일 5월 13일 5월 13일 5월 13일 ~!3일 5월 13일 5월 13일 ~!",
...,
"status": "ACTIVE"
}
캐시가 남는다는 짐작은 했지만 nextjs 12 버전을 현업에서 사용중이기 때문에 SSR 사용이 처음이 아닌데 라는 생각 때문에 원인 파악을 하는 것이 조금 어려웠던 것 같다.
결국 해답은 공식 문서에 있었다.
fetch() 사용 시 cache 옵션을 명시하지 않으면 default인 'force-cache'가 적용되며,
Next.js의 Data Cache에 저장된 응답 데이터가 존재할 경우 이를 그대로 반환된다.
그렇다면 Data Cache는 어디에 저장되는가?
.next/cache/ 경로에 관련된 캐시가 저장될 수 있고, Vercel에서는 CDN 캐시와 연동된다.
환경 | 캐시 저장 위치 | 설명 |
---|---|---|
로컬 개발 | .next/cache/fetch-cache/ 디렉토리 | 서버에서 fetch() 한 결과가 여기에 파일 형태로 저장됨 |
Vercel 배포 | Vercel의 CDN(에지 네트워크) | 캐시된 fetch 결과 및 페이지 HTML이 Vercel의 글로벌 엣지 서버에 저장됨 |
await fetch('/api/your-endpoint', {
cache: 'no-store',
next: { revalidate: 0 }
});
revalidate만 설정해도 되지만, Next 내부 캐시가 꼬이는 이슈를 방지하려면 cache도 함께 명시하는 것이 안전
페이지 레벨에서 SSR을 구성할 경우, generateStaticParams, generateMetadata, getServerSideProps 등에서도 동일한 원칙 적용 필요