Next.js 14 에서 메타데이터 적용하기

D uuu·2024년 7월 11일
0

Next.js14 프로젝트

목록 보기
11/11

next.js 로 구현하면서 이번에는 꼭 메타데이터를 적용해봐야겠다는 생각이 있었다!
왜냐하면 초보 개발자 입장에서는 글로만 접하는 SEO 가 도저히 이해가 안됐기 때문이다.

메타데이터는 뭐고 그게 왜 SEO 에 도움이 되는지 등 해보지 않고서는 반쪽자리 지식이라는 생각이 들었고, 때마침 next.js 14 로 프로젝트를 구현하기로 결정하면서 next.js 14 의 업그레이드 된 기능을 사용해 동적 메타데이터를 구현해 SEO 최적화 작업을 해보기로 했다😆

먼저 비교사진😎 (메타데이터 적용 전 & 후)

메타데이터를 적용하기 전과 후 모습을 비교해봤을때, 확실히 이미지와 더불어 사이트 정보를 제공하니 더 눈길이 가고 어떤 사이트인지 확실히 알 수 있다.
따라서 메타데이터를 잘 사용하면 사람들의 시선을 더 끄는 사이트로 만들 수 있고, 유입이 많아지면 그에 따른 기대 수익이 생겨날 수 있으니 매우 중요한 기능이라 할 수 있다.

메타태그 작성하기

메타 태그를 설정하는 방법으로는 HTML 코드를 작성할때 <head> 태그에 내용을 입력해주면 되는데, next.js 는 metadata 기능을 제공해주기 때문에 아래와 같이 일일이 작성해주지 않아도 된다!

<head>
<title>먹기록 - 매일 다른 음식을 기록하고 공유하세요</title>
<meta name="description" content="먹기록은 매일 먹은 음식과 음식점을 기록하고, 팔로우한 사람들과의 음식 일상을 공유하는 사이트입니다. 다양한 음식 경험을 기록하며 하루의 특별한 순간을 기억하세요."/>
<meta name="keywords" content="음식,일상,일기,공유,추억,맛집"/>
<link rel="canonical" href="https://omuk-beta.vercel.app"/>
<meta name="naver-site-verification" content="26f9b328438f88ca40b4d18c011e8a5cd0311d05"/>
<meta property="og:title" content="먹기록 - 매일 다른 음식을 기록하고 공유하세요"/>
<meta property="og:description" content="먹기록은 매일 먹은 음식과 음식점을 기록하고, 팔로우한 사람들과의 음식 일상을 공유하는 사이트입니다. 다양한 음식 경험을 기록하며 하루의 특별한 순간을 기억하세요."/>
<meta property="og:url" content="https://omuk-beta.vercel.app"/>
<meta property="og:site_name" content="먹기록 - 매일 다른 음식을 기록하고 공유하세요"/>
<meta property="og:locale" content="ko_KR"/><meta property="og:image" content="https://s3-omuk-images.s3.ap-northeast-2.amazonaws.com/main.png"/>
<meta property="og:type" content="website"/>
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:title" content="먹기록 - 매일 다른 음식을 기록하고 공유하세요"/>
<meta name="twitter:description" content="먹기록은 매일 먹은 음식과 음식점을 기록하고, 팔로우한 사람들과의 음식 일상을 공유하는 사이트입니다. 다양한 음식 경험을 기록하며 하루의 특별한 순간을 기억하세요."/>
<meta name="twitter:image" content="https://s3-omuk-images.s3.ap-northeast-2.amazonaws.com/main.png"/>
</head>

metadata

이런식으로 metadata 를 사용하면 title, description 등을 설정할 수 있다.
이런 metadata 는 page, layout 에서만 작성이 가능하고 서버 컴포넌트에서만 작성 할 수 있다. 즉, 'use client' 로 작성한 컴포넌트는 사용이 불가능하다!

export const metadata: Metadata = {
    title: {
        template: '%s | MUKIROK',
        default: 'MUKIROK',
    },
     description: '먹기록은 매일 먹은 음식을 기록하고, 팔로우한 사람들과의 음식 일상을 공유하는 사이트입니다. 다양한 음식 경험을 기록하며 하루의 특별한 순간을 기억하세요.',
};

동적 메타데이터 생성하기

