마이그레이션을 위해 각 페이지들은 TanStack Start/Router에 맞게 다 작업했고, SEO를 위해 만든 웹 페이지기도 하니 이제 렌더링된 페이지의 meta 태그랑 sitemap.xml를 작업이 남은 상황이다.
Next.js는 검색엔진 최적화나 페이지의 메타데이터를 예쁘게 정리해둔 타입에 맞게 담아주면 정말 알잘딱깔센하게 <head> 태그 안에 담아주는데[1], TanStack Start에서는 아래와 같이 직접 meta 태그나 link 태그 등을 하나하나 직접 빚어내야한다.
export const Route = createFileRoute("/articles/$articleId")({
loader: ({ params: { articleId } }) => fetchArticle({ data: { articleId } }),
head: (ctx) => {
// NOTE: 적당히 생략
return {
meta: [
{ name: "title", content: title },
{ name: "description", content: description },
{ name: "keywords", content: keywords },
{ name: "og:title", content: title },
{ name: "og:type", content: "article" },
{ name: "og:author", content: post.author.nick },
{ name: "og:image", content: "/ci/logo.svg" },
{ name: "og:url", content: fullUrl },
{ name: "og:description", content: description },
{ name: "og:locale", content: "ko_KR" },
{ name: "og:site_name", content: defaultTitle },
],
};
},
component: RouteComponent,
});
그러면 Next.js는 어떻게 각 페이지 컴포넌트 모듈에서 async function generateMetadata() 함수나 metadata 객체를 읽어서 어떻게 처리할까? 궁금해져서 찾아보았다.
Next.js 코드 속 src/lib/metadata에서는 모듈에 있는 메타데이터 정의를 읽고 generateMetadata()면 실행해서 resolve하는 resolve-metadata.ts부터, metadata.tsx를 통해 어떻게 Metadata 타입을 가지고 OpenGraph, Apple, Twitter를 비롯해 각 타입에 맞는 <meta> 태그를 만들어주는지 알 수 있다. OpenGraph라던가 각 세부 항목에 대해선 generate/opengraph.tsx 파일 등을 보면 이해할 수 있다.
이 방식이 꽤 괜찮게 느껴져서 자고 일어나선 해당 코드를 차용해서 새 코드베이스에서도 그대로 활용할 수 있게 만들어보려고 한다.