Next.js 16 메타 태그, Open Graph, JSON-LD 구조화된 데이터 자동 생성. 이커머스 SEO 최적화 (상품, 리뷰, 카테고리)
Next.js 16 App Router 기반 SEO 최적화를 자동화합니다. 메타 태그, Open Graph, JSON-LD 구조화된 데이터를 자동 생성하고 SEO 점수를 분석합니다.
# 기본 메타 태그 생성
/seo app/(main)/products/[productId]/page.tsx
# Open Graph 이미지 포함
/seo app/(main)/products/[productId]/page.tsx --og-image
# JSON-LD 구조화된 데이터 생성
/seo app/(main)/products/[productId]/page.tsx --schema Product
# 전체 SEO 최적화
/seo app/(main)/products/[productId]/page.tsx --all
# SEO 점수 분석
/seo app/(main)/products/[productId]/page.tsx --audit
<title> - 페이지 제목 (50-60자)<meta name="description"> - 페이지 설명 (150-160자)<meta name="keywords"> - 주요 키워드<link rel="canonical"> - 정규 URLog:title - 공유 제목og:description - 공유 설명og:image - 공유 이미지 (1200x630)og:url - 페이지 URLog:type - 페이지 타입 (product, website 등)twitter:card - 카드 타입 (summary_large_image)twitter:title - 트위터 제목twitter:description - 트위터 설명twitter:image - 트위터 이미지생성 결과:
// app/(main)/products/[productId]/page.tsx
import { Metadata } from 'next';
type Props = {
params: { productId: string };
};
export async function generateMetadata({ params }: Props): Promise<Metadata> {
// 상품 정보 조회
const product = await getProduct(params.productId);
return {
title: `${product.name} | Novera Shop`,
description: product.description.slice(0, 160),
keywords: [
product.category,
product.brand,
product.name,
'온라인 쇼핑',
'무료배송',
],
// Open Graph
openGraph: {
title: product.name,
description: product.description,
images: [
{
url: product.imageUrl,
width: 1200,
height: 630,
alt: product.name,
},
],
type: 'product',
locale: 'ko_KR',
siteName: 'Novera Shop',
},
// Twitter
twitter: {
card: 'summary_large_image',
title: product.name,
description: product.description,
images: [product.imageUrl],
},
// 정규 URL
alternates: {
canonical: `https://novera-shop.com/products/${params.productId}`,
},
// 추가 메타 태그
other: {
'product:price:amount': product.price.toString(),
'product:price:currency': 'KRW',
'product:availability': product.stock > 0 ? 'in stock' : 'out of stock',
},
};
}
export default async function ProductPage({ params }: Props) {
const product = await getProduct(params.productId);
return (
<>
{/* JSON-LD 구조화된 데이터 */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
image: product.imageUrl,
description: product.description,
brand: {
'@type': 'Brand',
name: product.brand,
},
offers: {
'@type': 'Offer',
url: `https://novera-shop.com/products/${params.productId}`,
priceCurrency: 'KRW',
price: product.price,
availability: product.stock > 0
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
seller: {
'@type': 'Organization',
name: 'Novera Shop',
},
},
aggregateRating: product.reviewCount > 0 ? {
'@type': 'AggregateRating',
ratingValue: product.averageRating,
reviewCount: product.reviewCount,
} : undefined,
}),
}}
/>
{/* 페이지 내용 */}
<div>{/* ... */}</div>
</>
);
}
생성 결과:
// app/(main)/category/[categoryId]/page.tsx
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const category = await getCategory(params.categoryId);
return {
title: `${category.name} - 베스트 상품 모음 | Novera Shop`,
description: `${category.name} 카테고리의 인기 상품을 만나보세요. 무료배송, 빠른 배송으로 편리하게 쇼핑하세요.`,
keywords: [category.name, '온라인 쇼핑', '베스트 상품', '무료배송'],
openGraph: {
title: `${category.name} 베스트 상품`,
description: `${category.name} 카테고리의 인기 상품을 만나보세요.`,
images: [category.thumbnailUrl],
type: 'website',
},
alternates: {
canonical: `https://novera-shop.com/category/${params.categoryId}`,
},
};
}
JSON-LD Review Schema:
{
'@context': 'https://schema.org',
'@type': 'Review',
itemReviewed: {
'@type': 'Product',
name: product.name,
image: product.imageUrl,
},
author: {
'@type': 'Person',
name: review.authorName,
},
reviewRating: {
'@type': 'Rating',
ratingValue: review.rating,
bestRating: 5,
worstRating: 1,
},
reviewBody: review.content,
datePublished: review.createdAt,
}
/seo app/(main)/products/[productId]/page.tsx --audit
# SEO 점수 분석: products/[productId]/page.tsx
## 📊 전체 점수: 75/100
### ✅ 통과 (7/10)
- [x] title 태그 존재 (58자 - 적정)
- [x] description 태그 존재 (152자 - 적정)
- [x] Open Graph 이미지 존재 (1200x630 - 적정)
- [x] 정규 URL 설정
- [x] 구조화된 데이터 (Product Schema)
- [x] 모바일 반응형
- [x] HTTPS 사용
### ⚠️ 개선 필요 (3/10)
1. **keywords 메타 태그 누락**
- 영향도: Medium
- 해결책: 상품 카테고리, 브랜드를 keywords에 추가
2. **Twitter Card 누락**
- 영향도: Medium
- 해결책: twitter:card, twitter:image 추가
3. **AggregateRating 누락**
- 영향도: High (검색 결과 별점 표시)
- 해결책: 리뷰 평점을 JSON-LD에 추가
## 💡 개선 제안
### 1순위 (즉시 수정)
```typescript
// AggregateRating 추가
aggregateRating: {
'@type': 'AggregateRating',
ratingValue: 4.5,
reviewCount: 127,
}
// Twitter Card 추가