포케코리아 SEO 개선기 2편 — JSON-LD 구조화 데이터로 검색 노출 강화하기
퀴즈 페이지 5개의 BreadcrumbList 오류 수정, ItemList·HowTo JSON-LD 추가, 메타데이터 상수화, thin content 해소까지 12가지 SEO 개선을 체계적으로 적용한 과정을 정리합니다.
들어가며
이 글은 포케코리아 SEO 개선기 시리즈의 두 번째 글입니다.
1편 Path URL 전환 → 2편 JSON-LD 구조화 데이터 → 3편 기술 도감 URL 마이그레이션
포케코리아에는 실루엣 퀴즈, 특성 퀴즈, 타입 퀴즈, 타입 상성 퀴즈 4종류의 퀴즈가 있다. 메인 퀴즈 페이지(/quiz)와 개별 퀴즈 페이지 4개, 총 5개 페이지의 SEO를 점검한 결과 여러 문제가 발견되었다.
- BreadcrumbList JSON-LD에 잘못된 name 값
- 개별 퀴즈 페이지에 url 필드 누락
- Title과 Description이 구체적이지 않음
- 텍스트 콘텐츠가 부족한 thin content
- 앵커 텍스트가 모든 퀴즈에서 동일한 “시작하기 →”
외부 SEO 리뷰 피드백도 반영하여 총 12가지 변경을 진행했다.
JSON-LD 구조화 데이터란
JSON-LD(JavaScript Object Notation for Linked Data)는 Google이 공식 권장하는 구조화 데이터 형식이다. HTML의 <script> 태그 안에 작성하여 검색엔진에게 페이지의 의미를 전달한다.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "포켓몬 퀴즈",
"url": "https://poke-korea.com/quiz"
}
</script>
Microdata나 RDFa와 달리 HTML 본문과 분리되어 있어 유지보수가 쉽고, 동적으로 생성하기도 편하다. Google은 올바른 구조화 데이터를 적용하면 리치 결과(Rich Results)로 표시할 수 있다고 안내한다.
변경 1~4: JSON-LD 오류 수정 및 보강
BreadcrumbList name 오류 수정
메인 퀴즈 페이지의 BreadcrumbList에 잘못된 name이 들어가 있었다.
// Before — "타입 상성 계산기"라는 다른 페이지의 이름이 들어가 있었음
{ position: 2, name: '타입 상성 계산기', item: 'https://poke-korea.com/quiz' }
// After
{ position: 2, name: '포켓몬 퀴즈', item: 'https://poke-korea.com/quiz' }
BreadcrumbList는 검색 결과에서 URL 대신 탐색 경로로 표시되기 때문에, name이 실제 페이지와 일치하지 않으면 사용자에게 혼란을 준다.
ItemList 추가
메인 퀴즈 페이지에 4가지 퀴즈 종류를 ItemList로 구조화했다.
const QUIZ_ITEMLIST_JSON_LD = {
'@context': 'https://schema.org',
'@type': 'ItemList',
name: '포켓몬 퀴즈 목록',
numberOfItems: 4,
itemListElement: [
{ position: 1, name: '포켓몬 실루엣 퀴즈', url: '...' },
{ position: 2, name: '포켓몬 특성 퀴즈', url: '...' },
{ position: 3, name: '포켓몬 타입 퀴즈', url: '...' },
{ position: 4, name: '포켓몬 타입 상성 퀴즈', url: '...' },
],
};
ItemList를 추가하면 Google이 퀴즈 종류 간의 관계를 이해하고, 캐러셀 형태의 리치 결과로 노출할 가능성이 생긴다.
primaryImageOfPage 추가
5개 퀴즈 JSON-LD 모두에 primaryImageOfPage 필드를 추가했다. 기존에 단순 문자열이었던 image 필드를 ImageObject 구조로 교체했다.
primaryImageOfPage: {
'@type': 'ImageObject',
url: 'https://poke-korea.com/assets/image/ogImage.png',
width: 1200,
height: 630,
},
OG 이미지와 동일한 이미지를 지정하여 일관성을 유지했다. width, height를 명시하면 Google 이미지 검색 최적화에도 도움이 된다.
개별 퀴즈 url 필드 추가
4개 개별 퀴즈 JSON-LD에 각 페이지의 url 필드가 빠져 있었다. 메인 퀴즈에만 있던 것을 모두 추가했다.
변경 5~6: 메타데이터 상수화와 재작성
인라인 메타데이터를 상수로 추출
각 page.tsx에 약 30줄씩 인라인으로 작성되어 있던 메타데이터를 seoMetaData.ts로 이관했다. createQuizMetadata 헬퍼 함수로 공통 구조를 생성하고, 각 페이지에서는 상수를 import만 하면 된다.
// Before — 각 page.tsx에 ~30줄
export const metadata: Metadata = {
title: '...',
description: '...',
robots: getRobotsConfig(),
openGraph: { ... },
alternates: { ... },
twitter: { ... },
};
// After — 각 page.tsx에 1줄
import { QUIZ_MAIN_META } from '~/constants/seoMetaData';
export const metadata = QUIZ_MAIN_META;
5개 페이지에서 약 150줄의 중복 코드가 제거되었다.
Title과 Description 재작성
외부 SEO 리뷰에서 가장 우선순위가 높았던 피드백이 Title과 Description의 구체성 부족이었다.
// Before
title: '포켓몬 퀴즈 | 포케 코리아'
description: '다양한 포켓몬 퀴즈를 통해 여러분의 포켓몬 지식을 테스트해보세요!'
// After
title: '포켓몬 퀴즈 모음 (실루엣·특성·타입·상성) | 포케 코리아'
description: '실루엣, 특성, 타입, 타입 상성까지 4종류의 포켓몬 퀴즈를 20문제 4지선다로 풀어보세요. 완료 후 결과를 바로 확인할 수 있습니다.'
개별 퀴즈도 문제 수(20문제)와 형식(4지선다)을 Title에 명시했다. JSON-LD의 name, description도 메타데이터와 일치하도록 동기화했다.
변경 7: 앵커 텍스트 개선
퀴즈 메인 페이지의 카드 링크가 모두 동일한 “시작하기 →“를 사용하고 있었다. Google SEO 가이드에서는 설명적인 앵커 텍스트를 권장한다.
// Before — 모든 퀴즈 카드에서 동일
<span>시작하기 →</span>
// After — 퀴즈별 구체적 텍스트 + aria-label
<Link aria-label={`${quiz.title} 시작하기`}>
<span>{quiz.title} 시작하기 <span aria-hidden="true">→</span></span>
</Link>
“시작하기”에서 “포켓몬 실루엣 퀴즈 시작하기”로 변경하여 검색엔진이 링크 대상 페이지의 내용을 파악할 수 있게 했다. aria-label도 추가하여 접근성도 함께 개선했다.
변경 8~9: Thin Content 해소
문제: 텍스트가 부족한 페이지
Thin content는 사용자에게 실질적인 가치를 제공하지 못하는 빈약한 콘텐츠를 말한다. Google의 Helpful Content System은 이런 페이지가 많은 사이트의 전체 순위를 하락시킬 수 있다.
퀴즈 페이지들이 이에 해당했다. 메인 퀴즈 페이지는 약 200자, 개별 퀴즈의 BeforeStage는 약 80자(4줄 리스트)에 불과했다.
해결: 설명 콘텐츠 블록 추가
각 퀴즈별 SEO 텍스트 콘텐츠(300~500자)를 quiz.constants.ts에 상수로 정의하고, 페이지에 설명 섹션을 추가했다.
| 위치 | Before | After |
|---|---|---|
| 메인 퀴즈 페이지 | ~200자 | ~500자 |
| 개별 퀴즈 BeforeStage | ~80자 | ~400자 (설명 3섹션 + 기존 리스트) |
각 퀴즈에 “퀴즈 소개”, “어떤 문제가 나오나요?”, “난이도 안내” 3개 섹션을 추가하여 페이지별 고유한 콘텐츠를 확보했다.
내부 링크 확장
thin content 해소와 함께 크롤링 경로도 개선했다. BeforeStage와 Result 화면에 두 종류의 내부 링크를 추가했다.
| 퀴즈 | 관련 페이지 링크 | 교차 퀴즈 링크 |
|---|---|---|
| 실루엣 퀴즈 | /list (포켓몬 도감) | 특성, 타입, 타입 상성 퀴즈 |
| 특성 퀴즈 | /ability (특성 도감) | 실루엣, 타입, 타입 상성 퀴즈 |
| 타입 퀴즈 | /list (포켓몬 도감) | 실루엣, 특성, 타입 상성 퀴즈 |
| 타입 상성 퀴즈 | /type-effectiveness (계산기) | 실루엣, 특성, 타입 퀴즈 |
관련 도감 페이지로의 링크와 다른 퀴즈로의 교차 링크를 추가하여 크롤러가 사이트 내 페이지를 더 효율적으로 탐색할 수 있게 했다.
변경 10~12: 코드 패턴 통일과 HowTo 추가
컴포넌트 패턴 통일
코드 리뷰를 거쳐 4개 퀴즈의 BeforeStage와 Result 컴포넌트를 동일한 패턴으로 통일했다. 인라인 렌더링을 공유 컴포넌트(OtherQuizLink)로 추출하고, 링크 색상을 프로젝트 디자인 시스템(text-primary-2)에 맞췄다.
HowTo JSON-LD 추가
개별 퀴즈 4개 페이지에 HowTo 타입 JSON-LD를 추가했다. 3단계 구조로 퀴즈 진행 과정을 설명한다.
| Step | 내용 |
|---|---|
| 1 | 시작하기 버튼으로 20문제 4지선다 시작 |
| 2 | (퀴즈별 상이) 문제 풀이 방법 안내 |
| 3 | 점수, 정답률, 소요 시간 및 오답 확인 |
참고: Google은 2023년 9월부터 HowTo 리치 결과 지원을 축소했다. 리치 결과로 직접 표시되지는 않지만, 페이지 내용을 이해하는 보조 신호로는 여전히 활용될 수 있다.
WebPage description 보강
개별 퀴즈 4개의 WebPage JSON-LD description을 quiz.constants.ts의 상세 설명 텍스트와 동기화했다.
// Before
description: '검은 실루엣만 보고 포켓몬 이름을 맞춰보세요!'
// After
description: '실루엣 퀴즈는 검은 그림자로 가려진 포켓몬의 외형만 보고 어떤 포켓몬인지 맞추는 퀴즈입니다.'
결과
전체 변경 요약
| 항목 | Before | After |
|---|---|---|
| BreadcrumbList | 오류 (잘못된 name) | 정상 |
| ItemList | 미적용 | 4개 퀴즈 목록 구조화 |
| primaryImageOfPage | 1개 (문자열) | 5개 (ImageObject) |
| url 필드 | 1개 | 5개 |
| 메타데이터 관리 | 인라인 (~150줄 중복) | 상수 1개 파일 |
| Title 구체성 | 일반적 제목 | 퀴즈 종류·문제 수 명시 |
| 앵커 텍스트 | ”시작하기 →” (동일) | “{퀴즈명} 시작하기 →“ |
| 메인 퀴즈 텍스트 | ~200자 | ~500자 |
| 개별 퀴즈 텍스트 | ~80자 | ~400자 |
| 내부 링크 (BeforeStage) | 0개 | 관련 1개 + 교차 3개 |
| 수정 파일 수 | — | 약 30개 |
검증 방법
Google Rich Results Test에서 각 퀴즈 페이지 URL을 입력하여 구조화 데이터의 유효성을 확인했다. BreadcrumbList, ItemList, WebPage 모두 오류 없이 감지되었다.
정리하며
이번 작업에서 가장 효과적이었던 것은 외부 SEO 피드백을 체계적으로 반영한 것이다. Title/Description 재작성, 앵커 텍스트 구체화, thin content 해소는 내부에서는 놓치기 쉬운 부분이었다.
JSON-LD 구조화 데이터는 리치 결과 노출이라는 직접적 효과도 있지만, 검색엔진이 페이지의 맥락을 정확히 이해하도록 돕는 간접적 효과가 더 크다. BreadcrumbList 하나의 name 오류가 전체 탐색 경로 표시를 망칠 수 있듯, 작은 실수가 큰 영향을 미칠 수 있다.
다음 편에서는 기술 도감 페이지의 URL 마이그레이션과 useSearchParams에서 Context로의 전환 과정을 다룬다.
포케코리아 SEO 개선기 시리즈
- 1편: 쿼리 파라미터에서 Path URL로 전환하기
- 2편: JSON-LD 구조화 데이터로 검색 노출 강화하기 (현재 글)
- 3편: 기술 도감 URL 마이그레이션과 Context 전환