:ledger: Next.js에서 SEO와 Metadata 설정 방법을 알아보자!

이전에 워드프레스 블로그를 운영하면서 SEO(검색 엔진 최적화)가 얼마나 중요한지 알게 되었다. SEO는 웹사이트의 가시성을 높이는 데 중요한 역할을 하고 그것은 곧 사용자가 웹 검색을 했을 때 나의 웹사이트가 얼마나 잘 노출되는 지 알 수 있었다. Next.js에서는 이러한 SEO를 향상시키기 위해 metadata API를 제공한다. 설정 방법에 대해 알아보자!

:one: Next.js에서의 SEO와 Metadata의 중요성

Next.js는 서버사이드 렌더링(SSR)을 지원하며, 이는 검색 엔진이 페이지를 효과적으로 크롤링할 수 있도록 도와준다. 그리고 각 페이지에 대한 메타데이터를 제공하여 검색 엔진에 해당 페이지의 내용을 알리는 것이 가능하다.

:pushpin: 1-1) MetaData의 역할

  1. 페이지 제목(title)
    • 검색 엔진과 브라우저 탭에 표시됨.
  2. 설명(description)
    • 검색 결과에서 페이지의 요약으로 나타냄.
  3. Open Graph 태그(og)
    • SNS에서 페이지를 공유할 때 표시되는 미리보기 정보임.
  4. 키워드(keywords)
    • 페이지에 대한 관련 검색어를 설정함 (최근에는 덜 사용됨)
  5. 기타 태그들:
    • robots, canonical, twitter, favicon, alternate 등 다양한 설정이 가능하다.

:two: Next.js에서 Metadata 설정하기

Next.js의 App Router에서는 각 페이지에 대해 Metadata를 쉽게 설정할 수 있다. 기본적으로 루트 폴더(src)의 layout.tsx에서 제공하고 있으며, 각 컴포넌트에서 export const metadata 형태로 메타데이터를 지정하면 된다.

  • metadata in page.tsx : 해당 page.tsx 컴포넌트에만 적용
  • metadata in layout.tsx : 해당 layout의 하위 요소에 모두 적용
  • 각 page에 metadata가 등록되는게 검색엔진에 좋은 점수를 받았던걸로 기억함
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
import Link from "next/link";

const geistSans = localFont({
  src: "./fonts/GeistVF.woff",
  variable: "--font-geist-sans",
  weight: "100 900",
});
const geistMono = localFont({
  src: "./fonts/GeistMonoVF.woff",
  variable: "--font-geist-mono",
  weight: "100 900",
});

// MetaData 설정 위치
export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        <header>
          <Link href={"/"}>홈으로가기</Link>
        </header>
        {children}
      </body>
    </html>
  );
}

:pushpin: 2-1) 기본적인 Metadata 설정

가장 기본적인 방법으로, 페이지마다 메타데이터를 설정하는 방법이다.

  • metadata 객체에서 title과 description을 정의할 수 있으며, 페이지 로딩 시 자동으로 HTML <head>에 반영된다.
  • 각 페이지마다 설정한다면 고유한 타이틀과 설명을 검색엔진에 제공할 수 있음
// app/about/page.tsx

// 각 페이지에다 넣어주면 됌
export const metadata = {
  title: 'WebSiteName - About 페이지',
  description: 'About 페이지 설명 넣어주면 됌',
};

export default function AboutPage() {
  return (
    <div>
      <h1>About Us</h1>
      <p>이 페이지는 About 페이지에 대한 소개 페이지입니다.</p>
    </div>
  );
}

:three: 동적으로 Metadata 설정

dynamic route를 갖고있는 route에서 동적으로 변경되는 params를 기반으로 metadat를 변경하고 싶을때 generateMetadata function을 사용하면 된다.

type Props = {
  params: {
    id: string;
  };
};

