image

meta 태그

태그
Next.jsHtmlDev
상세설명Next.js에서 동적 meta 태그 적용하기
작성일자2023.10.10

meta 태그

<meta> 태그는 HTML 문서의 <head>와 </head> 사이에 입력하는 특수 태그로서 해당 문서에 대한 정보인 메타데이터(metadata)를 정의할 때 사용합니다.

meta태그 종류

  • viewport - 반응 형 웹 구현
  • <meta name="viewport" content="width=device-width, initial-scale=1">

  • Keywords - 검색엔진에 의해 검색되는 단어 지정
  • <meta name="keywords" content="HTML, CSS, JavaScript">

  • Description - 검색 결과에 표시되는 문자 지정
  • <meta name="description" content="탐구한 것들을 기록하는 장소입니다." />

  • author - 웹 페이지의 소유자(또는 회사) 작성
  • <meta name="author " content="minsun">

    OpenGraph

    오픈그래프는 웹페이지가 소셜 미디어 또는 오픈그래프를 활용한 사이트로 공유될때 사용되어지는 정보이다.

    기본적으로 설정해야하는 og 메타태그

    <meta property="og:type" content="website">
    <meta property="og:url" content="https://example.com/page.html">
    <meta property="og:title" content="Content Title">
    <meta property="og:image" content="https://example.com/image.jpg">
    <meta property="og:description" content="Description Here">
    <meta property="og:site_name" content="Site Name">
    <meta property="og:locale" content="en_US">
    <!-- 다음의 태그는 필수는 아니지만, 포함하는 것을 추천함 -->
    <meta property="og:image:width" content="1200">
    <meta property="og:image:height" content="630">

    Naver 블로그, 카카오톡 미리보기 설정

    <meta property="og:title" content="콘텐츠 제목" /> 
    <meta property="og:url" content="웹페이지 URL" />
    <meta property="og:type" content="웹페이지 타입(blog, website 등)" />
    <meta property="og:image" content="표시되는 이미지" /> 
    <meta property="og:title" content="웹사이트 이름" /> 
    <meta property="og:description" content="웹페이지 설명" />

    트위터 미리보기 설정

    <meta name="twitter:card" content="트위터 카드 타입(요약정보, 사진, 비디오)" /> 
    <meta name="twitter:title" content="콘텐츠 제목" /> 
    <meta name="twitter:description" content="웹페이지 설명" /> 
    <meta name="twitter:image" content="표시되는 이미지 " />

    모바일 앱 미리보기 설정

    <--iOS-->
    <meta property="al:ios:url" content=" ios 앱 URL" />
    <meta property="al:ios:app_store_id" content="ios 앱스토어 ID" /> 
    <meta property="al:ios:app_name" content="ios 앱 이름" /> 
     
    <--Android-->
    <meta property="al:android:url" content="안드로이드 앱 URL" />
    <meta property="al:android:app_name" content="안드로이드 앱 이름" />
    <meta property="al:android:package" content="안드로이드 패키지 이름" /> 
    <meta property="al:web:url" content="안드로이드 앱 URL" />

    Next.js에서 meta 태그 적용하기

  • 정적 메타 태그
  • 개인적으로 Layout에서 화면 구성을 하고 싶어서 seo를 컴포넌트 화 시킨 후 Layout파일에 배치시킨 후 최상단인 _app.tsx에 Component 를 Layout로 감쌌다.

    // components/seo.tsx
    import Head from "next/head";
    
    export default function Seo() {
      return (
        <Head>
          <title>MinSun's Blog</title>
    		  <meta name="viewport" content="initial-scale=1.0, width=device-width" />
          <meta property="og:title" content={"MinSun's Blog"} />
          <meta property="og:site_name" content="MinSun's Blog" />
          <meta
            property="og:description"
            content={"탐구한 것들을 기록하는 장소입니다."}
          />
          <meta property="og:type" content="website" />
          <meta property="og:url" content={"https://min-sun.vercel.app/"} />
          <meta
            property="og:image"
            content={"https://images.unsplash.com/image"}
          />
          <meta property="og:image:width" content="1200" />
          <meta property="og:image:height" content="630" />
          <meta property="og:article:author" content="MinSun" />
        </Head>
      );
    }

    // components/Layout.tsx
    import Footer from "./Footer";
    import Header from "./Header";
    import Seo from "./Seo";
    
    export default function Layout({ children }) {
      return (
        <main>
          <Seo />
          <Header />
          <section>
            {children}
          </section>
          <Footer />
        </main>
      );
    }

    // _app.tsx
    import { useState, useEffect } from "react";
    import Layout from "@/components/Layout";
    
    export default function App({Component, pageProps: { session, ...pageProps },}) {
      return (
          <Layout>
             <Component {...pageProps} />
          </Layout>
      );
    }

    만약 적용안되면 next/head들을 _app.jsx로 옮기기

  • 다이나믹(동적) 메타 태그
  • Seo를 컴포넌트 화 시킨 후 각 페이지마다(pages 폴더 하위에 있는 파일 모두 다) return 바로 하위에서 불러오면 된다.

    해당 seo 컴포넌트는 title, desc, url, image 값이 있으면 적용한 값을 없으면 || 옆 defult 값이 적용되도록 되어있다.

    // components/seo.tsx
    import Head from "next/head";
    
    interface SeoType {
      title: string;
      desc?: string;
      url?: string;
      image?: string;
    }
    
    export default function Seo({ title, desc, url, image }: SeoType) {
      return (
        <Head>
          <title>{title ? title : "MinSun's Blog"}</title>
          <meta name="viewport" content="initial-scale=1.0, width=device-width" />
          <meta property="og:title" content={title ? title : "MinSun's Blog"} />
          <meta property="og:site_name" content="MinSun's Blog" />
          <meta
            property="og:description"
            content={desc || "탐구한 것들을 기록하는 장소입니다."}
          />
          <meta property="og:type" content="website" />
          <meta property="og:url" content={url || "https://min-sun.vercel.app/"} />
          <meta
            property="og:image"
            content={
              image ||
              "https://images.unsplash.com/image"
            }
          />
          <meta property="og:image:width" content="1200" />
          <meta property="og:image:height" content="630" />
          <meta property="og:article:author" content="MinSun" />
        </Head>
      );
    }

    동적으로 들어오는 값들은 getServerSideProps로 받아온 데이터만 쓸 수 있다.

    // index.tsx
    import Seo from "@/components/seo";
    
    export default function About() {
      return (
        <>
          <Seo title={`MinSun's Blog | About`} />
          <div>
            <div className="flex items-center justify-center gap-5 flex-col-reverse lg:flex-row">
                <p className="text-center lg:text-left">
                  About
                </p>
            </div>
          </div>
        </>
      );
    }
    
    
    // blog/[...id].tsx
    import axios from "axios";
    import { NextPageContext } from "next";
    import UseProperties from "libs/useProperties";
    import { BASE_URL, TOKEN } from "libs/config";
    import Seo from "@/components/seo";
    import { useRouter } from "next/router";
    
    export default function blockDetail({ propertiesData }: any) {
      const itemData = UseProperties(propertiesData);
    	const router = useRouter();
      return (
        <>
          <Seo
            title={itemData.name}
            url={BASE_URL + "/" + router.asPath}
            desc={itemData.description}
            image={propertiesData.cover?.external.url}
          />
          <p className="text-center lg:text-left">
             blogDetail
          </p>
        </>
      );
    }
    
    export async function getServerSideProps(context: NextPageContext) {
      const { query } = context;
      const axiosConfig = {
        headers: {
          ....
        },
      };
    
      const responseProperties = axios.get(
        `https://api.notion.com/v1/pages/${query.id}`,
        axiosConfig
      );
    
      const data = responseProperties.data;
      return {
        props: {data},
      };
    }

    후기

    동적 메타 태그적용 하면서 해맸던 점이 meta태그들이 중복으로 들어가는 문제 때문이었다.

    알고 보니 정적 메타 태그에서처럼 layout에 <Seo />를 주면 안된다. layout에 선언한 <Seo />가 선언 안 한 페이지들에는 default 값으로만 이루어진 meta태그들이 들어가는 줄 알았는데 그러면 선언한 페이지 meta와 layout meta 두 개가 중복되기 때문에 layout에있는 <Seo />를 삭제 해야 한다.

    meta 태그 적용 확인하는 방법

    카카오 공유 디버그

    image

    url에 해당 주소 넣으면 스크랩 결과, Open Graph 정보 보여줌

    만약 이미지 등 무언가를 변경했는데 적용이 안되면 캐시 초기화 후 디버그 다시하면된다.

    image