---
id: wiki-2026-0508-json-ld-structured-data
title: JSON-LD Structured Data
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [JSON-LD, Structured Data, Schema.org JSON-LD]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [seo, json-ld, schema-org, structured-data, web]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
  language: javascript
  framework: schema.org
---

# 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 묶음.

### 매 응용
1. E-commerce → Product + Offer + AggregateRating.
2. 미디어/블로그 → Article + Author(Person) + Publisher(Organization).
3. 로컬 비즈니스 → LocalBusiness + Address + OpeningHours.
4. FAQ/HowTo → FAQPage / HowTo (rich snippet 가시성 매우 높음).
5. SaaS → SoftwareApplication + AggregateRating.

## 💻 패턴

### Article schema (블로그/뉴스)
```html
<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)
```html
<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
```json
{
  "@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 효과 큼)
```json
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [{
    "@type": "Question",
    "name": "JSON-LD를 어디에 넣어야 하나요?",
    "acceptedAnswer": {
      "@type": "Answer",
      "text": "<head> 또는 <body> 어디든 가능. <head> 권장."
    }
  }]
}
```

### Next.js 13+ App Router 동적 생성
```tsx
// 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 연결
```json
{
  "@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 스크립트)
```js
// 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 추가 |
