마이그레이션을 위해 각 페이지들은 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 파일 등을 보면 이해할 수 있다.

이 방식이 꽤 괜찮게 느껴져서 자고 일어나선 해당 코드를 차용해서 새 코드베이스에서도 그대로 활용할 수 있게 만들어보려고 한다.


  1. https://nextjs.org/docs/app/getting-started/metadata-and-og-images ↩︎

4

If you have a fediverse account, you can reply to this note from your own instance. Search https://hackers.pub/ap/notes/0199bf15-bc63-79b1-8139-9445ee2c10b5 on your instance and reply to it.