본문으로 건너뛰기
피드

개인 웹사이트에 JSON-LD 넣는 법, 검색엔진과 크롤러가 내 사이트를 제대로 읽게 만들기

frontend 약 9분
vote
0
댓글
북마크

개인 웹사이트에 JSON-LD 구조화 데이터를 추가해 검색엔진과 크롤러가 사이트, 사람, 글, 프로젝트를 더 정확히 이해하게 만드는 실전 가이드야. WebSite, Person, ProfilePage, BlogPosting 같은 노드를 어떻게 연결하고 어느 페이지에 넣어야 하는지 예시 중심으로 설명해.

  • 1

    JSON-LD는 브라우저가 실행하는 자바스크립트가 아니라 크롤러가 읽는 구조화 데이터임

  • 2

    개인 사이트는 WebSite, Person, ProfilePage, BlogPosting 같은 노드를 연결하면 검색 결과와 지식 그래프 표현이 좋아질 수 있음

  • 3

    같은 @id를 여러 페이지에서 재사용하면 크롤러가 노드 정보를 병합할 수 있음

  • 4

    LLM 크롤러처럼 한 페이지만 읽는 수집기도 있으므로 페이지마다 최소한의 맥락을 넣는 균형이 필요함

  • JSON-LD는 개인 웹사이트에 “이 페이지가 무엇인지”를 크롤러에게 구조적으로 알려주는 방법임

    • 정식 이름은 JSON Linked Data고, HTML의 <head> 안에 <script type="application/ld+json"> 형태로 넣음
    • MIME 타입이 application/ld+json이라 브라우저 자바스크립트 엔진이 실행하지 않고, 구글봇 같은 전문 크롤러가 내용을 파싱함
    • 잘 넣으면 검색 결과의 사이트 이름, 경로, 작성자 정보, 링크 미리보기 같은 표현이 더 풍부해질 수 있음
  • 핵심 구조는 @context@graph임. 어렵게 들리지만, 결국 “어떤 규칙으로 어떤 객체들을 설명할지”를 정하는 방식임

    • @context에는 보통 https://schema.org를 넣고, 이게 JSON 안의 키와 타입을 해석하는 기준이 됨
    • @graph에는 WebSite, Person, BlogPosting 같은 노드들이 들어감
    • 각 노드는 @type으로 종류를 밝히고, @id로 고유 식별자를 갖고, 나머지 속성으로 세부 정보를 표현함

중요

