웹 개발
동적 라우트 배포할 때 확인할 사항들
Next.js나 다른 프레임워크의 동적 라우트가 프로덕션에서 404를 반환할 때 문제 해결 방법.
동적 라우트가 작동 안 할 때
"로컬에서는 /product/123이 잘 뜨는데 서버에선 404다"라는 신고가 오면, 보통 동적 라우트 설정이나 빌드 프로세스에서 뭔가 잘못되었다.
동적 라우트는 빌드할 때 미리 생성할 수도 있고(ISR), 요청 시 동적으로 생성할 수도 있는데, 각 방식에 문제가 생길 수 있다.
Next.js 동적 라우트 기본
// app/product/[id]/page.tsx
export default function ProductPage({ params }: { params: { id: string } }) {
return <h1>상품 {params.id}</h1>;
}
// 이 파일은 다음 경로들을 처리
// /product/1
// /product/abc
// /product/123
빌드할 때 라우트가 생성되지 않음
ISR(Incremental Static Regeneration) 설정이 있으면 빌드 시 라우트 목록을 생성한다.
// app/product/[id]/page.tsx
export async function generateStaticParams() {
const products = await getAllProducts();
return products.map(product => ({
id: product.id.toString(),
}));
}
export const revalidate = 3600; // 1시간마다 갱신
export default function ProductPage({ params }: { params: { id: string } }) {
return <h1>상품 {params.id}</h1>;
}
generateStaticParams가 없으면 모든 라우트를 미리 생성하지 못해서, 빌드 후 처음 요청하는 경로는 로드되지 않을 수 있다.
동적 라우트 테스트하기
npm run build
# 빌드 결과 확인
cat .next/routes-manifest.json | jq '.dynamicRoutes'
# 프로덕션 빌드 실행
npm run start
# 실제로 경로에 접근해보기
curl http://localhost:3000/product/123
curl http://localhost:3000/product/456
서버에서 라우트 처리 실패
만약 요청 시에 라우트를 동적으로 생성한다면, 서버에서 404를 반환할 수 있다.
// app/product/[id]/page.tsx
import { notFound } from 'next/navigation';
export default async function ProductPage({
params
}: {
params: { id: string }
}) {
const product = await getProduct(params.id);
if (!product) {
notFound(); // 404 페이지 표시
}
return <h1>{product.name}</h1>;
}
만약 getProduct가 실패하면(DB 연결 오류, 타임아웃 등) 의도하지 않은 404가 나타날 수 있다.
서버 로그를 확인해서 실제 오류를 본다.
# Docker 로그 확인
docker logs my_app_container
# 또는 SSH로 접속해서 확인
ssh user@server
tail -100 /var/log/nextjs/error.log
리다이렉트 설정 문제
만약 라우트를 리다이렉트 설정했다면 그게 제대로 작동하는지 확인한다.
// next.config.js
module.exports = {
async redirects() {
return [
{
source: '/old-product/:id',
destination: '/product/:id',
permanent: true, // 301 리다이렉트
},
];
},
};
리다이렉트도 빌드할 때 설정되므로, next.config.js를 수정한 후 다시 빌드해야 한다.
동적 라우트 캐시 문제
ISR로 설정했으면 캐시 시간이 지나야 새 콘텐츠가 로드된다.
export const revalidate = 60; // 60초마다 갱신
// On-demand 갱신도 설정 가능
export async function POST(request: Request) {
revalidateTag('product');
return new Response(JSON.stringify({ revalidated: true }));
}
배포 전 체크리스트
- 동적 라우트가
[id]형식으로 정의되어 있는가? - ISR을 사용한다면
generateStaticParams가 구현되어 있는가? - 로컬에서 빌드 후
npm run start로 테스트했는가? - 여러 동적 경로(예: /product/1, /product/abc)를 테스트했는가?
- 존재하지 않는 경로(예: /product/notfound)는 404를 반환하는가?
- 리다이렉트 설정이 있다면 제대로 작동하는가?
- 서버 로그에서 에러가 없는가?
이 항목들을 확인한 후 배포하면 동적 라우트 관련 404 에러를 대부분 방지할 수 있다.