스키마 마크업(Schema Markup)은 schema.org 어휘를 JSON-LD·Microdata·RDFa 형식으로 삽입해 크롤러가 콘텐츠의 의미를 명시적으로 파악할 수 있도록 하는 구조화 데이터 레이어다. Google은 자연어 파싱보다 구조화 데이터를 우선 참조해 Rich Result(별점·가격·FAQ·이벤트 등 강화 결과)를 생성하고, Perplexity·ChatGPT Search 같은 LLM 기반 답변 엔진도 잘 정의된 엔티티 신호를 인용 판단에 활용한다. 문제는 "스키마를 얼마나, 어떤 유형으로, 어느 페이지에" 넣어야 실제 색인·랭킹·인용에 영향을 주는가다. "많이 넣을수록 좋다"는 인식은 오해이며, 페이지 유형별 목적 기반 우선순위가 핵심이다.
스키마가 실제로 처리되는 경로
Googlebot이 페이지를 크롤링하면 HTML 파싱 → JavaScript 렌더링(WRS, Web Rendering Service) → 구조화 데이터 추출 순서를 밟는다. JSON-LD는 DOM 외부 script 태그에 독립 삽입되므로 렌더링 지연과 무관하게 추출된다. Microdata·RDFa는 HTML 요소 속성에 의존하므로 렌더링 완료 후 파싱된다.
- JSON-LD 권장 이유: DOM 조작 없이
head나body어디에도 삽입 가능 — SPA 동적 삽입 시 오류율이 Microdata보다 낮고 유지보수가 단순하다. - 복수 블록 허용: 한 페이지에 JSON-LD 블록을 여러 개 삽입해도 유효 — Article·BreadcrumbList·FAQPage를 각각 분리하면 한 블록 파싱 실패가 다른 블록에 영향을 주지 않는다.
- 동적 삽입 주의: Next.js에서
useEffect로 JSON-LD를 주입하면 WRS가 렌더링 전에 해당 블록을 못 잡을 수 있다 — App Router의 서버 컴포넌트에서 직접 반환하거나pages/_document.tsx에서 서버사이드 렌더링으로 넣어야 한다. - LLM 파이프라인 처리: Perplexity·Bing Copilot은 크롤링 시점에
application/ld+json블록을 직접 파싱해 엔티티·관계·날짜 신호를 추출하는 것으로 분석된다 — Organization의sameAs, Article의dateModified가 인용 신뢰도 신호로 작동한다.
페이지 유형별 우선순위 스키마와 Rich Result 조건
Google이 Rich Result로 렌더링하는 스키마 유형은 한정적이다. 지원 목록 외 타입은 색인 보조에는 쓰이지만 SERP 강화 결과로 표면화되지 않는다. 아래는 기술 블로그 포스트에 바로 적용 가능한 Article + BreadcrumbList 복합 JSON-LD 예시다.
<script type="application/ld+json">
[
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "스키마 마크업, 어디까지 해야 효과가 있을까",
"description": "JSON-LD 구조, Rich Result 조건, LLM 인용 신호까지 구조화 데이터의 실제 효과 범위와 구현 우선순위",
"author": {
"@type": "Person",
"name": "정유진",
"url": "https://example.com/authors/jeongyujin"
},
"publisher": {
"@type": "Organization",
"name": "Citeon",
"@id": "https://example.com/#organization",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png",
"width": 600,
"height": 60
}
},
"datePublished": "2026-06-18T09:00:00+09:00",
"dateModified": "2026-06-18T09:00:00+09:00",
"image": {
"@type": "ImageObject",
"url": "https://example.com/images/schema-markup-og.jpg",
"width": 1200,
"height": 630
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://example.com/blog/schema-markup-depth"
}
},
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "홈", "item": "https://example.com" },
{ "@type": "ListItem", "position": 2, "name": "블로그", "item": "https://example.com/blog" },
{ "@type": "ListItem", "position": 3, "name": "스키마 마크업, 어디까지 해야 효과가 있을까",
"item": "https://example.com/blog/schema-markup-depth" }
]
}
]
</script>
- image 필드는 필수: Article Rich Result(Top Stories 포함) 자격 요건에 width·height를 포함한
ImageObject가 필요하다 — 문자열 URL만 넣으면 경고 발생. - dateModified 분리 관리: 콘텐츠 실질 변경 시에만 갱신해야 한다 — 레이아웃·광고 수정을 이유로 매일 갱신하면 freshness 신호 조작으로 간주될 수 있다.
- FAQPage 2023년 이후 제한: 데스크톱 FAQ Rich Result는 의료·정부 사이트에만 표시되도록 축소됐다 — 그러나 LLM 엔진의 Q&A 직접 인용 효과는 여전히 유효하므로 지원 문서 페이지에는 계속 사용한다.
스키마 유형·목적·지원 엔진 비교
| 스키마 유형 | Google Rich Result | AEO/GEO 인용 효과 | 필수 필드 | 우선 적용 페이지 |
|---|---|---|---|---|
| Article | Top Stories (모바일) | 높음 — 날짜·저자 신호 | headline, datePublished, author, image | 블로그·뉴스 |
| FAQPage | 의료·행정 한정(2023~) | 매우 높음 — Q&A 직접 인용 | mainEntity, acceptedAnswer | 지원·문서 페이지 |
| Product + Offer | 쇼핑 Rich Result | 중간 — 가격·재고 파악 | name, offers.price, offers.priceCurrency | 상품 상세 |
| Organization | Knowledge Panel | 높음 — 브랜드 엔티티 확립 | name, url, logo, sameAs | 홈·About |
| BreadcrumbList | URL 경로 표시 | 낮음 | itemListElement[].name/item/position | 전 페이지 범용 |
| HowTo | 단계 표시 (모바일) | 중간 — 절차 인용 | step[].name, step[].text | 튜토리얼·가이드 |
검증과 측정: 세 단계 체크포인트
- Rich Results Test (
search.google.com/test/rich-results) — URL 또는 HTML 붙여넣기로 파싱 결과·경고·오류를 즉시 확인한다. "경고(warning)"는 Rich Result 박탈 사유가 아닐 수 있지만, 필수 필드 누락 오류는 즉시 수정 대상이다. - Search Console → 검색결과 모양새 → 강화 항목 — 인덱싱된 페이지 기준 유효·오류·경고 건수와 트렌드를 확인한다. 대규모 배포 후 오류 급증 감지에 적합하며 개선 전후 CTR 비교 기준선을 여기서 잡는다.
- Schema.org Validator (
validator.schema.org) — Google 외 파서(Bing, LLM 파이프라인)가 읽는 방식을 점검한다. JSON-LD 문법 오류가 Google에서는 허용되지만 다른 파서에서 깨지는 경우가 있다.
흔한 오해: 스키마를 많이 넣을수록 순위가 오른다
스키마 마크업은 직접적인 랭킹 신호가 아니다. Google은 공식 문서에서 구조화 데이터를 랭킹 인자로 사용하지 않는다고 명시했다. 스키마의 실제 효과 경로는 두 가지다. 첫째, SERP 강화 결과(Rich Result) 활성화로 CTR을 높이는 간접 효과. 둘째, Knowledge Graph·LLM 파이프라인에서 엔티티를 정확히 인식하게 해 인용·패널 노출을 늘리는 AEO/GEO 효과다.
올바른 처리법: 각 페이지의 주된 콘텐츠 유형에 정확히 대응하는 스키마만 삽입한다. 블로그 포스트에 Product를 삽입하거나, 자사 사이트와 무관한 외부 엔티티를 mainEntityOfPage로 지정하는 것은 Google Webmaster Guidelines "오해를 일으키는 구조화 데이터" 위반 사유다. AggregateRating을 직접 수집하지 않은 리뷰로 채우는 것도 정책 위반이며, 수동 조치(Manual Action) 대상이 될 수 있다.
@id와 sameAs를 반드시 채워야 하나요?
@id는 엔티티를 URL로 고유 식별하는 IRI다. Organization이나 Person에서 지정하면 Google Knowledge Graph가 해당 엔티티를 Wikipedia·Wikidata 같은 외부 출처와 연결할 때 참조 포인트로 쓴다. sameAs에는 공식 외부 프로파일(Wikidata Q 번호 URL, LinkedIn 기업 페이지, Crunchbase 등)을 배열로 나열한다. 두 필드 모두 Rich Result 필수 조건은 아니지만, AEO·GEO에서 LLM이 브랜드 엔티티를 정확히 인식하고 인용할 때 신뢰 신호로 강하게 작동한다. 실무 권장: 홈페이지 Organization 스키마에는 항상 포함하고, 블로그·상품 페이지의 publisher·author에도 @id로 동일 Organization을 참조시킨다.
Next.js App Router에서 페이지마다 JSON-LD를 서버사이드로 삽입하는 가장 안전한 방법은 무엇인가요?
App Router의 서버 컴포넌트(Server Component)에서 아래처럼 dangerouslySetInnerHTML로 직접 렌더링하는 것이 가장 안전하다. generateMetadata는 meta 태그만 제어하므로 JSON-LD에는 사용할 수 없다.
// app/blog/[slug]/page.tsx (Server Component)
export default async function BlogPost({ params }) {
const post = await getPost(params.slug)
const jsonLd = {
"@context": "https://schema.org",
"@type": "Article",
"headline": post.title,
"datePublished": post.publishedAt,
"dateModified": post.updatedAt,
"author": { "@type": "Person", "name": post.author }
}
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<article>{/* 콘텐츠 */}</article>
</>
)
}
이 방식은 HTML에 정적으로 포함되어 WRS 렌더링 큐 지연과 무관하게 Googlebot이 초기 응답에서 즉시 파싱한다. useEffect 내 동적 삽입은 Googlebot에게 인식될 보장이 없어 권장하지 않는다.
참고 자료
이 글의 권고는 아래 공식 문서·연구를 근거로 합니다.