> 같은 @id를 여러 페이지에서 재사용하면 크롤러가 같은 노드의 정보를 병합할 수 있음. 다만 LLM 크롤러처럼 한 페이지만 읽는 수집기도 있으니, 중요한 맥락은 각 페이지에 어느 정도 반복해두는 게 좋음.

  • 개인 사이트의 기본 노드는 WebSite임. 사이트 전체의 이름, 주소, 설명, 대표 이미지, 게시자 정보를 알려주는 역할임

    • 예시에서는 @idhttps://hawksley.dev/#website처럼 루트 URL 뒤에 해시를 붙여 고유하게 만듦
    • 루트 페이지에는 상세한 WebSite 정보를 넣고, 다른 페이지에는 URL과 이름 정도만 넣은 가벼운 버전을 넣어도 충분하다고 설명함
    • 실제 예시에서는 구글 검색 결과가 name 값을 사이트 이름으로 해석해 표시한 장면도 보여줌
  • WebPage는 현재 HTML 페이지 자체를 설명함. 글 내용이나 사람 자체가 아니라 “이 물리적 페이지”를 가리키는 노드임

    • isPartOf로 이 페이지가 어떤 WebSite에 속하는지 연결함
    • breadcrumb로 BreadcrumbList 노드를 연결하면 검색 결과의 경로 표현을 제어할 수 있음
    • 중요한 건 BlogPosting 같은 콘텐츠 타입과 WebPage를 구분하는 것임. 하나는 페이지 컨테이너고, 하나는 그 안의 콘텐츠에 가까움
  • 개인 사이트에서는 Person 노드가 꽤 중요함. 작성자가 누구인지, 다른 프로필과 어떻게 연결되는지 알려주기 때문임

    • url, name, givenName, familyName, image, sameAs 같은 속성이 핵심으로 소개됨
    • sameAs에는 깃허브, 링크드인, 해커뉴스, Lobsters 같은 외부 프로필을 넣어 동일 인물임을 크롤러에게 알려줄 수 있음
    • 이름이 흔한 사람일수록 이런 연결이 지식 그래프에서 동명이인 문제를 줄이는 데 도움이 됨
  • ProfilePage는 자기소개 페이지나 홈 화면처럼 특정 사람을 설명하는 페이지에 붙임

    • mainEntity로 Person 노드를 연결해서 “이 페이지의 주인공은 이 사람”이라고 알려줌
    • dateCreateddateModified는 최신성 신호로 쓸 수 있지만, 사이트에 준비돼 있지 않으면 너무 집착하지 않아도 된다고 함
    • 홈이 자기소개 중심이면 루트 페이지에 쓰고, 별도 소개 페이지가 있으면 거기에 쓰는 식으로 적용하면 됨
  • 프로젝트를 보여주는 페이지라면 SoftwareApplication 노드도 쓸 만함

    • 예시 프로젝트는 Rust로 만든 유튜브 플레이리스트 동기화 CLI이고, applicationCategory, operatingSystem, creator, sameAs, offers 같은 속성을 넣음
    • 오픈소스 무료 프로젝트라도 offers를 넣고 가격을 0으로 지정하라고 설명함
    • 더 구체적으로는 MobileApplication, WebApplication, VideoGame 같은 하위 타입도 사용할 수 있음
  • BreadcrumbList는 루트가 아닌 페이지 대부분에서 쓸 수 있는 실용 노드임

    • 검색 결과에서 긴 URL 대신 사이트 › 블로그 같은 짧은 경로를 보여주는 데 도움을 줄 수 있음
    • 실제 경로와 반드시 1:1로 같을 필요는 없고, 페이지가 어떤 분류에 속하는지 표현하는 용도에 가깝다고 설명함
    • 이미 URL 구조가 짧다면 효과가 작을 수 있지만, 경로가 길거나 복잡한 사이트라면 체감이 큼
  • 블로그가 있다면 BlogBlogPosting을 나눠서 생각하는 게 좋음

    • Blog는 블로그 인덱스나 홈에 넣고, WebSite와 개별 글 사이의 중간 연결점 역할을 함
    • BlogPosting은 개별 글마다 넣고, 제목, 설명, 섹션, 키워드, 언어, 발행일, 수정일, 작성자, 대표 이미지, 라이선스를 담음
    • 개인 블로그에서는 authorpublisher가 같은 Person을 가리켜도 괜찮고, 구글 문서도 이제 Person 게시자를 허용한다고 설명함
  • 결론은 꽤 실전적임. 정적 사이트든 빌드 시스템이 있든 최소한의 JSON-LD만 넣어도 얻을 게 있음

    • 최소 세트로는 루트 페이지의 WebSite, ProfilePage, Person이 제안됨
    • 블로그 글이 있다면 BlogPosting을 추가하고, 프로젝트가 있다면 SoftwareApplication을 붙이면 됨
    • 작성자는 본인 사이트에 약 100시간을 들이며 JSON-LD를 추가했고, 글 전체를 복붙 후 수정하기 쉽게 예시 중심으로 구성함

