Pages Router
Head
페이지 별로 Head 컴포넌트 안에 작성하여 SEO 관련 메타 데이터를 설정할 수 있다.
import Head from "next/head";
export default Page() {
return (
<>
<Head>
<title>타이틀</title>
<meata property="og:image" content={썸네일 주소} />
<meata property="og:title" content={타이틀} />
<meata property="og:description" content={설명} />
</Head>
<div>
// ...
</div>
</>
);
}
Fallback 상태에서의 SEO 처리
동적 라우팅을 사용하는 페이지(예: 아이템별 상세 페이지)에서 fallback:true를 설정했을 때, 지정하지 않은 경로에 대해 SSR과 유사하게 동작한다.
이때 초기 HTML에 SEO 관련 메타 데이터가 포함되지 않는 문제가 발생할 수 있는데, 이를 방지하기 위해 fallback 상태에서도 기본적인 SEO 설정을 제공하는 것이 중요하다.
import { GetStaticPropsContext, InferGetStaticPropsType } from "next";
import Head from "next/head";
import { useRouter } from "next/router";
import fetchOneBook from "@/lib/fetch-one-book";
import styles from "./[id].module.css";
export const getStaticPaths = async () => {
return {
paths: [
{ params: { id: "1" } },
{ params: { id: "2" } },
{ params: { id: "3" } },
],
fallback: true,
};
};
export const getStaticProps = async (context: GetStaticPropsContext) => {
const { id } = context.params!;
const book = await fetchOneBook(Number(id));
if (!book) {
return {
notFound: true,
};
}
return {
props: {
book,
},
};
};
export default function Page({
book,
}: InferGetStaticPropsType<typeof getStaticProps>) {
const router = useRouter();
// fallback 상태일 때, 기본적인 SEO 메타 데이터를 설정
if (router.isFallback) {
return (
<>
<Head>
<title>한입북스</title>
<meta property="og:image" content="/thumbnail.png" />
<meta property="og:title" content="한입북스" />
<meta
property="og:description"
content="한입 북스에 등록된 도서들을 만나보세요."
/>
</Head>
<div>로딩중입니다.</div>
</>
);
}
if (!book) return "문제가 발생했습니다. 다시 시도하세요.";
const { title, subTitle, description, author, publisher, coverImgUrl } = book;
return (
<>
<Head>
<title>{title}</title>
<meta property="og:image" content={coverImgUrl} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
</Head>
{/* 페이지 내용 */}
</>
);
}
App Router
Metadata
앱 라우터에서는 페이지 라우터의 Head 컴포넌트를 대체하는 metadata 객체를 이용해 페이지의 메타데이터를 설정할 수 있다.
import { Metadata } from 'next';
export const metadata: Metadata = {
title: "타이틀",
description: "설명"
openGraph: {
title: "타이틀,
description: "설명",
images: ["썸네일 주소"],
},
};
export default function Page() {
return (
// 페이지 컨텐츠
);
}
동적 메타데이터 생성
동적 라우트나 검색 페이지와 같이 페이지 내용에 따라 메타 데이터가 변경되어야 하는 경우, generateMetadata 함수를 사용할 수 있다.
검색 페이지 예시
아래의 예제는 URL의 검색 파라미터를 사용하여 동적으로 메타데이터를 생성한다.
import { Metadata } from 'next';
type PropsType = {
searchParams: {
q?: string;
};
};
export function generateMetadata({ searchParams }: PropsType): Metadata {
const query = searchParams.q || '전체';
return {
title: `${query} : 검색`,
description: `${query} 검색 결과입니다.`,
openGraph: {
title: `${query} : 검색`,
description: `${query} 검색 결과입니다.`,
images: ["/thumbnail.png"],
},
};
}
export default function Page({ searchParams }: PropsType) {
// 검색 결과 렌더링
}
상세 페이지 예시
아래의 예제는 도서 id를 이용하여 서버에서 도서 정보를 가져온 후, 그 정보를 바탕으로 메타데이터를 동적으로 생성한다.
import { Metadata } from 'next';
type PropsType = {
params: {
id: string;
};
};
export async function generateMetadata({
params,
}: PropsType): Promise<Metadata> {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/${params.id}`
);
if (!response.ok) {
throw new Error('도서 정보를 가져오는데 실패했습니다');
}
const book = await response.json();
return {
title: `${book.title} - 한입북스`,
description: book.description,
openGraph: {
title: `${book.title} - 한입북스`,
description: book.description,
images: [book.coverImgUrl],
},
};
}
export default function Page({ params }: PropsType) {
// 상세 정보 렌더링
}'Frontend > Next.js' 카테고리의 다른 글
| Next.js의 데이터 페칭 방식 (0) | 2025.11.13 |
|---|---|
| React Server Component (0) | 2025.11.13 |
| Next.js 페이지 라우터의 렌더링 방식 (0) | 2025.11.13 |
| Next.js의 프리 페칭 (Pre-fetching) (0) | 2025.11.13 |
| Next.js의 레이아웃 설정 (0) | 2025.11.09 |
