Next.js APP에서 사이트맵 동적으로 생성하기
개발 이야기위 이미지는 그냥 퍼온 짤..
보통의 사이트맵은 sitemaps.org의 프로토콜에 맞춰 아래와 같은 형태로 작성한다.
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://aaa.com/</loc>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://aaa.com/signin/</loc>
<changefreq>daily</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>https://aaa.com/rewards/</loc>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://aaa.com/policies/privacy/</loc>
<changefreq>daily</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://aaa.com/policies/terms/</loc>
<changefreq>daily</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://aaa.com/blog/</loc>
<changefreq>daily</changefreq>
<priority>0.7</priority>
</url>
</urlset>
참고로 Next.js에서 그냥 위 처럼 정적 사이트맵을 사용하려면, app/sitemap.xml
에다가 저거 복붙하면 된다.
남들 다 아는 내용 한줄 한줄 해석해보자.
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
이 부분이야 사이트맵을 XML 포멧으로, 그리고 sitemaps의 스키마대로 작업한다는 부분이고,
<url>
<loc>https://aaa.com/</loc>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<loc>
페이지의 URL. 반드시 https:// 또는 http:// (이제 이건 좀 쓰지 마라) 로 시작해야한다. 2,048자 까지만 지원한다. 2048자 넘는 URL을 가진 페이지라면 생각만 해도 어질어질하다..
<lastmod>
이 페이지의 마지막 수정일. W3C의 Datetime 포멧으로 작성한다. 시간은 YYYY-MM-DD 식으로 제외해도 된다. 이 수정 시간은 페이지가 마지막으로 수정된 시간을 의미하며, 사이트맵이 작성된 시간을 의미하지 않음에 유의.
<changefreq>
업데이트 빈도. 이 페이지가 보통 얼마 간격으로 업데이트 되는지를 나타낸다. always | hourly | daily | weekly | monthly | yearly | never
를 넣을 수 있다. always
는 문서가 접속할 때 마다 업데이트 된다는 것을 의미하며, never
는 영영 업데이트 되지 않을 아카이브된 문서 등에 사용한다. 이 changefreq 값은 그냥 힌트고, 강제성이 없다. 검색엔진 크롤러는 제멋대로 행동할것이다.
<priority>
다른 URL 대비 얼마나 중요한 페이지인지를 나타낸다. 0.0
에서 1.0
사이로 적으며, 기본값은 0.5
다. 다른 웹 사이트의 페이지와는 아무 연관성이 없으므로, 검색엔진 노출 순위와 아무 상관 없다. 또한 모든 값들을 1.0
으로 해봐야 SEO에 도움이 전혀 되지 않는다. 상대값이다.
자 그럼...
내 웹 사이트가 작을때는 이거 직접 입력하는게 큰 문제가 되지 않을 수 있다. 근데 이게 페이지가 한두개가 아니라면? 심지어 이 블로그 처럼 글을 쓸 때 마다 페이지가 늘어난다면? 글 쓸 때 마다 사이트맵 수정할건가? 개발자는 최대한 게을러야 한다. 컴퓨터를 노예로 부려서 일을 쉽고 편하게 하는 방법을 연구하는 사람이 개발자다.
이제 Next.js의 동적 사이트맵 생성 기능을 이용해보자.
Next.js 공식 문서의 Generate a Sitemap 문서을 참조하자.
import { MetadataRoute } from 'next';
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: 'https://acme.com',
lastModified: new Date(),
},
{
url: 'https://acme.com/about',
lastModified: new Date(),
},
{
url: 'https://acme.com/blog',
lastModified: new Date(),
},
];
}
뭐야 이게 다네.. 하면 좀 별로고.. 적용하면서 알아낸 점들을 공유해본다.
- public/sitemap.xml이 있을 경우 app/sitemap.ts 는 동작하지 않는다. public에 남은 찌꺼기를 지워라.
- react-query 같은 클라이언트 펑션은 사용할 수 없다. 너무 싫고, 구리구리한 fetch를 써야한다.
- changeFrequency와 priority는 아직 지원하지 않는다. 어떤 착한 형이 PR 을 만들어놓은게 보인다.
- 공식문서에 보면, 여러개의 사이트맵을 동시생성할 수 있는 기능을 만드는 중이라고 한다. 여기랑 여기서 그 흔적을 찾을 수 있었다. generateSitemaps() 라는 함수를 한창 만드는 중인듯.
내 블로그 글을 땡겨와서 사이트맵으로 만드는 코드는 다음과 같다.
export const getPosts = () => {
return fetch(`${process.env.NEXT_PUBLIC_BASE_FETCH_URL}/api/blog/posts`, {
next: { revalidate: 60 * 10 }, // 10분 캐시
})
.then((res) => {
if (!res.ok) {
return Promise.reject();
}
return res.json();
})
.catch(() => {
return [];
});
};
const Sitemap = async (): Promise<MetadataRoute.Sitemap> => {
const posts: FBBlogPost[] = await getPosts();
const blogPosts = posts.map((post) => ({
url: `https://miriya.vercel.app/blog/${post.id}`,
lastModified: new Date(),
}));
return [
{
url: 'https://miriya.vercel.app',
lastModified: new Date(),
},
{
url: 'https://miriya.vercel.app/profile',
lastModified: new Date(),
},
{
url: 'https://miriya.vercel.app/idols',
lastModified: new Date(),
},
{
url: 'https://miriya.vercel.app/cameras',
lastModified: new Date(),
},
{
url: 'https://miriya.vercel.app/pentax',
lastModified: new Date(),
},
{
url: 'https://miriya.vercel.app/pentax/slr',
lastModified: new Date(),
},
{
url: 'https://miriya.vercel.app/pentax/dslr',
lastModified: new Date(),
},
{
url: 'https://miriya.vercel.app/mycar',
lastModified: new Date(),
},
{
url: 'https://miriya.vercel.app/minihome',
lastModified: new Date(),
},
...blogPosts,
];
};
export default Sitemap;
async로 데이터 불러와서 돌리다보니 Promise 한꺼풀 씌워준거 외에 특이사항은 없다.
아직 사이트 복잡도가 낮아서 뭐 강좌라고 하기에도 뭐한걸 적게 되었는데, 이후에 기능이 추가되는대로 업데이트 할 예정이다. 이 문서를 작성하는 시점에서 Next.js 버전은 v13.4.3-canary.0 이다.