Next.js
Next.js sitemap에 잘못된 URL이 들어갔을 때 찾아서 고치는 법
sitemap.xml을 열어봤더니 존재하지 않는 URL이나 www가 붙은 URL이 섞여 있었다. 원인을 좁히는 순서를 정리했다.
Google Search Console에서 "sitemap에 포함된 URL이 크롤링됐지만 색인되지 않음" 경고를 보다가 실제 sitemap.xml을 열어봤다. 거기서 예상치 못한 URL들이 나왔다. https://www.example.com이 들어가 있어야 할 자리에 http://localhost:3000이 있거나, 삭제한 포스트 URL이 여전히 남아 있는 경우다.
sitemap에서 잘못된 URL이 나오는 주요 원인
1. NEXT_PUBLIC_SITE_URL 환경변수가 잘못 설정됨
Next.js에서 sitemap을 동적으로 생성할 때 보통 환경변수로 기본 URL을 잡는다.
// app/sitemap.ts
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://example.com'
// ...
}
빌드 환경에서 이 변수가 없거나 잘못된 값이면 로컬 URL이나 fallback 값이 그대로 들어간다.
2. 삭제된 콘텐츠가 sitemap에 남아 있음
데이터베이스에서 소프트 딜리트를 쓰는 경우, sitemap을 생성하는 쿼리가 deletedAt IS NULL 조건을 빠뜨리면 삭제된 항목도 포함된다.
// 잘못된 예 - 삭제된 포스트가 포함될 수 있음
const posts = await db.post.findMany()
// 올바른 예
const posts = await db.post.findMany({
where: { publishedAt: { not: null }, deletedAt: null },
})
현재 sitemap 확인하는 법
# 실제 응답 확인
curl -s https://example.com/sitemap.xml | head -50
# URL 목록만 추출
curl -s https://example.com/sitemap.xml | grep -oP '(?<=<loc>)[^<]+'
# 잘못된 도메인이 들어 있는지 확인
curl -s https://example.com/sitemap.xml | grep -v 'example.com'
마지막 명령으로 example.com이 아닌 도메인이 나오면 환경변수나 기본값 문제다.
sitemap 캐시 확인
Next.js의 app/sitemap.ts는 기본적으로 빌드 시에 정적으로 생성된다. 새 배포 없이 내용이 바뀌길 기대한다면 revalidate를 설정해야 한다.
export const revalidate = 3600 // 1시간마다 재생성
또는 Vercel 대시보드에서 /sitemap.xml 캐시를 수동으로 퍼지할 수 있다.
수정 후 Search Console에 제출
sitemap을 수정하고 배포한 뒤에는 Search Console에서 다시 제출한다.
- Search Console → Sitemaps
- 기존 sitemap URL을 삭제하고 다시 추가
- 또는 "다시 제출" 버튼 클릭
크롤러가 새 sitemap을 처리하는 데 며칠이 걸릴 수 있다. 특정 URL을 빨리 색인에서 제거하려면 "삭제" 도구를 따로 사용해야 한다.