App Router 내장 sitemap (권장)
Next.js App Router에서는 app/sitemap.ts 파일 하나로 사이트맵이 자동 생성된다. 별도 패키지가 필요 없다.
정적 사이트맵
// app/sitemap.ts
import type { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
return [
{ url: "https://website.com", lastModified: new Date() },
{ url: "https://website.com/about", lastModified: new Date() },
{ url: "https://website.com/blog", lastModified: new Date() },
];
}
/sitemap.xml이 자동 생성된다. 별도 패키지 불필요.
동적 사이트맵
API나 DB에서 데이터를 가져와 URL을 동적으로 생성할 수 있다.
// app/sitemap.ts
import type { MetadataRoute } from "next";
export default async function sitemap(): MetadataRoute.Sitemap {
const res = await fetch("https://jsonplaceholder.typicode.com/posts");
const posts: { id: number }[] = await res.json();
const postUrls = posts.map((post) => ({
url: `https://website.com/post/${post.id}`,
lastModified: new Date(),
}));
return [
{ url: "https://website.com", lastModified: new Date() },
...postUrls,
];
}
대규모 사이트 - 사이트맵 분할
generateSitemaps를 사용하면 여러 사이트맵 파일로 분할할 수 있다.
// app/sitemap.ts
import type { MetadataRoute } from "next";
export async function generateSitemaps() {
return [{ id: 0 }, { id: 1 }, { id: 2 }];
}
export default async function sitemap({
id,
}: {
id: number;
}): Promise<MetadataRoute.Sitemap> {
const start = id * 5000;
const end = start + 5000;
const posts = await getPostRange(start, end);
return posts.map((post) => ({
url: `https://website.com/post/${post.id}`,
lastModified: post.updatedAt,
}));
}
/sitemap/0.xml, /sitemap/1.xml 형태로 생성된다.
Pages Router (레거시)
Pages Router를 쓰고 있다면 next-sitemap 패키지가 간편하다.
npm install next-sitemap
// next-sitemap.config.js
module.exports = {
siteUrl: "https://website.com",
generateRobotsTxt: true,
};
// package.json
{
"scripts": {
"postbuild": "next-sitemap"
}
}
구글 서치콘솔 제출
배포 후 구글 서치콘솔에서 사이트맵 URL을 제출하면 된다. 예전에 쓰던 google.com/ping?sitemap= 엔드포인트는 2023년에 deprecated 되었다.