Next.js
Next.js sitemap을 수동 파일로 둘지 동적 라우트로 만들지 정한 기준
글이 자주 추가되는 블로그에서 sitemap.xml을 정적 파일과 동적 라우트 중 어디에 둘지 비교한 기록이다.
처음에는 public/sitemap.xml 하나면 충분해 보였다
블로그 글이 몇 개 없을 때는 public/sitemap.xml을 손으로 고쳐도 괜찮았다. 문제는 글을 발행할 때 sitemap 수정이 자꾸 빠졌다는 것이다. 검색 노출이 바로 달라지는 건 아니지만, 새 글 URL을 따로 제출하는 일이 반복됐다.
그래서 sitemap을 정적 파일로 둘지, Next.js 라우트에서 동적으로 만들지 기준을 정했다.
정적 파일이 편한 경우
페이지 수가 적고 거의 바뀌지 않는 사이트라면 정적 파일이 단순하다.
<url>
<loc>https://example.com/about</loc>
<changefreq>monthly</changefreq>
</url>
장점은 배포 결과가 눈에 보이고, 서버 로직이 필요 없다는 점이다. 회사 소개 페이지나 포트폴리오처럼 URL이 고정된 사이트에는 아직도 이 방식이 편하다.
동적 라우트가 나은 경우
글, 상품, 문서처럼 데이터가 계속 늘어나면 누락이 더 큰 문제가 된다. 이때는 DB나 파일 목록에서 URL을 만들어 주는 편이 낫다.
export async function GET() {
const posts = await getPublishedPosts();
const body = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${posts.map((post) => ` <url><loc>https://example.com/posts/${post.slug}</loc></url>`).join('
')}
</urlset>`;
return new Response(body, {
headers: {
'Content-Type': 'application/xml; charset=utf-8',
},
});
}
내가 헷갈렸던 부분은 Content-Type이었다. 브라우저에서는 문자열이 보여서 괜찮아 보였지만, XML로 내려가도록 헤더를 명확히 주는 게 좋았다.
비교해서 정한 기준
| 기준 | 정적 sitemap | 동적 sitemap |
|---|---|---|
| URL 변경 빈도 | 낮을 때 적합 | 높을 때 적합 |
| 구현 난이도 | 낮음 | 약간 있음 |
| 누락 가능성 | 직접 관리하면 있음 | 데이터 기준이라 낮음 |
| 장애 범위 | 파일 배포 문제 | DB/API 문제 영향 |
내가 선택한 방식
블로그처럼 글이 계속 추가되는 곳은 동적 라우트로 두는 쪽이 맞았다. 대신 sitemap 생성이 DB에 너무 자주 부담을 주지 않도록 캐시 시간을 짧게라도 둔다.
export const revalidate = 3600;
마무리 기준은 단순하다. URL이 손으로 셀 수 있을 만큼 적으면 정적 파일, 발행 작업과 함께 계속 늘어나면 동적 생성. sitemap은 화려한 기능이 아니라 빠뜨리지 않는 운영 장치에 가깝다.