generateMetadata
이 페이지에서는 generateMetadata
와 정적 metadata 객체를 사용한 모든 설정 기반 메타데이터 옵션을 다룹니다.
import type { Metadata } from "next";
// 정적 메타데이터
export const metadata: Metadata = {
title: "...",
};
// 또는 동적 메타데이터
export async function generateMetadata({ params }) {
return {
title: "...",
};
}
// 정적 메타데이터
export const metadata = {
title: "...",
};
// 또는 동적 메타데이터
export async function generateMetadata({ params }) {
return {
title: "...",
};
}
알아두면 좋은 점:
metadata
객체와generateMetadata
함수 내보내기는 서버 컴포넌트에서만 지원됩니다.- 동일한 라우트 세그먼트에서
metadata
객체와generateMetadata
함수를 모두 내보낼 수 없습니다.
metadata
객체
정적 메타데이터를 정의하려면 layout.js
또는 page.js
파일에서 Metadata
객체를 내보내세요.
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "...",
description: "...",
};
export default function Page() {}
export const metadata = {
title: "...",
description: "...",
};
export default function Page() {}
지원되는 전체 옵션 목록은 메타데이터 필드를 참조하세요.
generateMetadata
함수
동적 메타데이터는 현재 라우트 매개변수, 외부 데이터 또는 상위 세그먼트의 metadata
와 같은 동적 정보에 의존합니다. Metadata
객체를 반환하는 generateMetadata
함수를 내보내서 설정할 수 있습니다.
import type { Metadata, ResolvingMetadata } from "next";
type Props = {
params: { id: string };
searchParams: { [key: string]: string | string[] | undefined };
};
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// 라우트 매개변수 읽기
const id = params.id;
// 데이터 가져오기
const product = await fetch(`https://.../${id}`).then((res) => res.json());
// 선택적으로 상위 메타데이터에 접근하고 확장(대체하지 않음)
const previousImages = (await parent).openGraph?.images || [];
return {
title: product.title,
openGraph: {
images: ["/some-specific-page-image.jpg", ...previousImages],
},
};
}
export default function Page({ params, searchParams }: Props) {}
export async function generateMetadata({ params, searchParams }, parent) {
// 라우트 매개변수 읽기
const id = params.id;
// 데이터 가져오기
const product = await fetch(`https://.../${id}`).then((res) => res.json());
// 선택적으로 상위 메타데이터에 접근하고 확장(대체하지 않음)
const previousImages = (await parent).openGraph?.images || [];
return {
title: product.title,
openGraph: {
images: ["/some-specific-page-image.jpg", ...previousImages],
},
};
}
export default function Page({ params, searchParams }) {}
매개변수
generateMetadata
함수는 다음 매개변수를 받습니다:
-
props
- 현재 라우트의 매개변수를 포함하는 객체:-
params
-generateMetadata
가 호출된 세그먼트에서 루트 세그먼트까지의 동적 라우트 매개변수 객체를 포함합니다. 예시:라우트 URL params
app/shop/[slug]/page.js
/shop/1
{ slug: '1' }
app/shop/[tag]/[item]/page.js
/shop/1/2
{ tag: '1', item: '2' }
app/shop/[...slug]/page.js
/shop/1/2
{ slug: ['1', '2'] }
-
searchParams
- 현재 URL의 검색 매개변수를 포함하는 객체입니다. 예시:URL searchParams
/shop?a=1
{ a: '1' }
/shop?a=1&b=2
{ a: '1', b: '2' }
/shop?a=1&a=2
{ a: ['1', '2'] }
-
-
parent
- 상위 라우트 세그먼트에서 해결된 메타데이터의 프로미스입니다.
반환
generateMetadata
는 하나 이상의 메타데이터 필드를 포함하는 Metadata
객체를 반환해야 합니다.
알아두면 좋은 점:
- 메타데이터가 런타임 정보에 의존하지 않는 경우,
generateMetadata
보다는 정적metadata
객체를 사용하여 정의해야 합니다.fetch
요청은generateMetadata
,generateStaticParams
, 레이아웃, 페이지 및 서버 컴포넌트에서 동일한 데이터에 대해 자동으로 메모이제이션됩니다.fetch
를 사용할 수 없는 경우 Reactcache
를 사용할 수 있습니다.searchParams
는page.js
세그먼트에서만 사용할 수 있습니다.- Next.js의
redirect()
와notFound()
메서드도generateMetadata
내에서 사용할 수 있습니다.
메타데이터 필드
title
title
속성은 문서의 제목을 설정하는 데 사용됩니다. 간단한 문자열이나 선택적 템플릿 객체로 정의할 수 있습니다.
문자열
export const metadata = {
title: "Next.js",
};
<title>Next.js</title>
템플릿 객체
import type { Metadata } from "next";
export const metadata: Metadata = {
title: {
template: "...",
default: "...",
absolute: "...",
},
};
export const metadata = {
title: {
default: "...",
template: "...",
absolute: "...",
},
};
Default
title.default
는 title
을 정의하지 않은 하위 라우트 세그먼트에 대체 제목을 제공하는 데 사용할 수 있습니다.
import type { Metadata } from "next";
export const metadata: Metadata = {
title: {
default: "Acme",
},
};
import type { Metadata } from "next";
export const metadata: Metadata = {};
// 출력: <title>Acme</title>
Template
title.template
는 하위 라우트 세그먼트에 정의된 titles
에 접두사나 접미사를 추가하는 데 사용할 수 있습니다.
import type { Metadata } from "next";
export const metadata: Metadata = {
title: {
template: "%s | Acme",
default: "Acme", // 템플릿을 만들 때 기본값이 필요합니다
},
};
export const metadata = {
title: {
template: "%s | Acme",
default: "Acme", // 템플릿을 만들 때 기본값이 필요합니다
},
};
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "About",
};
// 출력: <title>About | Acme</title>
export const metadata = {
title: "About",
};
// 출력: <title>About | Acme</title>
알아두면 좋은 점:
title.template
는 하위 라우트 세그먼트에 적용되며 정의된 세그먼트에는 적용되지 않습니다. 이는 다음을 의미합니다:
title.template
을 추가할 때title.default
가 필요합니다.layout.js
에 정의된title.template
은 동일한 라우트 세그먼트의page.js
에 정의된title
에 적용되지 않습니다.page.js
에 정의된title.template
은 페이지가 항상 종료 세그먼트이기 때문에 효과가 없습니다(하위 라우트 세그먼트가 없음).라우트에서
title
또는title.default
를 정의하지 않은 경우title.template
은 아무 효과가 없습니다.
Absolute
title.absolute
는 상위 세그먼트에 설정된 title.template
을 무시하는 제목을 제공하는 데 사용할 수 있습니다.
import type { Metadata } from "next";
export const metadata: Metadata = {
title: {
template: "%s | Acme",
},
};
export const metadata = {
title: {
template: "%s | Acme",
},
};
import type { Metadata } from "next";
export const metadata: Metadata = {
title: {
absolute: "About",
},
};
// 출력: <title>About</title>
export const metadata = {
title: {
absolute: "About",
},
};
// 출력: <title>About</title>
알아두면 좋은 점:
layout.js
title
(문자열)과title.default
는 하위 세그먼트의 기본 제목을 정의합니다(title
을 정의하지 않은 경우). 가장 가까운 상위 세그먼트의title.template
가 있다면 이를 활용합니다.title.absolute
는 하위 세그먼트의 기본 제목을 정의합니다. 상위 세그먼트의title.template
을 무시합니다.title.template
는 하위 세그먼트에 대한 새로운 제목 템플릿을 정의합니다.
page.js
- 페이지가 자체 제목을 정의하지 않으면 가장 가까운 상위의 해결된 제목이 사용됩니다.
title
(문자열)은 라우트의 제목을 정의합니다. 가장 가까운 상위 세그먼트의title.template
가 있다면 이를 활용합니다.title.absolute
는 라우트 제목을 정의합니다. 상위 세그먼트의title.template
을 무시합니다.title.template
은page.js
에서 효과가 없습니다. 페이지는 항상 라우트의 종료 세그먼트이기 때문입니다.
description
export const metadata = {
description: "The React Framework for the Web",
};
<meta name="description" content="The React Framework for the Web" />
기본 필드
export const metadata = {
generator: "Next.js",
applicationName: "Next.js",
referrer: "origin-when-cross-origin",
keywords: ["Next.js", "React", "JavaScript"],
authors: [{ name: "Seb" }, { name: "Josh", url: "https://nextjs.org" }],
creator: "Jiachi Liu",
publisher: "Sebastian Markbåge",
formatDetection: {
email: false,
address: false,
telephone: false,
},
};
<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="keywords" content="Next.js,React,JavaScript" />
<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" />
metadataBase
metadataBase
는 완전한 URL이 필요한 metadata
필드에 대한 기본 URL 접두사를 설정하는 편리한 옵션입니다.
metadataBase
를 사용하면 현재 라우트 세그먼트 및 그 아래에서 정의된 URL 기반metadata
필드가 절대 URL 대신 상대 경로를 사용할 수 있습니다.- 필드의 상대 경로는
metadataBase
와 결합되어 완전한 URL을 형성합니다. - 구성되지 않은 경우
metadataBase
는 기본값으로 자동 채워집니다.
export const metadata = {
metadataBase: new URL("https://acme.com"),
alternates: {
canonical: "/",
languages: {
"en-US": "/en-US",
"de-DE": "/de-DE",
},
},
openGraph: {
images: "/og-image.png",
},
};
<link rel="canonical" href="https://acme.com" />
<link rel="alternate" hreflang="en-US" href="https://acme.com/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://acme.com/de-DE" />
<meta property="og:image" content="https://acme.com/og-image.png" />
알아두면 좋은 점:
metadataBase
는 일반적으로 모든 라우트에 걸쳐 URL 기반metadata
필드에 적용하기 위해 루트app/layout.js
에 설정됩니다.- 절대 URL이 필요한 모든 URL 기반
metadata
필드는metadataBase
옵션으로 구성할 수 있습니다.metadataBase
는 하위 도메인(예:https://app.acme.com
) 또는 기본 경로(예:https://acme.com/start/from/here
)를 포함할 수 있습니다.metadata
필드가 절대 URL을 제공하는 경우metadataBase
는 무시됩니다.metadataBase
를 구성하지 않고 URL 기반metadata
필드에 상대 경로를 사용하면 빌드 오류가 발생합니다.- Next.js는
metadataBase
(예:https://acme.com/
)와 상대 필드(예:/path
) 사이의 중복 슬래시를 단일 슬래시(예:https://acme.com/path
)로 정규화합니다.
기본값
구성되지 않은 경우 metadataBase
에는 기본값이 있습니다.
Vercel에서:
- 프로덕션 배포의 경우
VERCEL_URL
이 사용됩니다.- 프리뷰 배포의 경우
VERCEL_BRANCH_URL
이 우선순위를 가지며, 없는 경우VERCEL_URL
로 대체됩니다.이러한 값이 있으면
metadataBase
의 기본값으로 사용되며, 그렇지 않으면http://localhost:${process.env.PORT || 3000}
로 대체됩니다. 이를 통해 Open Graph 이미지가 로컬 빌드와 Vercel 프리뷰 및 프로덕션 배포에서 모두 작동할 수 있습니다. 기본값을 재정의할 때는 환경 변수를 사용하여 URL을 계산하는 것이 좋습니다. 이를 통해 로컬 개발, 스테이징 및 프로덕션 환경에 대한 URL을 구성할 수 있습니다.이러한 환경 변수에 대한 자세한 내용은 시스템 환경 변수 문서를 참조하세요.
URL 구성
URL 구성은 기본 디렉토리 순회 의미론보다 개발자의 의도를 우선시합니다.
metadataBase
와metadata
필드 사이의 후행 슬래시는 정규화됩니다.metadata
필드의 "절대" 경로(일반적으로 전체 URL 경로를 대체함)는 "상대" 경로(metadataBase
의 끝에서 시작)로 취급됩니다.
예를 들어, 다음과 같은 metadataBase
가 주어진 경우:
import type { Metadata } from "next";
export const metadata: Metadata = {
metadataBase: new URL("https://acme.com"),
};
export const metadata = {
metadataBase: new URL("https://acme.com"),
};
위의 metadataBase
를 상속하고 자체 값을 설정하는 metadata
필드는 다음과 같이 해결됩니다:
metadata 필드 | 반환된 URL |
---|---|
/ | https://acme.com |
./ | https://acme.com |
payments | https://acme.com/payments |
/payments | https://acme.com/payments |
./payments | https://acme.com/payments |
../payments | https://acme.com/payments |
https://beta.acme.com/payments | https://beta.acme.com/payments |
openGraph
export const metadata = {
openGraph: {
title: "Next.js",
description: "The React Framework for the Web",
url: "https://nextjs.org",
siteName: "Next.js",
images: [
{
url: "https://nextjs.org/og.png", // 반드시 절대 URL이어야 합니다
width: 800,
height: 600,
},
{
url: "https://nextjs.org/og-alt.png", // 반드시 절대 URL이어야 합니다
width: 1800,
height: 1600,
alt: "My custom alt",
},
],
videos: [
{
url: "https://nextjs.org/video.mp4", // 반드시 절대 URL이어야 합니다
width: 800,
height: 600,
},
],
locale: "en_US",
type: "website",
},
};
<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:url" content="https://nextjs.org/og-alt.png" />
<meta property="og:image:width" content="1800" />
<meta property="og:image:height" content="1600" />
<meta property="og:image:alt" content="My custom alt" />
<meta property="og:type" content="website" />
export const metadata = {
openGraph: {
title: "Next.js",
description: "The React Framework for the Web",
type: "article",
publishedTime: "2023-01-01T00:00:00.000Z",
authors: ["Seb", "Josh"],
},
};
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-01-01T00:00:00.000Z" />
<meta property="article:author" content="Seb" />
<meta property="article:author" content="Josh" />
알아두면 좋은 점:
- Open Graph 이미지에는 파일 기반 메타데이터 API를 사용하는 것이 더 편리할 수 있습니다. 구성 내보내기를 실제 파일과 동기화할 필요 없이 파일 기반 API가 자동으로 올바른 메타데이터를 생성합니다.
robots
import type { Metadata } from "next";
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,
},
},
};
<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"
/>
icons
알아두면 좋은 점: 가능한 경우 파일 기반 메타데이터 API를 사용하는 것이 좋습니다. 구성 내보내기를 실제 파일과 동기화할 필요 없이 파일 기반 API가 자동으로 올바른 메타데이터를 생성합니다.
export const metadata = {
icons: {
icon: "/icon.png",
shortcut: "/shortcut-icon.png",
apple: "/apple-icon.png",
other: {
rel: "apple-touch-icon-precomposed",
url: "/apple-touch-icon-precomposed.png",
},
},
};
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
rel="apple-touch-icon-precomposed"
href="/apple-touch-icon-precomposed.png"
/>
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",
},
],
},
};
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="icon" href="https://example.com/icon.png" />
<link rel="icon" href="/icon-dark.png" media="(prefers-color-scheme: dark)" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
rel="apple-touch-icon-precomposed"
href="/apple-touch-icon-precomposed.png"
/>
<link
rel="apple-touch-icon"
href="/apple-icon-x3.png"
sizes="180x180"
type="image/png"
/>
알아두면 좋은 점:
msapplication-*
메타 태그는 Microsoft Edge의 Chromium 빌드에서 더 이상 지원되지 않으므로 더 이상 필요하지 않습니다.
themeColor
더 이상 사용되지 않음: Next.js 14부터
metadata
의themeColor
옵션은 더 이상 사용되지 않습니다. 대신viewport
구성을 사용하세요.
manifest
웹 애플리케이션 매니페스트 사양에 정의된 웹 애플리케이션 매니페스트입니다.
export const metadata = {
manifest: "https://nextjs.org/manifest.json",
};
<link rel="manifest" href="https://nextjs.org/manifest.json" />
twitter
Twitter 사양은 (놀랍게도) X(이전의 Twitter)뿐만 아니라 다른 곳에서도 사용됩니다.
Twitter 카드 마크업 참조에서 자세히 알아보세요.
export const metadata = {
twitter: {
card: "summary_large_image",
title: "Next.js",
description: "The React Framework for the Web",
siteId: "1467726470533754880",
creator: "@nextjs",
creatorId: "1467726470533754880",
images: ["https://nextjs.org/og.png"], // 반드시 절대 URL이어야 합니다
},
};
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
export const metadata = {
twitter: {
card: "app",
title: "Next.js",
description: "The React Framework for the Web",
siteId: "1467726470533754880",
creator: "@nextjs",
creatorId: "1467726470533754880",
images: {
url: "https://nextjs.org/og.png",
alt: "Next.js Logo",
},
app: {
name: "twitter_app",
id: {
iphone: "twitter_app://iphone",
ipad: "twitter_app://ipad",
googleplay: "twitter_app://googleplay",
},
url: {
iphone: "https://iphone_url",
ipad: "https://ipad_url",
},
},
},
};
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:card" content="app" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
<meta name="twitter:image:alt" content="Next.js Logo" />
<meta name="twitter:app:name:iphone" content="twitter_app" />
<meta name="twitter:app:id:iphone" content="twitter_app://iphone" />
<meta name="twitter:app:id:ipad" content="twitter_app://ipad" />
<meta name="twitter:app:id:googleplay" content="twitter_app://googleplay" />
<meta name="twitter:app:url:iphone" content="https://iphone_url" />
<meta name="twitter:app:url:ipad" content="https://ipad_url" />
<meta name="twitter:app:name:ipad" content="twitter_app" />
<meta name="twitter:app:name:googleplay" content="twitter_app" />
viewport
더 이상 사용되지 않음: Next.js 14부터
metadata
의viewport
옵션은 더 이상 사용되지 않습니다. 대신viewport
구성을 사용하세요.
verification
export const metadata = {
verification: {
google: "google",
yandex: "yandex",
yahoo: "yahoo",
other: {
me: ["my-email", "my-link"],
},
},
};
<meta name="google-site-verification" content="google" />
<meta name="y_key" content="yahoo" />
<meta name="yandex-verification" content="yandex" />
<meta name="me" content="my-email" />
<meta name="me" content="my-link" />
appleWebApp
export const metadata = {
itunes: {
appId: "myAppStoreID",
appArgument: "myAppArgument",
},
appleWebApp: {
title: "Apple Web App",
statusBarStyle: "black-translucent",
startupImage: [
"/assets/startup/apple-touch-startup-image-768x1004.png",
{
url: "/assets/startup/apple-touch-startup-image-1536x2008.png",
media: "(device-width: 768px) and (device-height: 1024px)",
},
],
},
};
<meta
name="apple-itunes-app"
content="app-id=myAppStoreID, app-argument=myAppArgument"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Apple Web App" />
<link
href="/assets/startup/apple-touch-startup-image-768x1004.png"
rel="apple-touch-startup-image"
/>
<link
href="/assets/startup/apple-touch-startup-image-1536x2008.png"
media="(device-width: 768px) and (device-height: 1024px)"
rel="apple-touch-startup-image"
/>
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
alternates
export const metadata = {
alternates: {
canonical: "https://nextjs.org",
languages: {
"en-US": "https://nextjs.org/en-US",
"de-DE": "https://nextjs.org/de-DE",
},
media: {
"only screen and (max-width: 600px)": "https://nextjs.org/mobile",
},
types: {
"application/rss+xml": "https://nextjs.org/rss",
},
},
};
<link rel="canonical" href="https://nextjs.org" />
<link rel="alternate" hreflang="en-US" href="https://nextjs.org/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://nextjs.org/de-DE" />
<link
rel="alternate"
media="only screen and (max-width: 600px)"
href="https://nextjs.org/mobile"
/>
<link
rel="alternate"
type="application/rss+xml"
href="https://nextjs.org/rss"
/>
appLinks
export const metadata = {
appLinks: {
ios: {
url: "https://nextjs.org/ios",
app_store_id: "app_store_id",
},
android: {
package: "com.example.android/package",
app_name: "app_name_android",
},
web: {
url: "https://nextjs.org/web",
should_fallback: true,
},
},
};
<meta property="al:ios:url" content="https://nextjs.org/ios" />
<meta property="al:ios:app_store_id" content="app_store_id" />
<meta property="al:android:package" content="com.example.android/package" />
<meta property="al:android:app_name" content="app_name_android" />
<meta property="al:web:url" content="https://nextjs.org/web" />
<meta property="al:web:should_fallback" content="true" />
archives
역사적 관심이 있는 기록, 문서 또는 기타 자료의 모음을 설명합니다 (출처).
export const metadata = {
archives: ["https://nextjs.org/13"],
};
<link rel="archives" href="https://nextjs.org/13" />
assets
export const metadata = {
assets: ["https://nextjs.org/assets"],
};
<link rel="assets" href="https://nextjs.org/assets" />
bookmarks
export const metadata = {
bookmarks: ["https://nextjs.org/13"],
};
<link rel="bookmarks" href="https://nextjs.org/13" />
category
export const metadata = {
category: "technology",
};
<meta name="category" content="technology" />
facebook
특정 Facebook 소셜 플러그인을 위해 Facebook 앱이나 Facebook 계정을 웹페이지에 연결할 수 있습니다 Facebook 문서
알아두면 좋은 점: appId 또는 admins 중 하나만 지정할 수 있으며 둘 다 지정할 수는 없습니다.
export const metadata = {
facebook: {
appId: "12345678",
},
};
<meta property="fb:app_id" content="12345678" />
export const metadata = {
facebook: {
admins: "12345678",
},
};
<meta property="fb:admins" content="12345678" />
여러 개의 fb:admins 메타 태그를 생성하려면 배열 값을 사용할 수 있습니다.
export const metadata = {
facebook: {
admins: ["12345678", "87654321"],
},
};
<meta property="fb:admins" content="12345678" />
<meta property="fb:admins" content="87654321" />
other
모든 메타데이터 옵션은 내장 지원을 사용하여 다루어야 합니다. 그러나 사이트나 브랜드에 특정한 사용자 정의 메타데이터 태그가 있거나 방금 출시된 새로운 메타데이터 태그가 있을 수 있습니다. other
옵션을 사용하여 모든 사용자 정의 메타데이터 태그를 렌더링할 수 있습니다.
export const metadata = {
other: {
custom: "meta",
},
};
<meta name="custom" content="meta" />
동일한 키의 여러 메타 태그를 생성하려면 배열 값을 사용할 수 있습니다.
export const metadata = {
other: {
custom: ["meta1", "meta2"],
},
};
<meta name="custom" content="meta1" /> <meta name="custom" content="meta2" />
지원되지 않는 메타데이터
다음 메타데이터 유형은 현재 내장 지원이 없습니다. 그러나 레이아웃이나 페이지 자체에서 여전히 렌더링할 수 있습니다.
메타데이터 | 추천 |
---|---|
<meta http-equiv="..."> | redirect() , 미들웨어, 보안 헤더를 통해 적절한 HTTP 헤더 사용 |
<base> | 레이아웃이나 페이지 자체에서 태그를 렌더링하세요. |
<noscript> | 레이아웃이나 페이지 자체에서 태그를 렌더링하세요. |
<style> | Next.js에서의 스타일링에 대해 자세히 알아보세요. |
<script> | 스크립트 사용에 대해 자세히 알아보세요. |
<link rel="stylesheet" /> | 스타일시트를 레이아웃이나 페이지 자체에 직접 import 하세요. |
<link rel="preload /> | ReactDOM preload 메서드를 사용하세요 |
<link rel="preconnect" /> | ReactDOM preconnect 메서드를 사용하세요 |
<link rel="dns-prefetch" /> | ReactDOM prefetchDNS 메서드를 사용하세요 |
리소스 힌트
<link>
요소에는 외부 리소스가 필요할 가능성이 있음을 브라우저에 힌트하는 데 사용할 수 있는 여러 rel
키워드가 있습니다. 브라우저는 이 정보를 사용하여 키워드에 따라 사전 로딩 최적화를 적용합니다.
메타데이터 API는 이러한 힌트를 직접 지원하지 않지만, 새로운 ReactDOM
메서드를 사용하여 문서의 <head>
에 안전하게 삽입할 수 있습니다.
"use client";
import ReactDOM from "react-dom";
export function PreloadResources() {
ReactDOM.preload("...", { as: "..." });
ReactDOM.preconnect("...", { crossOrigin: "..." });
ReactDOM.prefetchDNS("...");
return "...";
}
"use client";
import ReactDOM from "react-dom";
export function PreloadResources() {
ReactDOM.preload("...", { as: "..." });
ReactDOM.preconnect("...", { crossOrigin: "..." });
ReactDOM.prefetchDNS("...");
return "...";
}
<link rel="preload">
페이지 렌더링(브라우저) 수명 주기 초기에 리소스 로딩을 시작합니다. MDN 문서를 참조하세요.
ReactDOM.preload(href: string, options: { as: string })
<link rel="preload" href="..." as="..." />
<link rel="preconnect">
원본에 대한 연결을 미리 시작합니다. MDN 문서를 참조하세요.
ReactDOM.preconnect(href: string, options?: { crossOrigin?: string })
<link rel="preconnect" href="..." crossorigin />
<link rel="dns-prefetch">
리소스 요청 전에 도메인 이름을 해결하려고 시도합니다. MDN 문서를 참조하세요.
ReactDOM.prefetchDNS(href: string)
<link rel="dns-prefetch" href="..." />
알아두면 좋은 점:
- 이러한 메서드는 현재 클라이언트 컴포넌트에서만 지원되며, 초기 페이지 로드 시 여전히 서버 측 렌더링됩니다.
next/font
,next/image
,next/script
와 같은 Next.js 내장 기능은 관련 리소스 힌트를 자동으로 처리합니다.
타입
IDE에서 내장 TypeScript 플러그인을 사용하고 있다면 수동으로 타입을 추가할 필요가 없지만, 명시적으로 추가하고 싶다면 Metadata
타입을 사용하여 메타데이터에 타입 안전성을 추가할 수 있습니다.
metadata
객체
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Next.js",
};
generateMetadata
함수
일반 함수
import type { Metadata } from "next";
export function generateMetadata(): Metadata {
return {
title: "Next.js",
};
}
비동기 함수
import type { Metadata } from "next";
export async function generateMetadata(): Promise<Metadata> {
return {
title: "Next.js",
};
}
세그먼트 props 포함
import type { Metadata } from "next";
type Props = {
params: { id: string };
searchParams: { [key: string]: string | string[] | undefined };
};
export function generateMetadata({ params, searchParams }: Props): Metadata {
return {
title: "Next.js",
};
}
export default function Page({ params, searchParams }: Props) {}
상위 메타데이터 포함
import type { Metadata, ResolvingMetadata } from "next";
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
return {
title: "Next.js",
};
}
JavaScript 프로젝트
JavaScript 프로젝트의 경우 JSDoc을 사용하여 타입 안전성을 추가할 수 있습니다.
/** @type {import("next").Metadata} */
export const metadata = {
title: "Next.js",
};
버전 기록
버전 | 변경 사항 |
---|---|
v13.2.0 | viewport , themeColor , colorScheme 가 viewport 구성을 위해 더 이상 사용되지 않습니다. |
v13.2.0 | metadata 와 generateMetadata 도입. |