위와 같이 metadata 를 설정하면 모든 페이지에서 동일한 title 과 description 이 보여지는데, 페이지 별로 콘텐츠에 따라 메타데이터도 다르게 표시하고 싶을 수 있다. 그때 사용하는 것이 바로 generateMetadata 함수이다.

음식점 별로 title 에는 음식점 이름을 description 에는 음식점 소개를 표시하고 싶었기에 나는 동적 메타데이터를 이용해 아래와 같이 구현했다.

요런식으로 음식점을 클릭할때마다 '음식점 이름 | 먹기록' 으로 음식점 이름이 바뀌는 걸 볼 수 있다👇👇

const getDetail = async (id: string) => {
    const response = await fetch(`https://place.map.kakao.com/m/main/v/${id}/`);

    if (!response.ok) {
        throw new Error('데이터 가져오기 실패');
    }
    return response.json();
};

export const generateMetadata = async ({ params: { id } }: ParamType) => {
    const post = await getDetail(id);

    return {
        title: post.title,
        description : post.content
    };
 };

유연하게 작성해보자

지금까지는 메타데이터를 title, description 만 작성했는데, 소셜 네트워크 등에 사이트를 공유할때 사이트 이미지와 소개글이 나타나도록 Open Graph 을 추가해보자
Open Graph 을 등록하면 아래와 같이 공유할때 메인 이미지와 블로그 제목이 함께 보내져 어떤 글인지 한눈에 알 수 있다.

기본 META 데이터 상수로 작성하기

이 부분부터 블로그 내용(Reference 참고)을 많이 참고했다.
기본적인 meta 데이터를 상수로 작성했다.
이는 RootLayout 에 들어갈 메타데이터로 대표 이미지와 배포 url 등을 적어줬다.
나같은 경우에는 대표 이미지를 aws s3 에 업로드 해놓고 해당 url 을 넣어줬다.

export const META = {
    title: '먹기록 - 매일 다른 음식을 기록하고 공유하세요',
    description:
        '먹기록은 매일 먹은 음식을 기록하고, 팔로우한 사람들과의 음식 일상을 공유하는 사이트입니다. 다양한 음식 경험을 기록하며 하루의 특별한 순간을 기억하세요.',
    keyword: ['음식', '일상', '일기', '공유', '추억', '맛집', '맛집추천'],
    siteName: 'MUKIROK | 먹기록',
    url: 'https://omuk-beta.vercel.app',
    ogImage: 'https://s3-omuk-images.s3.ap-northeast-2.amazonaws.com/main.png',
    naverVerification: 'naver 검증 코드 작성',
    googleVerification: 'google 검증 코드 작성',
};

구글 서치콘솔 https://search.google.com/search-console/about
네이버 서치어드바이저

metadata 를 만드는 함수 작성하기

기본적인 meta 데이터를 만들었으니 이제 메타데이터를 생성해주는 함수를 만들었다.
getMetadata 함수에는 동적으로 생성 될 메타데이터 정보를 위해 title, description, image, path 를 props 받도록 했다.

만약, props 이 없다면 기본 META 데이터를 사용하도록 했다.
여기서 openGraph 속성을 넣어줬다.

export const getMetadata = (metadataProps?: MetaDataType) => {
    const { title, description, ogImage, asPath } = metadataProps || {};

    const TITLE = title ? `${title} | 먹기록` : META.title;
    const DESCRIPTION = description || META.description;
    const PAGE_URL = asPath || META.url;
    const OG_IMAGE = ogImage || META.ogImage;

    const metadata: Metadata = {
        metadataBase: new URL(META.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,
            },
        },
    };

    return metadata;
};

적용하기

위에서 하드코딩 했던 로직을 getMetadata 로 수정해줬다.
그러고 나서 카카오톡에 공유해보니 아래와 같이 메인 표지와 음식점 별로 사이트에 접속했을때의 미리보기가 잘 구현된 걸 볼 수 있다!!😎

app/layout.tsx

export const generateMetadata = () => {
    return getMetadata();
};
app/[id]/layout.tsx

export const generateMetadata = async ({ params: { id } }: ParamType) => {
    const post = await getDetail(id);

    return getMetadata({
        title: post.basicInfo?.placenamefull,
        description: post.basicInfo?.category.catename,
        ogImage: post.basicInfo?.mainphotourl,
        asPath: `/${id}`,
    });
};

Reference !!

profile
배우고 느낀 걸 기록하는 공간

0개의 댓글