기술 맥락

  • 이 글의 핵심 선택은 검색엔진 최적화를 키워드 반복으로 푸는 대신, 페이지의 의미 구조를 JSON-LD로 명시하는 거예요. 크롤러는 HTML 텍스트만 읽어도 어느 정도 추론하지만, 작성자·사이트·글·프로젝트 관계를 구조화해주면 훨씬 덜 헷갈리거든요.

  • @id를 URL 해시 형태로 고정하는 이유는 같은 엔티티를 여러 페이지에서 다시 참조하기 위해서예요. 예를 들어 모든 글에서 같은 Person 노드를 가리키면, 크롤러는 이 글들의 작성자가 같은 사람이라는 관계를 안정적으로 묶을 수 있어요.

  • WebSite와 WebPage, BlogPosting을 분리하는 것도 설계상 의미가 있어요. 사이트 전체, HTML 페이지, 글 콘텐츠는 서로 다른 계층이라서 하나로 뭉개면 검색엔진이 어떤 정보가 어디에 속하는지 애매하게 받아들일 수 있거든요.

  • LLM 크롤러 얘기가 흥미로운 지점이에요. 전통적인 검색 크롤러는 여러 페이지를 돌며 정보를 병합할 수 있지만, 어떤 수집기는 한 페이지만 보고 답변 근거를 만들 수 있어요. 그래서 중복을 줄이되, 각 페이지가 최소한의 자기소개와 출처 맥락을 갖게 만드는 균형이 필요해요.

  • 개인 개발자 포트폴리오에서는 이 작업이 생각보다 실용적이에요. 프로젝트, 블로그 글, 외부 프로필이 흩어져 있을 때 JSON-LD가 그 조각들을 한 사람의 작업물로 연결해주기 때문이에요.

개인 블로그나 포트폴리오를 운영하는 개발자에게 꽤 바로 써먹을 수 있는 글이야. 요즘은 검색엔진뿐 아니라 LLM 크롤러도 페이지의 작성자와 맥락을 보니까, 구조화 데이터는 예전보다 더 실용적인 메타데이터 작업이 됐어.

댓글

댓글

댓글을 불러오는 중...

frontend

Deno, 웹 프로젝트를 데스크톱 앱으로 묶는 `deno desktop` 공개

Deno가 TypeScript 파일 하나부터 Next.js 앱까지 데스크톱 앱으로 패키징하는 `deno desktop`을 공개했다. 아직 안정 릴리스는 아니고 Deno v2.9.0 canary에서만 쓸 수 있지만, 운영체제 WebView 기반의 작은 바이너리, 프레임워크 자동 감지, 내장 자동 업데이트까지 한 번에 노린다.

frontend

파비콘 안에 웹사이트를 숨겨 넣은 개발자, 진짜 됨

한 개발자가 웹사이트의 파비콘 이미지를 작은 저장소처럼 사용해 HTML을 픽셀 RGB 값 안에 넣고, 브라우저에서 다시 읽어 렌더링하는 실험을 했다. 208바이트짜리 HTML payload에 4바이트 길이 헤더를 붙여 총 212바이트를 만들었고, 이를 9x9 픽셀 PNG 안에 87% 사용률로 저장했다.

frontend

스크린이 절대 못 보여주는 색은 어디에 있을까

이 글은 우리가 화면에서 보는 색이 인간이 볼 수 있는 색 전체가 아니라, sRGB와 Display-P3 같은 색역 안에 갇힌 일부라는 점을 파고든다. 특히 숲, 바닷속, 새와 나비의 구조색, 생물발광, 교통신호 LED 같은 실제 세계에는 모니터와 카메라가 제대로 담지 못하는 청록색과 녹색 계열이 꽤 많다는 얘기다. 디스플레이, 카메라, 조명, 렌더링을 다루는 개발자라면 “색상값 하나”가 생각보다 물리와 표준의 타협이라는 걸 체감하게 된다.

frontend

크롬, 매니페스트 버전 2 우회로까지 닫는다

구글 크롬이 매니페스트 버전 2 확장 지원을 사실상 최종 종료 단계로 밀어넣고 있다. 기존에는 플래그나 레지스트리 설정으로 유블록 오리진 같은 확장을 살리는 우회가 있었지만, 크로미움 150과 151을 거치며 그 우회 코드까지 제거되는 흐름이다.

frontend

HTML 우선 사이트로 전환했더니 신청 완료자가 하룻밤 사이 2배가 된 이야기

한 공공성 강한 유틸리티 회사가 React 기반 신청 폼 실패 뒤, Astro와 HTML 우선 구조로 다시 만들었더니 폼 완료자가 출시 직후 2배로 늘어남. 핵심은 자바스크립트 없이도 동작하는 페이지별 폼, 서버 저장 세션, 접근성, 점진적 향상이었음.