export function generateMetadata({ params }: Props) {
  return {
    title: `Detail 페이지 : ${params.id}`,
    description: `Detail 페이지 : ${params.id}`,
  };
}

const TestDetailPage = ({ params }: Props) => {
  return <div>Detail 페이지 : {params.id}</div>;
};

export default TestDetailPage;

:four: Open Graph (OG) 메타데이터 설정

웹사이트가 SNS에서 공유될 때, 미리보기 카드에 표시되는 정보는 Open Graph(OG) 메타데이터에 의해 결정된다. 이 정보는 카카오톡, 트위터 등 공유할 때 큰 영향을 미침

  • 설정해주는게 뭔가 더 신뢰성이 높아져서 잘 들어왔던 걸로 기억함
export const metadata = {
  title: '페이지 제목을 입력', // 이 페이지의 제목을 설정. 브라우저 탭과 검색 엔진에 표시될 내용.
  description: '페이지 설명을 입력', // 페이지의 요약 설명. 검색 엔진 결과에 표시될 내용.
  openGraph: {
    title: 'Open Graph에 표시될 페이지 제목 입력', // SNS에서 공유될 때 표시될 제목.
    description: 'Open Graph에 표시될 페이지 설명 입력', // SNS에서 공유될 때 표시될 설명.
    url: '페이지 URL을 입력', // 공유될 페이지의 정확한 URL.
    siteName: '웹사이트 이름을 입력', // 웹사이트 이름. Open Graph에서 표시될 사이트 이름.
    images: [
      {
        url: '이미지 URL을 입력', // 공유될 때 사용할 이미지의 URL.
        width: 800, // 이미지의 너비 (픽셀).
        height: 600, // 이미지의 높이 (픽셀).
        alt: '이미지 설명을 입력', // 이미지 대체 텍스트 (이미지가 로드되지 않을 때 표시).
      },
    ],
    locale: '언어 코드 입력 (예: ko_KR)', // 페이지의 언어 및 지역 설정.
    type: '콘텐츠 유형을 입력 (예: website)', // 페이지의 Open Graph 콘텐츠 유형. 일반적으로 'website'.
  },
};

:four: Robots 메타데이터 설정

네이버 웹마스터도구나 다음웹마스터도구 등에서 웹사이트의 robots 설정을 할 수 있는 것처럼 Next.js 에서는 특정 페이지에서도 robot 설정을 해줄 수 있음

  • robots 설정으로 검색 엔진에 의해 인덱싱되지 않거나 링크가 크롤링되지 않도록 설정할 수 있음.
  • 비공개 페이지나 검색 엔진에 노출되지 않아야 하는 페이지에 유용함.
export const metadata = {
  title: '비공개 페이지입니다만?',
  robots: 'noindex, nofollow',  // 이 페이지는 검색 엔진에 의해 인덱싱되지 않으며 링크를 따라가지 않음
};

:five: Favicon 설정

Favicon은 모든 페이지에서 공통적으로 노출되어야 하기에 루트에 있는 layout.tsx에 설정하면 좋다.

// app/layout.tsx

export const metadata = {
  icons: {
    icon: '/favicon.ico', // 브라우저 탭에 표시될 favicon
    apple: '/apple-touch-icon.png', // iOS 기기에서 홈 화면에 추가할 때 사용되는 아이콘
  },
};

:fire: 마무리

SEO는 웹사이트의 성능과 사용자 경험을 향상시킬 뿐만 아니라 검색 엔진에서 노출을 극대화해서 더 많은 사용자를 유입할 수 있게 도와준다. 현재 9/25일 부로 호스팅이 만료된 나의 워드프레스 블로그 https://rarrit.com을 운영하며 SEO 작업과 구글 서치콘솔, 구글 애널리틱스, 네이버 웹마스터도구, 다음 웹마스터도구 등을 사용해보며 SEO 작업이 얼마나 중요한지 알기에 Next.js에서도 잘 적용할 수 있도록 노력해야겠다.