notes
JSON-LD — 구조화 데이터가 뭔지 (쉬운 설명)
검색엔진이 페이지 의미를 읽게 돕는 JSON-LD(구조화 데이터)를 비개발자도 이해할 수 있게 풀어 쓴 개념 노트.
한 줄로
JSON-LD는 검색엔진이 웹페이지 콘텐츠의 「의미」를 schema.org라는 약속된 용어로 기계가 읽게 담아 두는 구조화 데이터 형식이다.
도서관으로 치면, 책표지·목차만으로도 사람은 대충 알 수 있지만, 사서(검색엔진)는 바코드·명찰이 있으면 「이건 요리책이고, 저자는 누구고, 발행일은 언제」를 훨씬 덜 헷갈리고 잡는다. 바코드가 책 내용을 대신하진 않는다. 다만 무엇이 무엇인지를 같은 말로 말해 주는 역할이다.
JSON-LD는 그 이름 그대로 JavaScript Object Notation for Linked Data — JSON으로 쓴 링크드 데이터다. W3C 쪽과도 맞닿아 있는 형식이고, 웹에서 「이 덩어리는 구조화 데이터야」라고 표시할 때 많이 쓰인다.
왜 필요한가 — 사람과 검색엔진이 페이지를 보는 차이
사람은 레이아웃, 큰 제목, 별 아이콘, 「조리 시간 30분」 같은 글씨를 보고 바로 맥락을 잡는다. 「아, 블로그 글이구나」「리뷰네」「이벤트 날짜네」.
검색엔진은 기본적으로 HTML 글자열을 읽어서 해석한다. <div>, <span> 안에 글자가 잔뜩 있어도, 그게 리뷰인지 광고인지, 날짜가 본문인지 사이드바인지를 사람만큼 쉽게 단정하지 못한다. 그래서 「이름표」를 붙여 주면 — 「이 페이지의 이 정보는 Organization(회사·단체)이고, 이름은 ○○다」 — 문맥 파악이 훨씬 명확해진다.
이 이름표를 페이지에 붙이는 방법을 넓게는 구조화 데이터(structured data) 라고 부르고, 그중 지금 웹에서 가장 흔히 쓰는 형식이 JSON-LD다.
구조화 데이터란 / schema.org란
구조화 데이터는 「페이지에 보이는 정보를, 기계가 정해진 칸에 맞춰 읽을 수 있게 적어 둔 것」이다. 사람용 문장만 두지 말고, 「타입은 뭐고, 이름은 뭐고, 주소는 뭐」처럼 칸이 있는 기록을 같이 두는 셈이다.
schema.org는 그 칸과 이름표를 모아 둔 약속된 이름표 사전이다. 구글·빙·야후 등이 함께 쓰는 쪽이라, 「Organization = 회사·단체」「Product = 상품」「Article = 글·기사」처럼 서로 다른 사이트도 같은 말로 말할 수 있다. 「스키마」라고 하면 거창해 보이는데, 실무에서는 「이 타입·이 속성 이름으로 쓰자」는 공통 단어장에 가깝다.
JSON-LD는 그 이름표를 JSON 한 덩어리로 적어 HTML에 넣는 방식이다. 페이지 본문을 일일이 속성으로 찌르지 않아도 된다.
JSON-LD vs Microdata vs RDFa — 왜 구글이 JSON-LD를 좋아하나
구조화 데이터를 붙이는 방식이 여러 가지다.
구글 Search Central 쪽에서는 대규모로 넣고 고치기 쉽다는 이유로 JSON-LD를 권하는 편이다. 「다른 방식이 틀렸다」가 아니라, 실무에서 다루기 편한 쪽을 밀어 준다에 가깝다. 나는 새 사이트나 Astro 블로그에 넣을 때도 거의 JSON-LD로 간다.
어떻게 붙이나
보통은 HTML의 <head> 안, 또는 <body> 끝에 이런 식으로 한 블록을 넣는다.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "예시 회사",
"url": "https://example.com"
}
</script>
화면에는 안 보인다. 브라우저가 「이건 실행할 JS가 아니라, ld+json 데이터구나」하고 넘기고, 검색엔진 크롤러가 읽어서 해석한다.
자주 나오는 키만 쉽게 풀면 이렇다.
@context: 「이 JSON의 단어는 schema.org 사전을 따른다」는 선언. 거의 항상"https://schema.org"를 넣는다.@type: 이게 뭔 종류인지 — Organization, Article, Product… 이름표의 종류.@id: 「이 개체의 고유 주소(식별자)」. 같은 회사를 여러 페이지에서 말할 때, URL 같은 걸로 한 존재를 가리키게 할 때 쓴다. 처음엔 없어도 예제는 돌아가지만, 사이트 전체로 키우면 정리에 도움이 된다.
나머지는 @type에 따라 name, url, logo, image 같은 속성(칸) 이 붙는다.
Organization 예시 — 필드가 의미하는 바
회사·브랜드·팀 사이트의 「우리 누구임」을 말할 때 기본이 되는 타입이 Organization이다.
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "블로그",
"url": "https://example.example",
"logo": "https://example.example/logo.png",
"sameAs": [
"https://www.instagram.com/example",
"https://blog.example.com"
]
}
포인트는 화면에 실제로 있는 이야기와 맞출 것. 로고 URL이 깨져 있거나, 이름만 바꾸고 본문·푸터와 다르면 의미가 없다. 검색엔진은 「이 페이지가 말하는 조직」과 「구조화 데이터가 말하는 조직」이 한통속인지 본다.
리치 결과란 / 순위와의 관계
구조화 데이터가 잘 잡히면, 검색 결과에 별점, 요리 시간, 이벤트 일시, FAQ 펼침 같은 리치 결과(rich result) 후보가 될 수 있다. 평범한 파란 링크 한 줄보다 정보가 풍부해 보이니, 눈에 띄고 클릭될 가능성은 올라갈 수 있다.
다만 구글이 반복해서 말하는 핵심이 있다.
자격만 된다고 항상 리치 결과가 뜨는 것도 아니다. 유형별 가이드 충족, 품질, 쿼리·지역 등 여러 조건이 겹친다. 「넣었으니 끝」이 아니라 「넣을 자격은 만들어 둔다」로 보면 마음이 편하다.
사이트 전체 SEO 맥락은 땡큐캠핑 SEO 쪽에 더 있고, 검색·AI 노출 쪽은 GEO(생성형 엔진 최적화) — SEO와 무엇이 다른가, 크롤·인덱싱 신호는 메타 robots 태그 — 정의·지시어·사용법 와 같이 보면 그림이 맞는다.
자주 쓰는 @type — 「이런 페이지에 이런 이름표」
유형별 풀코드는 이 글 범위가 아니다. 다만 이름표가 무엇을 위한 것인지만 짧게.
「블로그면 무조건 BlogPosting만」이 아니다. 홈에는 Organization + WebSite, 글에는 BlogPosting, 상품이면 Product… 페이지가 실제로 무엇인지에 맞추면 된다. 엉뚱한 타입을 붙이면 이름표가 거짓말하는 꼴이다.
여러 개 script / @graph
한 페이지에 JSON-LD <script> 블록이 여러 개 있어도 된다. 예: Organization 하나, BlogPosting 하나.
한 블록 안에 여러 개체를 넣을 때는 @graph 배열로 묶는 패턴도 흔하다. 「이 문맥 안에 A도 있고 B도 있다」를 한 JSON에 모아 두는 방식이다.
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "Organization", "name": "…" },
{ "@type": "WebSite", "name": "…", "url": "…" }
]
}
처음엔 script를 타입별로 나눠 두고, 나중에 정리하고 싶어질 때 @graph를 봐도 늦지 않다.
주의할 것 — 그리고 테스트
구조화 데이터에서 제일 흔한 사고는 기술 문법 오류보다 「내용이 거짓말」 이다.
- 화면에 없는 내용을 넣지 않기 — 없는 별점, 가짜 리뷰, 안 보이는 가격·재고.
- 타입을 끼워 맞추지 않기 — FAQ가 아닌데 FAQPage, 가게가 아닌데 LocalBusiness.
- 필수에 가까운 칸 빼먹지 않기 — 유형마다 「이게 없으면 리치 결과 후보도 안 됨」인 속성이 있다. (상세는 유형 가이드를 보면 된다. 이 글은 개념이니 목록만 안다.)
- 배포 후 방치하지 않기 — 로고 URL이 바뀌었는데 JSON-LD만 예전 주소인 경우.
확인 순서는 단순하다.
- 사람 눈으로 본문·화면에 있는 말과 JSON이 같은지.
- 구글 리치 결과 테스트에 URL이나 코드 조각을 넣어 문법·필수값·유형 자격 확인.
- 실제 사이트에 올린 뒤에는 Search Console(GSC) 에서 해당 리치 결과·구조화 데이터 관련 보고가 쌓이는지 본다.
테스트 도구 이름이 바뀔 수는 있어도, 「미리 검사 → 배포 후 GSC」 흐름은 같다.
블로그(Astro 등)에 넣는 위치 — 개념만
구현 풀코드는 SEO 작업 문서 쪽이 맞고, 개념만 말하면 이렇다.
- 사이트 공통(Organization, WebSite 등) → 레이아웃 한곳(예:
BaseLayout)에 두면 모든 페이지에 따라간다. - 글·상품마다 다른 것(BlogPosting, Product 제목·날짜·이미지) → 그 페이지 데이터에서 만들어 그 페이지에만 넣는다.
Astro면 frontmatter·콘텐츠 컬렉션 값을 읽어 <script type="application/ld+json"> 에 JSON.stringify 로 넣는 식이 흔하다. 「어디에 두느냐」만 먼저 정하면, 코드는 그에 맞춰 짧아진다. 민섭 블로그 SEO 정리와 이 글을 같이 보면 「왜 붙이는지 / 어디에 붙이는지」가 한 세트가 된다.
정리
- JSON-LD = 페이지 의미를 schema.org 이름표로, JSON 한 덩어리로 검색엔진에게 전달하는 형식.
- Microdata/RDFa처럼 HTML에 속성을 흩뿌리지 않고,
application/ld+jsonscript로 분리해 두는 쪽이 유지보수에 유리해서 구글도 밀어 주는 편. - 효과의 중심은 리치 결과·문맥 파악. 직접 순위 가산점은 아님.
- Organization 같은 기본 타입부터, 화면과 같은 말을 쓰는지가 전부다.
- 붙인 뒤에는 리치 결과 테스트 → GSC로 확인.
이름표는 콘텐츠를 대신하지 않는다. 좋은 글·정확한 상품 정보가 본체고, JSON-LD는 그걸 기계가 덜 헷갈리게 읽는 명찰이다.