Next.js 동적 라우팅에서 메타데이터 생성하기

힘센캥거루·2024-12-16

검색엔진 최적화를 위해 metadata를 어떻게 넣을까 검색을 하다가 velog에서 Doeunnkimm님의 글을 보고 메타데이터를 정적으로 주입하고 있었다.

포스팅을 시작하니 동적 라우팅에서 각 포스트마다 다른 metadata를 넣고 싶었다.

그래서 복습하는 겸 한번 써본다.

1. 코드

먼저 위의 velog에서 구한 코드는 아래와 같다.

getMetadata.tsx
// 먼저 기본적으로 필요한 메타 데이터를 설정한다.
const META = {
  title: "블로그 제목",
  siteName: "사이트이름",
  description: "블로그에 대한 대략적인 설명",
  keyword: ["배열", "형태의", "키워드"],
  url: "https://sample.kr",
  googleVerification: "xxx", //구글 서치콘솔
  naverVerification: "xxx", //네이버 서치어드바이저
  ogImage: "https://sample.kr/assets/thumbnail.png", // 썸네일,
} as const;
 
// getMetadata 함수를 이용해 metadata를 설정한다.
// 아래 함수 하나면 대부분의 사이트에서 필요한 metadata는 끝난다.
export const getMetadata = (metadataProps?: generateMetadataProps) => {
  const { title, description, asPath, ogImage } = metadataProps || {};
 
  const TITLE = title ? `${title} | 블로그 제목` : META.title;
  const DESCRIPTION = description || META.description;
  const PAGE_URL = asPath ? asPath : "";
  const OG_IMAGE = ogImage || META.ogImage;
 
  const metadata: Metadata = {
    metadataBase: new URL(META.url),
    alternates: {
      canonical: PAGE_URL,
    },
    title: TITLE,
    description: DESCRIPTION,
    keywords: [...META.keyword],
    openGraph: {
      title: TITLE,
      description: DESCRIPTION,
      siteName: TITLE,
      locale: "ko_KR",
      type: "website",
      url: PAGE_URL,
      images: {
        url: OG_IMAGE,
      },
    },
    verification: {
      google: META.googleVerification,
      other: {
        "naver-site-verification": META.naverVerification,
      },
    },
    twitter: {
      title: TITLE,
      description: DESCRIPTION,
      images: {
        url: OG_IMAGE,
      },
    },
    icons: {
      icon: "/favicon/favicon.ico",
    },
  };
 
  return metadata;
};

그리고 해당 코드를 layout.tsx에서 호출해서 사용한다.

metadata를 생성하고 이를 export 해주면 홈페이지에 대한 메타 데이터를 생성한다.

layout.tsx
import "./globals.css";
import { Metadata } from "next";
import { getMetadata } from "@/utils/getMetadata";
 
// 메타데이터 객체를 내보냄
export const metadata: Metadata = {
  // 전개연산자 ..,를 이용해 객체를 가져온다.
  ...getMetadata(),
 
  // 만일 다른 제목을 쓰고 싶다면 아래와 같이 하면 된다.
  ...getMetadata({ title: "다른제목" }),
};
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <body className="h-svh">
        <div>
          <div className="mx-auto max-w-7xl p-6 lg:px-8">{children}</div>
        </div>
      </body>
    </html>
  );
}

자신의 홈페이지로 들어가 F12키를 누른 뒤, <head> 태그를 살펴보면 meatadata를 확인할 수 있다.

메타디에터

2. 동적 라우팅과 metadata

동적 라우팅에서는 generateMetadata 함수를 이용했다.

이에 대한 설명은 위의 블로그나 Nextjs 공식문서에 있다.

메타데이터

이 글의 핵심은 metadata를 만들 때 동적 라우팅에 이용되는 객체를 이용할 수 있다는 것이다.

나는 slug와 글 목록이 있는 Json을 이용해 메타 데이터를 만들었다.

layout.tsx
export async function generateMetadata({
  params,
}: {
  params: { slug: string };
}) {
  const { slug } = await params;
 
  //카테고리 목록 json을 호출함
  const categoryData = fs.readFileSync(categoryJsonPath, "utf-8");
  const categorys: postCardFrontMatter[] = JSON.parse(categoryData);
 
  // 현재의 slug와 url이 동일한 것을 1개 찾아 반환함.
  const baseMetaData = categorys.find(
    (category) => category.postUrlPath === slug
  );
 
  //이것을 이용해 메타데이터 설정
  const metadata: Metadata = {
    ...getMetadata({
      title: baseMetaData?.data.title,
      description: baseMetaData?.data.description,
      asPath: `https://earthscience.kr/posts/${slug}`,
      ogImage:
        baseMetaData?.data.thumbnail &&
        `https://earthscience.kr/posts/${slug}/${baseMetaData.data.thumbnail}`,
    }),
  };
  return metadata;
}

3. 후기

보통 페이스북의 공유 디버거를 많이들 활용한다.

그런데 나는 페이스북 아이디가 없어서 그냥 카톡으로 테스트를 해보았다.

단점은 이미지가 뜨기까지 시간이 좀 오래 걸린다.

카톡 테스트

처음에는 사진이 보이지 않다가 다음날 다시 들여다보니 사진이 잘 뜬다.

하나씩 만들어가는 재미가 있는것 같다.