Next.js
Next.js sitemap.xml에 새 글이 빠지는 이유와 확인 방법
Next.js에서 sitemap을 정적으로 생성하면 빌드 시점의 글만 포함된다. 글을 발행한 뒤 사이트맵이 갱신됐는지 직접 확인하는 것이 필요하다.
새 글을 올리고 Google Search Console에서 색인 요청을 했는데, sitemap에 해당 URL이 없다는 걸 나중에 발견한 적이 있다. 글은 사이트에서 잘 보이는데 sitemap에는 빠져 있는 상황이었다.
정적 sitemap과 동적 sitemap의 차이
Next.js에서 sitemap을 구성하는 방법은 크게 두 가지다.
정적 public/sitemap.xml: 파일을 직접 작성하거나 빌드 스크립트로 생성한다. 빌드 시점의 URL만 포함되므로, 새 글을 올릴 때마다 다시 빌드하거나 파일을 수동으로 업데이트해야 한다.
app/sitemap.ts (동적 생성): App Router에서 지원하는 방식으로, 요청마다 또는 ISR 주기로 sitemap을 생성한다.
// app/sitemap.ts
import { MetadataRoute } from 'next'
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getAllPublishedPosts() // DB에서 직접 조회
return [
{
url: 'https://example.com',
lastModified: new Date(),
},
...posts.map((post) => ({
url: `https://example.com/posts/${post.slug}`,
lastModified: post.updatedAt,
})),
]
}
sitemap 확인 방법
배포 후 브라우저에서 /sitemap.xml에 접속하거나 curl로 직접 확인한다.
curl -s https://example.com/sitemap.xml | grep '<loc>'
# <loc>https://example.com/</loc>
# <loc>https://example.com/posts/첫번째-글</loc>
# ...
새로 올린 글의 URL이 목록에 있는지 확인한다. 없다면 아래 원인을 점검한다.
흔한 원인
정적 빌드 시 DB 접근 실패: 빌드 환경에서 데이터베이스에 연결할 수 없으면 글 목록을 가져오지 못하고 빈 sitemap이 생성된다. 빌드 로그에 에러가 찍히는지 확인한다.
next-sitemap 라이브러리 설정 누락: next-sitemap을 쓰는 경우 postbuild 스크립트에서 실행되므로, 빌드 후 이 스텝이 정상 완료됐는지 확인해야 한다.
// package.json
"scripts": {
"build": "next build",
"postbuild": "next-sitemap" // 이 줄이 없으면 sitemap이 생성되지 않는다
}
캐시 문제: output: 'export' 정적 내보내기 방식이라면 빌드를 다시 해야 반영된다. Vercel이나 Cloudflare Pages라면 배포 후 CDN 캐시가 만료될 때까지 기다리거나 퍼지(purge)해야 한다.
Google Search Console 제출
URL이 sitemap에 포함됐다면 Search Console에서 sitemap URL을 제출하거나, URL 검사 도구로 색인 요청을 넣는다. 색인이 반영되는 데는 며칠이 걸릴 수 있다.