서치 콘솔의 "'itemReviewed' 입력란이 누락되었습니다" 오류는, 평가 대상(부모 아이템)과 연결되지 않은 AggregateRating이 페이지 어딘가에 단독으로 있을 때 생긴다. 내 경우 범인은 화면 별점에 붙어 있던 마이크로데이터였고, 같은 평점은 이미 JSON-LD에 제대로 들어 있었다.
즉 구글은 같은 평점을 두 번 신고받은 셈이었다. 한 번은 JSON-LD 안에서 소프트웨어의 평점으로, 또 한 번은 HTML 속에서 주인 없는 평점으로. 두 번째가 "이름 없는 항목"이 되어 오류로 잡혔다. 고친 방법은 의외로 단순해서 화면 별점의 마이크로데이터 속성만 지웠다. 어떻게 찾았고 어떻게 확인했는지 순서대로 적는다.
- "이름 없는 항목"의 AggregateRating은 부모 아이템 없이 단독으로 붙은 마이크로데이터인 경우가 많다.
- JSON-LD에 이미 aggregateRating이 있다면 화면 별점의 itemScope·itemProp은 중복이다. 속성만 지우면 모양은 그대로다.
- 구조화 데이터는 JSON-LD 한 가지 방식으로, 한 곳에서만 만든다. 화면 값과 JSON-LD 값은 같은 함수에서 나오게 한다.
PART 01서치 콘솔에 뜬 화면
구글 서치 콘솔에서 BoltPDF 프로그램 페이지(youngsam.net/programs/boltpdf)를 URL 검사했더니 개선사항 쪽에 "리뷰 스니펫: 항목 3개 감지됨, 일부 항목이 잘못됨"이 떠 있었다. 펼쳐 보니 감지된 항목은 이랬다.
세 번째 항목의 상세에는 ratingValue 5.0, bestRating 5, ratingCount 1이 들어 있었고, 그 아래 빨간 글씨로 "'itemReviewed' 입력란이 누락되었습니다"가 중요한 문제로 찍혀 있었다. 처음 보면 꽤 겁이 나는 화면이다. 평점 데이터가 망가졌나, 리뷰 시스템에 문제가 있나 싶다. 그런데 이름 없는 항목의 숫자를 보니 페이지 상단 별점 표시 "★ 5.0 (1)"과 똑같았다. 바로 거기서 실마리가 잡혔다.
그리고 이건 BoltPDF만의 문제가 아니었다. 별점 컴포넌트는 모든 프로그램 페이지가 공유하니, 별점이 있는 프로그램 페이지 전부에서 같은 오류가 나고 있던 것이었다.
itemScope itemType="https://schema.org/AggregateRating"이 붙어 있고, 안쪽 숫자들에 itemProp="ratingValue", bestRating, ratingCount가 하나씩 달려 있었다. 아마 "별점이니까 schema 속성을 달아 두면 좋겠지" 하는 마음으로 붙였을 것이다. 문제는 이 요소를 감싸는 부모가 없었다는 점이다. 바깥에 itemScope itemType="SoftwareApplication" 같은 아이템이 없으니, 구글 입장에서 이건 "무엇에 대한 평점인지 모르는 평점" 하나가 페이지에 떠 있는 것이다. 평가 대상이 없으니 itemReviewed가 누락됐다는 오류가 정확한 진단이었다. 한편 같은 평점은 이미 페이지의 JSON-LD 안에 SoftwareApplication.aggregateRating으로 제대로 들어가 있었다. 결국 오류의 정체는 중복 신고였다.PART 02왜 "이름 없는 항목"이 되는가
마이크로데이터는 HTML 요소에 속성을 붙여 구조를 표현한다. itemScope가 붙은 요소는 하나의 아이템이 되고, 그 안의 itemProp은 가장 가까운 바깥 아이템의 속성이 된다. 그런데 itemScope가 붙은 요소가 다른 아이템의 itemProp이 아니라면, 그건 페이지의 최상위 아이템으로 따로 해석된다.
AggregateRating은 혼자서는 의미가 없는 타입이다. 구글의 리뷰 스니펫 가이드도 평점은 평가 대상 아이템 안에 중첩되거나, itemReviewed로 대상을 가리켜야 한다고 설명한다. 최상위에 홀로 떠 있는 AggregateRating에는 이름(name)도 없고 대상도 없으니 서치 콘솔은 "이름 없는 항목"이라고 표시하고, 필수 입력란인 itemReviewed가 빠졌다고 알려 준다.
// 전: 부모 아이템 없이 단독으로 붙은 마이크로데이터
<span className="rating"
itemScope itemType="https://schema.org/AggregateRating">
★ <span itemProp="ratingValue">{avg.toFixed(1)}</span>
<meta itemProp="bestRating" content="5" />
(<span itemProp="ratingCount">{count}</span>)
</span>
// 후: 보이는 모양은 그대로, 의미 속성만 제거
<span className="rating">
★ <span>{avg.toFixed(1)}</span>
({count})
</span>수정은 이게 전부다. itemScope, itemType, itemProp, 그리고 meta 태그를 지웠고 클래스와 글자는 건드리지 않았다. 사용자가 보는 별점은 1픽셀도 안 바뀌었다. 같은 컴포넌트가 한국어 페이지와 다국어(en/ja/zh) 페이지에 따로 있어서 두 군데 모두 고쳤다. 한쪽만 고치면 서치 콘솔에서 언어별 URL로 같은 오류가 계속 나올 테니까.
PART 03마이크로데이터 vs JSON-LD
둘 다 구글이 읽는 형식이다. 기능만 보면 같은 걸 표현할 수 있다. 하지만 유지보수 관점에서는 차이가 크고, 구글도 문서에서 JSON-LD를 권장한다고 밝히고 있다.
내 사이트는 원래 JSON-LD를 주력으로 쓰고 있었다. 프로그램 페이지마다 SoftwareApplication 객체를 만들고 그 안에 aggregateRating을 넣는다. 그런데 컴포넌트 한 구석에 마이크로데이터가 남아 있었고, 두 방식이 서로를 모른 채 같은 평점을 각자 신고하고 있었다. 섞어 쓰는 게 금지는 아니지만, 섞는 순간 "이 정보가 몇 번, 어디서 나가는가"를 사람이 추적해야 한다.
PART 04올바른 JSON-LD는 이렇게 생겼다
aggregateRating은 평가 대상 객체 안에 넣는다. 이렇게 중첩하면 itemReviewed를 따로 쓸 필요가 없다. 부모가 곧 평가 대상이기 때문이다. SoftwareApplication은 구글 문서에서 aggregateRating이나 review를 지원하는 타입으로 안내되어 있다.
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "BoltPDF",
"applicationCategory": "BusinessApplication",
"operatingSystem": "Windows",
"offers": { "@type": "Offer", "price": "0", "priceCurrency": "KRW" },
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "5.0",
"bestRating": "5",
"ratingCount": "2"
}
}여기서 내가 신경 쓰는 건 숫자의 출처다. 화면 별점, 리뷰 목록 헤더, JSON-LD에 들어가는 평점이 서로 다르면 구글이 "보이는 내용과 구조화 데이터가 다르다"고 판단할 여지가 생긴다. 그래서 youngsam.net에서는 평점 평균과 개수를 공통 함수 하나로 계산하고, 화면 표시·리뷰 헤더·JSON-LD가 모두 그 결과를 쓴다.
PART 05배포 후 검증 흐름
고쳤다고 끝이 아니다. 실제로 오류가 사라졌는지, 그리고 정상 데이터까지 같이 지워 버리지 않았는지 둘 다 확인해야 한다. 내가 한 확인에 리치 결과 테스트를 더한 순서는 이렇다.
schema.org/AggregateRating 마이크로데이터가 0개인지 본다. 동시에 JSON-LD 안의 aggregateRating이 그대로 남아 있는지 확인한다. (구글이 크롤링했을 때는 리뷰가 1건이었고, 고칠 즈음엔 새 리뷰가 승인돼 2건이었다. 숫자가 화면·JSON-LD에서 함께 바뀌면 정상이다.) 지워야 할 것과 남겨야 할 것을 둘 다 본다.첫 단계에서 "남겨야 할 것"을 같이 확인하는 게 중요하다. 오류를 없애려고 구조화 데이터를 통째로 지우면 서치 콘솔은 조용해지지만 리치 결과 자격도 같이 사라진다. 오류 0개가 목표가 아니라, 올바른 데이터 1벌이 목표다.
- "이름 없는 항목"의 숫자를 화면과 대조해 어디서 나온 데이터인지 찾는다.
- 부모 없이 단독으로 붙은 AggregateRating 마이크로데이터가 있으면 의미 속성만 지운다. 모양은 그대로 둔다.
- 구조화 데이터는 JSON-LD로, 한 곳에서만 만든다. 평점은 평가 대상 객체 안에 중첩한다.
- 화면·리뷰 헤더·JSON-LD 평점은 공통 함수 하나에서 나오게 한다.
- 배포 후 "지운 것 0개, 남긴 것 그대로"를 확인하고 서치 콘솔에서 수정 결과 확인을 요청한다.
자주 묻는 질문
서치 콘솔의 'itemReviewed 입력란이 누락되었습니다' 오류는 무슨 뜻인가요?
평점(AggregateRating)이나 리뷰가 무엇에 대한 것인지 알 수 없다는 뜻이다. 평점이 평가 대상 아이템 안에 중첩되어 있지 않고 itemReviewed로 대상을 가리키지도 않을 때 생긴다. 화면 별점에 단독으로 붙은 마이크로데이터가 흔한 원인이다.
리뷰 스니펫에 '이름 없는 항목'이 감지되는 이유는 무엇인가요?
name 속성이 없는 아이템이 최상위로 해석될 때 그렇게 표시된다. AggregateRating을 itemScope로 단독 선언하면 그 자체가 하나의 아이템이 되는데, 평점에는 보통 이름이 없으니 이름 없는 항목으로 나온다. 부모 아이템과 연결하거나 중복이라면 제거하면 된다.
JSON-LD와 마이크로데이터를 같이 써도 되나요?
구글은 둘 다 읽기 때문에 함께 쓸 수는 있다. 다만 같은 정보를 두 방식으로 내보내면 중복이 생기고, 한쪽 구조가 틀리면 이번 사례처럼 오류가 난다. 구글이 권장하는 JSON-LD 한 가지로 통일하는 편이 관리가 쉽다.
소프트웨어 페이지에 별점 리치 결과를 넣을 수 있나요?
SoftwareApplication은 구글 문서에서 aggregateRating이나 review를 지원하는 타입으로 안내된다. 평점을 SoftwareApplication 객체 안에 중첩하고, 화면에 보이는 평점과 같은 값을 넣으면 된다. 다만 리치 결과 표시 여부는 구글이 결정하므로 자격을 갖추는 것까지가 사이트가 할 수 있는 일이다.
구조화 데이터를 고친 뒤 서치 콘솔에서는 어떻게 확인하나요?
URL 검사에서 실제 URL 테스트로 현재 버전을 다시 읽히고, 개선사항의 해당 리치 결과 보고서에서 수정 결과 확인을 요청한다. 검증에는 시간이 걸린다. 배포 직후에는 리치 결과 테스트로 먼저 확인하면 빠르다.

댓글 0