Yeogi(여기) 웹사이트를 리팩터링하면서 메타데이터를 건들게 되었습니다.
메타데이터가 무엇인지, 메타데이터를 잘 설정했을 때 어떤 이점이 있는지에 대해서는 어느 정도 알고 있었지만 해당 PR을 올리면서 제가 얼마나 메타데이터를 얕잡아보고 있었는지 깨닫는 기회가 되었습니다.
그래서 메타데이터에 대해 알아보려고 합니다.
어디서부터 알아볼까 고민하다가 우선은 메타데이터에 넣을 수 있는 옵션들에는 어떤 것들이 있는지, 그리고 각각의 옵션들의 값들에 따른 결과에 대해서부터 시작하겠습니다 😊
메타데이터는 웹페이지에 대한 추가 세부 정보를 제공합니다.
메타데이터 정보는 페이지를 방문하는 사용자에게 보이지 않으며 페이지의 HTML, 일반적으로 <head>
요소 내에 내장되어 백그라운드에서 작동합니다.
메타데이터는 웹페이지의 콘텐츠를 더 잘 이해해야 하는 검색 엔진 및 기타 시스템에 필수적인 정보입니다.
메타데이터는 웹페이지의 SEO를 향상하는 데 중요한 역할을 하며, 검색 엔진과 소셜 미디어 플랫폼에서 더 쉽게 접근하고 이해할 수 있게 만듭니다.
적절한 메타데이터는 검색 엔진이 웹페이지를 효과적으로 색인화하여 검색 결과에서 순위를 높이는 데 도움이 됩니다. 또한 Open Graph와 같은 메타데이터는 소셜 미디어에서 공유된 링크의 모양을 개선하여 사용자에게 콘텐츠를 더 매력적이고 유익하게 만듭니다.
title은 브라우저 탭에 표시되는 웹페이지의 제목을 의미합니다.
검색 엔진이 웹페이지의 내용을 이해하는 데 도움이 되므로 SEO에 중요하며 설정한 제목이 브라우저 탭에 보여지게 됩니다.
// head output
<title>Page Title</title>
// sample
export const metadata: Metadata = {
title: '...',
}
// example
export const metadata: Metadata = {
title: "Record Your Trip"
}
설명 항목에 내용을 작성하게 되면 웹페이지 콘텐츠에 대한 간략한 개요를 제공할 수 있으며 검색 엔진 결과에 표시됩니다.
// head output
<meta name="description" content="A brief description of the page content." />
// sample
export const metadata: Metadata = {
title: '...',
description: '...',
}
// example
export const metadata: Metadata = {
title: "Record Your Trip",
description: "여기에 여행을 기록하세요"
}
키워드 설정 시 웹페이지 콘텐츠와 관련된 키워드가 포함되어 있어 검색 엔진이 페이지를 색인하는 데 도움이 됩니다.
// head output
<meta name="keywords" content="keyword1, keyword2, keyword3" />
// sample
export const metadata: Metadata = {
title: '...',
description: '...',
keywords: []
}
// example
export const metadata: Metadata = {
title: "Record Your Trip",
description: "여기에 여행을 기록하세요",
keywords: ["여기", "yeogi", "여행", "기록", "여행 기록", "trip", "vacation", "travel", "travel logs"]
}
과거에는 검색 엔진 최적화(SEO)에서 중요한 역할을 했지만, 현재는 대부분의 주요 검색 엔진(특히 Google)에서 더 이상 keywords 메타태그를 사용하지 않거나 그 중요성을 거의 부여하지 않는다고 합니다.
여전히 포함하는 것이 해롭지는 않으며, 특히 페이지의 주제를 명시적으로 나타내고자 할 때 사용할 수 있지만 title, description, 그리고 페이지의 실제 콘텐츠가 검색 엔진 최적화에 더 중요한 요소입니다.
파비콘(작은 아이콘)을 설정하게 되면 브라우저의 주소창이나 탭에 표시되는 웹 페이지 제목 옆에 설정한 아이콘을 보여줄 수 있습니다.
// head output
<link rel="icon" href="path/to/favicon.ico" />
// sample
export const metadata: Metadata = {
title: '...',
description: '...',
keywords: [],
icons: {
icon: "favicon image src"
}
}
// example
export const metadata: Metadata = {
title: "Record Your Trip",
description: "여기에 여행을 기록하세요",
keywords: ["여기", "yeogi", "여행", "기록", "여행 기록", "trip", "vacation", "travel", "travel logs"],
icons: {
icon: "/your_logo_img.svg",
},
}
export const metadata = {
icons: {
icon: [
{ url: '/icon.png' },
new URL('/icon.png', 'https://example.com'),
{ url: '/icon-dark.png', media: '(prefers-color-scheme: dark)' },
],
shortcut: ['/shortcut-icon.png'],
apple: [
{ url: '/apple-icon.png' },
{ url: '/apple-icon-x3.png', sizes: '180x180', type: 'image/png' },
],
other: [
{
rel: 'apple-touch-icon-precomposed',
url: '/apple-touch-icon-precomposed.png',
},
],
},
}
기본적인 메타데이터 설정을 전부 작성한 다음 링크를 공유하면 아래와 같이 보여지게 됩니다.
// head output
<meta name="application-name" content="Next.js" />
<meta name="author" content="Seb" />
<link rel="author" href="https://nextjs.org" />
<meta name="author" content="Josh" />
<meta name="generator" content="Next.js" />
<meta name="referrer" content="origin-when-cross-origin" />
<meta name="color-scheme" content="dark" />
<meta name="creator" content="Jiachi Liu" />
<meta name="publisher" content="Sebastian Markbåge" />
<meta name="format-detection" content="telephone=no, address=no, email=no" />
// sample
export const metadata = {
generator: 'Next.js',
applicationName: 'Next.js',
referrer: 'origin-when-cross-origin',
authors: [{ name: 'Seb' }, { name: 'Josh', url: 'https://nextjs.org' }],
creator: 'Jiachi Liu',
publisher: 'Sebastian Markbåge',
formatDetection: {
email: false,
address: false,
telephone: false,
},
}
오픈 그래프(OG) 메타데이터는 제목, 설명, 미리보기 이미지와 같은 정보를 제공하여 소셜 미디어 플랫폼에서 공유될 때 웹페이지가 표현되는 방식을 향상시킵니다.
// head output
<meta property="og:title" content="Title Here" />
<meta property="og:description" content="Description Here" />
<meta property="og:image" content="image_url_here" />
// sample
export const metadata: Metadata = {
// .... 생략
openGraph: {
title: "Record Your Trip",
description: "여기에 여행을 기록하세요",
siteName: "Yeogi",
locale: 'ko_KR',
type: 'website',
url: "https://yeogi-client.vercel.app/",
images: {
url: "OG image's absolute src",
},
},
}
// example
오픈그래프에서 작성한 내용은 미리보기 카드에서 확인이 가능한 내용이고 SEO와 직접적으로 연관이 있는 건 일반적인 메타데이터 설정입니다 :)
두 메타데이터의 역할이 다르기 때문에 각각 설정해주는 것이 좋을 것 같아요.
하지만 두 메타데이터에 들어가는 내용 중 공통되는 것이 있다면, 예를 들면 title과 description 같이, 변수로 만들어 넣어줄 수도 있습니다.
// head output
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="en_US" />
<meta property="og:image:url" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image:alt" content="My custom alt" />
<meta property="og:type" content="website" />
// sample
export const metadata = {
openGraph: {
images: [
{
url: 'https://nextjs.org/og.png', // Must be an absolute URL
width: 800,
height: 600,
}
],
videos: [
{
url: 'https://nextjs.org/video.mp4', // Must be an absolute URL
width: 800,
height: 600,
},
],
locale: 'en_US',
type: 'website',
},
}
robots.txt
를 통해 검색엔진 크롤링에 대한 지침을 제공할 수 있습니다.
robots는 웹 페이지의 로봇 메타 태그에 해당하는 내용을 설정하는 옵션으로 검색 엔진 크롤러나 웹 로봇에게 해당 페이지를 어떻게 다루어야 하는지 지시할 수 있습니다.
robots 메타 태그의 주요 역할은 아래 두 가지가 대표적입니다.
① 검색 엔진 인덱싱 제어
페이지가 검색 엔진의 인덱스에 포함될지 여부를 결정
② 링크 팔로우 제어
페이지 내의 링크를 따라갈지 여부를 결정
대부분의 웹 페이지에서 인덱싱(index)과 팔로우(follow)는 기본적으로 활성화된 상태, 즉 둘 다 기본값이 true로 설정되어 있기 때문에 robots 메타 태그를 따로 설정하지 않으면 검색 엔진은 웹 페이지를 인덱싱하고, 그 페이지 내의 링크를 따라가 다른 페이지를 탐색하게 됩니다.
기본적으로 제공되는 값이 true이기 때문에 따로 설정할 필요는 없습니다.
하지만 명시적으로 한 번 더 설정할 경우, 코드를 명확히 하거나 다른 페이지에서 noindex 또는 nofollow를 사용한 후 기본 설정으로 돌아가고자 할 때 유용할 수 있습니다.
명시적으로 한 번 더 설정했을 때의 장단점을 간단히 정리하자면 아래와 같습니다 :
👍🏻 장점
- 검색 가시성
- SEO 강화
- 사이트 탐색성 증가
👎🏻 단점
- 원치 않는 페이지 인덱싱
- SEO 노이즈
- 중복 콘텐츠 문제
인덱싱(indexing, 색인 작업)은 검색 엔진이 웹 페이지의 내용을 분석하여 데이터베이스에 저장하는 과정을 의미합니다. 이 데이터베이스는 검색 엔진이 사용자에게 검색 결과를 제공할 때 사용하는 곳을 말합니다.
🟢 index: true
해당 웹 페이지는 검색 엔진의 데이터베이스에 포함 O → 관련된 키워드로 검색시 검색 결과 O
🔴 index: false
해당 웹 페이지는 검색 엔진의 데이터베이스에 포함 X → 검색 결과 X
예를 들어, 아래와 같이 robots: 'noindex'
라고 설정할 경우 검색 엔진은 그 페이지를 인덱싱하지 않으며, 사용자가 검색할 때 그 페이지가 검색 결과에 나타나지 않게 됩니다.
// head output
<meta name="robots" content="noindex" />
// sample
export const metadata: Metadata = {
robots: {
index: false,
},
}
링크를 따라가기는 검색 엔진의 웹 크롤러가 해당 페이지에 있는 링크를 따라가서 그 링크로 연결된 다른 페이지를 방문하는 것을 의미합니다.
🟢 follow: true
크롤러는 페이지의 모든 링크를 따라가면서 다른 페이지들을 방문하고 인덱싱할 수 있습니다.
이를 통해 웹 전체를 탐색하며 페이지 간의 연결을 분석합니다.
🔴 follow: false
크롤러는 해당 페이지에서 다른 페이지로 연결된 링크를 무시합니다.
따라서 해당 페이지에 있는 링크를 따라가 다른 페이지를 방문하거나 인덱싱하지 않습니다.
예를 들어, robots: 'nofollow'라고 설정하면, 검색 엔진은 그 페이지에 있는 링크를 따라가지 않으며, 그 링크로 연결된 페이지를 방문하거나 인덱싱하지 않습니다.
// head output
<meta name="robots" content="noindex, follow" />
// sample
export const metadata: Metadata = {
robots: {
index: false,
follow: true
},
}
// head output
<meta name="robots" content="noindex, follow, nocache" />
<meta
name="googlebot"
content="index, nofollow, noimageindex, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>
// sample
export const metadata: Metadata = {
robots: {
index: false,
follow: true,
nocache: true,
googleBot: {
index: true,
follow: false,
noimageindex: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
}
검색 엔진이 이 페이지를 캐시하게 할 것인지에 대한 여부를 설정하는 옵션으로 검색 엔진에게 이 페이지의 콘텐츠를 캐시하지 않도록 지시하는 역할을 합니다.
🟢 nocache: true
검색 엔진이 이 페이지를 캐시하지 않도록 설정 → 이 페이지의 복사본 저장 X
사용자가 이 페이지를 검색할 때 항상 최신 버전을 보게 됨
🔴 nocache: false
검색 엔진이 이 페이지를 캐시할 수 있도록 허용 → 페이지의 복사본 저장 O
사용자가 검색 결과에서 페이지를 클릭할 때 캐시된 버전을 봄
이 설정은 특정 페이지의 내용이 자주 변경되거나, 캐시로 인해 사용자에게 잘못된 정보가 표시될 위험이 있는 경우 유용합니다.
따라서 정적(static) 메타데이터를 사용하는 페이지는 내용이 자주 변경되지 않으므로 캐시를 허용하는 것이 일반적으로 더 효율적입니다.
따라서 이런 페이지의 경우는 캐시를 허용함으로써 페이지 로딩 속도를 빠르게 하는 것이 유리할 수 있습니다.
반대로 다이나믹(dynamic) 메타데이터를 사용하는 페이지는 내용이 자주 변경될 수 있기 때문에 nocache를 true로 설정하여 사용자에게 항ㅅ아 최신 데이터를 보여줄 수 있도록 하는 것이 유리할 수 있습니다.
메타데이터에 많은 내용을 적다보면 굉장히 길어집니다.
그러면 코드의 길이도 길어지고 덩달아 가독성이 떨어질 수 밖에 없습니다.
개인적으로 저는 한 파일의 코드 길이가 최대 100줄, 가능하다면 50 ~ 70줄 사이를 유지하길 선호하기 때문에 상수화해 관리하도록 했습니다.
들어가야 하는 내용을 전부 적은 후 이를 constants/metadata.ts
파일을 만들어 분리했습니다.
정적인 메타데이터(static meta-data)의 경우에는 아래와 같이 한 줄로 줄일 수 있습니다.
// 최상위 layout.tsx
export const metadata = DEFAULT_METADATA
// app/survey/page.tsx
export const metadata = SURVEY_METADATA
References.
[🌍 officials]
[👩🏻💻 blogs]