6.7 KiB
6.7 KiB
id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
| id | title | category | status | canonical_id | aliases | duplicate_of | source_trust_level | confidence_score | verification_status | tags | raw_sources | last_reinforced | github_commit | tech_stack | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wiki-2026-0508-json-ld-structured-data | JSON-LD Structured Data | 10_Wiki/Topics | verified | self |
|
none | A | 0.9 | applied |
|
2026-05-10 | pending |
|
JSON-LD Structured Data
매 한 줄
"매 JSON-LD = 검색엔진에게 페이지 의미를 직접 말해주는 메타 데이터 레이어". HTML 마크업과 분리된
<script type="application/ld+json">블록으로 Schema.org vocabulary를 사용해 entity, relation, property를 선언한다. Google이 권장하는 structured data 형식이며 rich snippet/knowledge panel/AI Overviews 노출의 입장권.
매 핵심
매 왜 JSON-LD인가
- 분리성: HTML rendering과 독립 — 마크업 변경 없이 추가 가능.
- Google 권장: Microdata/RDFa보다 우선순위 높음 (2026 기준).
- AI 친화적: LLM-powered search (Perplexity, ChatGPT Search, Google AI Overviews)가 entity graph 추출에 활용.
- 유지보수: Template engine에서 server-side 생성 쉬움.
매 핵심 vocabulary
@context: 보통"https://schema.org".@type: Article, Product, Organization, BreadcrumbList, FAQPage, Recipe 등.@id: entity의 canonical URI (graph 연결용).@graph: 같은 페이지 내 다중 entity 묶음.
매 응용
- E-commerce → Product + Offer + AggregateRating.
- 미디어/블로그 → Article + Author(Person) + Publisher(Organization).
- 로컬 비즈니스 → LocalBusiness + Address + OpeningHours.
- FAQ/HowTo → FAQPage / HowTo (rich snippet 가시성 매우 높음).
- SaaS → SoftwareApplication + AggregateRating.
💻 패턴
Article schema (블로그/뉴스)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "JSON-LD 완전 정복",
"image": ["https://example.com/cover.jpg"],
"datePublished": "2026-05-10T08:00:00+09:00",
"dateModified": "2026-05-10T08:00:00+09:00",
"author": {
"@type": "Person",
"name": "홍길동",
"url": "https://example.com/author/hong"
},
"publisher": {
"@type": "Organization",
"name": "Example",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
}
}
}
</script>
Product + Offer (E-commerce)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Mechanical Keyboard X1",
"image": "https://example.com/x1.jpg",
"sku": "X1-BLK",
"brand": { "@type": "Brand", "name": "Acme" },
"offers": {
"@type": "Offer",
"url": "https://example.com/p/x1",
"priceCurrency": "KRW",
"price": "189000",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "412"
}
}
</script>
BreadcrumbList
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
{ "@type": "ListItem", "position": 2, "name": "Blog", "item": "https://example.com/blog" },
{ "@type": "ListItem", "position": 3, "name": "JSON-LD" }
]
}
FAQPage (rich snippet 효과 큼)
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "JSON-LD를 어디에 넣어야 하나요?",
"acceptedAnswer": {
"@type": "Answer",
"text": "<head> 또는 <body> 어디든 가능. <head> 권장."
}
}]
}
Next.js 13+ App Router 동적 생성
// app/blog/[slug]/page.tsx
export default async function Page({ params }) {
const post = await getPost(params.slug);
const jsonLd = {
"@context": "https://schema.org",
"@type": "Article",
headline: post.title,
datePublished: post.publishedAt,
author: { "@type": "Person", name: post.author },
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<article>{/* content */}</article>
</>
);
}
@graph로 다중 entity 연결
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "Organization", "@id": "https://example.com/#org", "name": "Example" },
{ "@type": "WebSite", "@id": "https://example.com/#site", "publisher": { "@id": "https://example.com/#org" } },
{ "@type": "WebPage", "@id": "https://example.com/page#webpage", "isPartOf": { "@id": "https://example.com/#site" } }
]
}
검증 (Node 스크립트)
// scripts/validate-jsonld.mjs
import { readFileSync } from "fs";
const html = readFileSync(process.argv[2], "utf8");
const matches = html.matchAll(/<script type="application\/ld\+json">([\s\S]*?)<\/script>/g);
for (const m of matches) {
try { JSON.parse(m[1]); console.log("OK"); }
catch (e) { console.error("INVALID:", e.message); process.exit(1); }
}
매 결정 기준
| 상황 | Approach |
|---|---|
| 단일 entity 페이지 | 단순 @type 객체 |
| 다중 entity (sitelinks 노리기) | @graph 배열 |
| CMS/headless | 빌드 시 SSG/SSR로 inject |
| 동적 콘텐츠 (가격 변동) | SSR로 매 요청 생성 |
기본값: SSR로 page-level JSON-LD 생성 + Google Rich Results Test로 검증.
🔗 Graph
- 부모: SEO, Schema.org
- 변형: Microdata, RDFa
- 응용: Rich-Snippets, Knowledge-Graph, AI-Search-Optimization
- Adjacent: Open-Graph-Protocol, Twitter-Cards, Sitemap-XML
🤖 LLM 활용
언제: schema 자동 생성 (페이지 콘텐츠 → JSON-LD), 누락 type 추천, validation 에러 해석. 언제 X: Schema.org spec의 정확성 검증 (LLM이 deprecated property 추천 가능 — 항상 Google Rich Results Test로 cross-check).
❌ 안티패턴
- Hidden content: 페이지에 없는 정보를 JSON-LD에만 — Google penalty.
- 잘못된 @type: Article인데 Product로 — 무시됨.
- 다중 동일 type: 한 페이지에 Article 3개 — 어떤 게 main인지 모호.
- 수동 매번 작성: template/helper 없이 — 일관성 깨짐, typo.
- 검증 누락: production 배포 후 무효 JSON 발견.
🧪 검증 / 중복
- Verified (Google Search Central docs, schema.org 2026).
- 신뢰도 A.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — 매 format, Next.js App Router 패턴, @graph 추가 |