728x90
728x90

메타데이터(Metadata) 추가하기

들어가며

  • Next.js에서 컴포넌트에 메타데이터(Metadata)를 추가하는 방법을 정리해본다.

 

메타데이터(Metadata)

  • 웹페이지에 대한 추가 정보를 제공하는 데이터
  • 주로 HTML 문서의 @<head>@ 태그 안에 포함되어 있으며, 검색 엔진 최적화(SEO), 소셜 미디어 공유, 브라우저 설정 등 여러 목적으로 사용된다.

 

메타데이터  추가하기

  • 정적 페이지(Static Page) 동적 페이지(Dynamic Page)에 메타데이터를 추가하는 방법이 다르다.

 

정적 페이지

방법

  • 페이지나 레이아웃 파일에 @metadata@라는 이름의 상수를 내보내는 방식을 통해 메타데이터를 설정할 수 있다.
export const metadata = {
  title: 'All Meals',
  description: 'Browse the delicious meals shared by our vibrant community.',
};

 

  • 최상위 @layout.js@ 파일에 기본 메타데이터를 설정하면, 해당 레이아웃으로 감싸진 모든 페이지에 이 메타데이터가 적용된다.
  • 개별 페이지에서 메타데이터를 설정하면, 그 페이지의 메타데이터가 우선 적용된다.

 

사용 예

import { Suspense } from 'react';
import Link from 'next/link';

import classes from './page.module.css';
import MealsGrid from '@/components/meals/meals-grid';
import { getMeals } from '@/lib/meals';

export const metadata = {
  title: 'All Meals',
  description: 'Browse the delicious meals shared by our vibrant community.',
};

async function Meals() {
  const meals = await getMeals();

  return <MealsGrid meals={meals} />;
}

export default function MealsPage() {
  return (
    <>
      <header className={classes.header}>
        <h1>
          Delicious meals, created{' '}
          <span className={classes.highlight}>by you</span>
        </h1>
        <p>
          Choose your favorite recipe and cook it yourself. It is easy and fun!
        </p>
        <p className={classes.cta}>
          <Link href="/meals/share">Share Your Favorite Recipe</Link>
        </p>
      </header>
      <main className={classes.main}>
        <Suspense
          fallback={<p className={classes.loading}>Fetching meals...</p>}
        >
          <Meals />
        </Suspense>
      </main>
    </>
  );
}

개발자 도구에서 추가한 메타데이터를 확인할 수 있다.

 

동적 페이지

방법

  • 상수나 변수를 사용하여 메타데이터를 내보내지 않고, @generateMetadata@라는 비동기 함수를 내보내는 방식을 통해 메타데이터를 설정할 수 있다.
    • Next.js는 다른 메타데이터를 찾지 못하면 이 함수를 실행하여 메타데이터 객체를 반환한다.
    • 페이지 컴포넌트가 받는 것과 동일한 데이터를 @props@로 받는다.
export async function generateMetadata({ params }) {
  const meal = getMeal(params.mealSlug);

  if (!meal) {
    notFound();
  }

  return {
    title: meal.title,
    description: meal.summary,
  };
}

 

사용 예

// localhost:3000/meals/my-meal
import Image from 'next/image';
import { notFound } from 'next/navigation';

import { getMeal } from '@/lib/meals';
import classes from './page.module.css';

export async function generateMetadata({ params }) {
  const meal = getMeal(params.mealSlug);

  if (!meal) {
    notFound();
  }

  return {
    title: meal.title,
    description: meal.summary,
  };
}

export default function MealDetailsPage({ params }) {
  const meal = getMeal(params.mealSlug); // mealSlug 대신 다른 단어를 사용해도 된다.

  // 잘못된 URL에 접근할 경우 404 Not Found
  if (!meal) {
    notFound();
  }

  // 항목 끝 마다 줄 바꾸기
  meal.instructions = meal.instructions.replace(/\n/g, '<br />');

  return (
    <>
      <header className={classes.header}>
        <div className={classes.image}>
          <Image src={meal.image} alt={meal.title} fill />
        </div>
        <div className={classes.headerText}>
          <h1>{meal.title}</h1>
          <p className={classes.creator}>
            by <a href={`mailto: ${meal.creator_email}`}>{meal.creator}</a>
          </p>
          <p className={classes.summary}>{meal.summary}</p>
        </div>
      </header>
      <main>
        <p
          className={classes.instructions}
          dangerouslySetInnerHTML={{
            // HTML의 코드를 직접 삽입 (XSS 공격에 취약)
            __html: meal.instructions,
          }}
        ></p>
      </main>
    </>
  );
}

각 페이지 별로 페이지 제목이 변경되는 것과 개발자 도구를 통해 메타 데이터가 추가된 것을 확인할 수 있다.

 

참고 사이트

 

Optimizing: Metadata | Next.js

Use the Metadata API to define metadata in any layout or page.

nextjs.org

 

728x90
728x90