일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- babel.config.js
- 백준
- react native 세팅
- React
- react native font
- Project
- react native
- 리액트 네이티브
- AWS Access Key
- AWS
- firebase 라이브러리
- img upload
- 에러
- error
- Next.js
- react native picker
- react native 개발
- react native CLI
- Access Key 생성
- aws bucket 정책
- js
- 리엑트 네이티브 아이콘
- s3 upload
- GIT
- 리액트
- 문자열 대소문자 구별
- 문자열 대소문자
- PongWorld
- fire base
- 리액트 네이티브 에러
- Today
- Total
밝을희 클태
[ Next.JS ] 배포 환경에서 주문형 재검증(On-demand Revalidation)이 안된다 본문
Binaries:
Node: 22.3.0
npm: 10.8.1
Yarn: 1.22.19
pnpm: 8.14.0
Relevant Packages:
next: 14.2.5 // Latest available version is detected (14.2.5).
eslint-config-next: 14.2.3
react: 18.3.1
react-dom: 18.3.1
typescript: 5.4.5
현재 개발 환경에서 테스트를 마치고, 배포 환경에서 프로젝트를 테스트 중인데, 주로 revalidateTag를 사용해서 재검증을 요청하는 방식으로 구현했다. 다른 페이지들은 전부 문제가 없었는데, 메인 페이지(’/’)에서 재검증 요청이 제대로 이루어지지 않는 문제가 발생했다.
검색해보니까 작년부터 나와 비슷한 사례들이 좀 있긴 한데, 딱히 이거다 하는 해결책은 없었다.
처음에는 Vercel 문제인가 싶어서 Serverless Functions의 리전도 바꿔보고 이것저것 만져봤는데, Vercel 문제가 아닌 것 같았다. 그래서 로컬에 배포 환경을 조성하고 테스트해보니 여전히 문제가 발생했다.
서버에 부담을 줄이기 위해 메인 페이지를 방문할 때마다 요청을 하는 게 아니라, 상품이 업로드되면 products 태그를 활용해 재검증 요청을 하도록 구현했다.
CSR에 useQuery staleTime은 Infinity
import RenderHome from './_components/RenderHome';
import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query';
import getRecentProducts from './_lib/getRecentProducts';
export default async function Home() {
const queryClient = new QueryClient();
await queryClient.prefetchQuery({ queryKey: ['recentProducts'], queryFn: getRecentProducts, staleTime: 60 * 1000 });
const dehydratedstate = dehydrate(queryClient);
return (
<HydrationBoundary state={dehydratedstate}>
<RenderHome />
</HydrationBoundary>
);
}
const getRecentProducts = async () => {
try {
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
const res = await fetch(`${baseUrl}/api/products/recent`, {
next: { tags: ['products'] },
});
const data = await res.json();
return data;
} catch (error) {
throw error;
}
};
export default getRecentProducts;
revalidateTag가 문제인가 싶어 revalidatePath로 변경해봤으나, 여전히 데이터 재검증은 일어나지 않았다. 그런데 신기한 건 revalidate, 메인 페이지의 CSR 환경에서 router.refresh()도 전혀 작동하지 않았다.
다른 페이지에서도 “products” 태그를 많이 사용하는 게 문제인가 싶어서 다른 태그를 줘봤지만, 이것도 해결책이 아니었다.
CSR에서 useQuery의 staleTime을 0으로 설정하고 테스트를 해보았으나, 메인 페이지의 데이터는 여전히 빌드 시점의 데이터로 남아 변하지 않았다. 내 예상은 CSR 환경에서의 fetch는 기본 캐싱 전략이 “no-store”이기 때문에, SSR에서 캐시 데이터를 가져오더라도 CSR에서는 DB의 최신 데이터를 가져와야 한다는 것이었다.
의심되는 부분을 찾았다. next run build를 할 때 생성된 파일들을 보면 최상단의 라우트가 문제가 되는 부분인데, 해당 라우트만 정적 라우트로 생성된 것을 볼 수 있었다.
해당 라우트를 강제로 동적 라우트로 설정하기 위해 아래의 코드를 추가했다.
export const dynamic = 'force-dynamic';
결과적으로, 동적 라우트로 잘 생성되었고, 배포 환경에서도 재검증 타이밍에 맞춰 요청이 잘 보내졌다.
이번 경험을 통해 Vercel 문제로만 생각하고 수많은 커밋을 남겼던 점이 아쉽다. 빌드 과정에서 조금만 더 주의 깊게 살펴봤다면 빠르게 원인을 찾을 수 있었을 것이다.
'KEYNUT 프로젝트' 카테고리의 다른 글
[ Next.JS ] 이미지 슬라이더(image-slider) UX 개선 (0) | 2024.08.18 |
---|---|
[ JS ] iPad safari에서 모바일 체크하기 (0) | 2024.08.07 |
[ JavaScript ] 핀치 줌 구현하기! (0) | 2024.07.19 |
[ Next.JS ]상품 업로드, 수정, 조회 로직 (0) | 2024.07.16 |
[ Next.JS ] 효율적인 서버사이드 데이터 캐싱 및 재검증 (0) | 2024.07.13 |