Metadata
- Next.js에는 향상된 SEO를 위해 애플리케이션 메타데이터(HTML <head /> 내의 정보)를 정의할 수 있는 메타데이터 API가 있다.
- page나 layout만 메타 데이터를 내보낼 수 있다.
- 각 파일에서 설정한 메타데이터는 중첩된 파일들에 의해 병합된다.
- Client Component에서는 metadata를 정의할 수 없다❌
- metadata는 페이지가 서버에서 렌더링될 때 <head>에 포함되어야 하는데, Client Component는 HTML을 이미 받은 후에 동작하기 때문이다.
- 템플릿과 기본값을 설정할 수 있다.
- 동적 제목 생성에 사용되는 자리 표시자 %s를 사용한다.
// app/layout.tsx
export const metadata: Metadata = {
title: {
template: "%s | Next Movies",
default: "Loading..."
},
description: "The best movies on the best framework",
};
// (home)/page.tsx
export const metadata = {
title: "Home",
};
// app/about-us/page.tsx
export const metadata = {
title: "About us",
};
// 브라우저 탭에 표시되는 제목은 루트에서는 Home | My Website, /about us에서는 About us | My Website가 된다.
Dynamic Metadata (동적 메타데이터)
- URL의 파라미터나 데이터를 기반으로, 페이지마다 다른 메타데이터를 설정할 수 있다.
generateMetadata 함수
: 페이지 렌더링 전에 메타데이터를 생성하는 함수
- 페이지가 로드될 때마다 동적으로 메타데이터를 업데이트 할 수 있다.
- 메타데이터 객체(metadata)와 generateMetadata 함수는 서버 컴포넌트(Server Components)에서만 지원된다.
- 하나의 페이지에서 generateMetadata 함수와 metadata 객체를 함께 사용할 수 없다.
import { generateMetadata } from 'next';
export async function generateMetadata({ params: { id } }: IParams) {
const movie = await getMovie(id);
return {
title: movie.title,
};
}
메타데이터 필드
- title: 페이지의 제목
- description: 페이지의 설명
- robots: 검색 엔진에서의 페이지 인덱싱을 제어하는 설정
(ex. noindex, nofollow) - keywords: 페이지와 관련된 키워드 목록
- openGraph: 소셜 미디어에서의 공유 시 보여지는 정보
(ex. title, description, images 등) - twitter: 트위터 카드 설정
(ex. card, site, title, description 등) - viewport: 페이지의 뷰포트 설정
(ex. width=device-width, initial-scale=1) - themeColor: 브라우저 주소창의 색상 지정
(ex. #ffffff)
export async function generateMetadata({ params: { id } }: IParams) {
const movie = await getMovie(id);
return {
title: movie.title,
description: movie.description,
keywords: movie.genres.join(', '),
openGraph: {
title: movie.title,
description: movie.description,
images: [movie.posterUrl],
},
twitter: {
card: 'summary_large_image',
title: movie.title,
description: movie.description,
},
viewport: 'width=device-width, initial-scale=1',
themeColor: '#000000',
};
}