o2o-infinith-demo/src/data/aeoGeoRubric.ts
Haewon Kam 6a38b19ddd feat: 법무법인 태하 AI Discovery 케이스 (68점/B) + 기준표 업종 중립화 + 결과 레지스트리 분리
- 선정: 네이버 '마약 변호사' 파워링크 1위 광고주. 랜딩 taehadrug.com + 메인 taehalaw.com 실측
- 핵심 발견: 메인 도메인 가비아 WAF가 GPTBot·OAI-SearchBot 403 차단, 도메인 6개·전화번호 4종 엔티티 분산, canonical http://
- 기준표 D1/B2/B3/C7 라벨을 병의원·법률 공용으로 (강남언니/로톡, MedicalClinic/LegalService, Physician/Attorney)
- src/data/discoveryResults.ts 레지스트리 신설, /discovery/taeha
- INFINITH 덱 13장 + PDF

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 11:40:01 +09:00

532 lines
22 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* INFINITH AI Discovery AEO/GEO 채점 기준표 v1.0
*
* 근거 기반: ado2-aeo-geo 스킬 (2026-08-26 한국 실측 · Princeton GEO · C-SEO Bench)
*
* 배점 철학
* - "차단되면 절대 인용될 수 없다"는 논쟁의 여지가 없다 → A(접근성)·B(엔티티) 배점이 높다
* - GEO 콘텐츠 전술의 효과는 학술적으로 논쟁 중 → C는 배점이 크지만 "좋은 콘텐츠 원칙"으로만 설명한다
* - llms.txt는 항목에서 제외한다 (Google 공식 효과 0, 채택률 0.13%)
* - 병의원 업종은 강남언니(ai-input=yes)가 AI 인용을 장악 → D(표면)에서 최고 배점
*/
import type { Rubric } from '../types/discovery';
const L = (l0: string, l1: string, l2: string, l3: string) => [
{ level: 0 as const, label: l0 },
{ level: 1 as const, label: l1 },
{ level: 2 as const, label: l2 },
{ level: 3 as const, label: l3 },
];
export const AEO_GEO_RUBRIC: Rubric = {
version: '1.0',
updatedAt: '2026-08-28',
categories: [
{
id: 'access',
code: 'A',
name: 'AI 크롤러 접근성',
nameEn: 'Access & Crawlability',
description:
'AI 검색엔진이 사이트를 읽을 수 있는가. 크롤러 접근이 막히면 나머지 항목은 전부 무효다.',
weight: 20,
},
{
id: 'entity',
code: 'B',
name: '엔티티 식별·구조화',
nameEn: 'Entity & Structured Data',
description:
'AI가 "이 병원이 누구인지"를 기계적으로 확정할 수 있는가. NAP 일관성과 스키마 위생.',
weight: 20,
},
{
id: 'content',
code: 'C',
name: '답변 인용 가능 콘텐츠',
nameEn: 'Answer-Ready Content',
description:
'패시지 단위로 잘라내도 자기완결적인 사실 덩어리가 있는가. 정의문·FAQ·수치·표·의료진 근거.',
weight: 25,
},
{
id: 'surface',
code: 'D',
name: 'AI 인용 표면 확보',
nameEn: 'Off-site Surfaces',
description:
'실제로 AI가 인용하는 외부 표면(강남언니·GBP·오픈웹)에 존재하는가. 네이버 자산은 글로벌 AI에 기여도 0.',
weight: 20,
},
{
id: 'measure',
code: 'E',
name: 'AI 가시성 측정 인프라',
nameEn: 'Measurement',
description:
'개선을 증명할 수 있는가. 소유 신호(크롤러 로그·GA4 AI 유입) 계측 여부.',
weight: 10,
},
{
id: 'hygiene',
code: 'F',
name: '기술 위생',
nameEn: 'Technical Hygiene',
description: '이미지 대체텍스트·CMS 보안·페이지 무게·모바일. 보조 지표.',
weight: 5,
},
],
criteria: [
// ───────────── A. 접근성 (20) ─────────────
{
id: 'A1',
category: 'access',
name: '검색용 AI 봇 허용',
rationale:
'OAI-SearchBot·PerplexityBot·Claude-SearchBot·bingbot·Googlebot이 막히면 인용 자체가 불가능. 학습봇(GPTBot·ClaudeBot)과 구분해 평가.',
weight: 5,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: 'robots.txt 파싱 + 각 UA로 실제 GET 200 확인 (crawler_audit.py)',
levels: L('검색봇 2개 이상 차단', '검색봇 1개 차단', '모두 허용, 학습봇 일부 차단', '검색봇 전부 허용 + 200 응답'),
},
{
id: 'A2',
category: 'access',
name: 'CDN/WAF AI 차단 없음',
rationale: 'Cloudflare는 2025-07부터 신규 도메인에 AI 크롤러 기본 차단. 업체가 인지하지 못한 채 AI 검색에서 사라지는 주원인.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: '응답 헤더(server/cf-ray) + AI UA 요청 시 403/challenge 여부',
levels: L('AI UA 403/챌린지', '일부 UA 차단', 'CDN 사용, 차단 없음', 'CDN 차단 없음 확인'),
},
{
id: 'A3',
category: 'access',
name: '서버 렌더링 본문',
rationale: 'AI 크롤러는 JS를 실행하지 않거나 지연시킨다. 초기 HTML에 본문이 없으면 빈 페이지로 읽힌다.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: 'JS 미실행 HTML의 텍스트 길이 / 렌더 후 텍스트 길이 비율',
levels: L('본문 전무 (SPA 빈 셸)', '30% 미만', '30~80%', '80% 이상 (SSR/정적)'),
},
{
id: 'A4',
category: 'access',
name: 'HTTPS·리다이렉트 정합',
rationale: 'http/www 변형이 하나의 정본 URL로 301 수렴해야 엔티티가 분산되지 않는다.',
weight: 2,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: 'http://, http://www, https:// 4변형 → 최종 URL 동일 여부',
levels: L('HTTPS 없음', '변형 간 200 중복', '일부 302', '전부 301로 정본 수렴'),
},
{
id: 'A5',
category: 'access',
name: 'sitemap.xml 제공',
rationale: '크롤러 발견 경로. robots.txt에 선언되어야 한다.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: 'robots.txt Sitemap: 선언 + 200 + lastmod 존재',
levels: L('없음', '있으나 robots 미선언', '선언·200', '선언·200·lastmod 최신'),
},
{
id: 'A6',
category: 'access',
name: 'Bing 색인 (ChatGPT 검색 경로)',
rationale: 'ChatGPT 검색은 Bing 인덱스에 상당 부분 의존. Bing Webmaster + IndexNow 등록 여부.',
weight: 3,
evidenceGrade: 'vendor',
control: 'direct',
method: 'manual',
howToCheck: 'Bing Webmaster Tools 등록 확인 (오너 접근 필요) 또는 site: 검색 결과 수',
levels: L('Bing 미색인', '일부 색인', '색인됨', '색인 + IndexNow 연동'),
},
{
id: 'A7',
category: 'access',
name: '응답 속도·크롤 예산',
rationale: 'TTFB가 느리거나 HTML이 비대하면 크롤러가 페이지를 덜 가져간다.',
weight: 1,
evidenceGrade: 'estimate',
control: 'direct',
method: 'auto',
howToCheck: 'TTFB < 0.5s, HTML < 300KB',
levels: L('TTFB > 2s', 'TTFB > 1s 또는 HTML > 1MB', 'TTFB < 0.5s, HTML > 300KB', 'TTFB < 0.5s, HTML < 300KB'),
},
// ───────────── B. 엔티티 (20) ─────────────
{
id: 'B1',
category: 'entity',
name: 'JSON-LD 문법 유효성',
rationale: '문법이 깨진 JSON-LD는 파서가 통째로 버린다. 있는데 무효인 것은 없는 것과 같다.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: '모든 ld+json 블록 JSON.parse 성공 여부',
levels: L('전부 무효 또는 없음', '일부 무효', '전부 유효', '전부 유효 + @graph 연결'),
},
{
id: 'B2',
category: 'entity',
name: '업종 엔티티 스키마 (MedicalClinic / LegalService / LocalBusiness)',
rationale: '엔티티 식별을 돕는 위생 조치. 인과 증거는 없으나 name·address·telephone·openingHours·전문분야(medicalSpecialty / areaServed)를 기계가 읽게 한다.',
weight: 5,
evidenceGrade: 'academic',
control: 'direct',
method: 'auto',
howToCheck: '@type MedicalClinic|LegalService|LocalBusiness 존재 + 필수 속성 4개',
levels: L('없음', 'Organization만', '업종 타입 + 주소·전화', '+ openingHours·전문분야·geo'),
},
{
id: 'B3',
category: 'entity',
name: '전문가 스키마 (Physician / Attorney)',
rationale: '"누가 담당하나"는 병의원·로펌 질의의 핵심. 의사·변호사 이름과 자격·경력을 구조화하면 E-E-A-T 엔티티가 된다.',
weight: 3,
evidenceGrade: 'academic',
control: 'direct',
method: 'auto',
howToCheck: '@type Physician|Attorney + name·전문분야·worksFor',
levels: L('없음', '이름만', '전문분야 포함', '자격·소속·sameAs 포함'),
},
{
id: 'B4',
category: 'entity',
name: 'NAP 사이트 내 일관성',
rationale: '같은 사이트 안에서 주소 표기가 다르면 외부 표면과 대조할 기준이 없다. 한 글자까지 동일해야 한다.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: '주소·전화 정규식 추출 → 고유 표기 수',
levels: L('주소/전화 미표기', '3개 이상 표기 변형', '2개 변형', '단일 표기'),
},
{
id: 'B5',
category: 'entity',
name: 'sameAs 연결',
rationale: 'Organization.sameAs로 YouTube·Instagram·강남언니·GBP를 연결해야 AI가 흩어진 언급을 한 엔티티로 묶는다.',
weight: 2,
evidenceGrade: 'academic',
control: 'direct',
method: 'auto',
howToCheck: 'Organization.sameAs 배열 길이',
levels: L('비어 있음', '1~2개', '3~4개', '5개 이상 (SNS + 버티컬 + 지도)'),
},
{
id: 'B6',
category: 'entity',
name: 'canonical·중복 제거',
rationale: '같은 내용이 여러 URL이면 인용 신호가 분산된다.',
weight: 2,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: 'rel=canonical 존재 + self-referencing',
levels: L('없음', '있으나 불일치', '있음', '있음 + 파라미터 정리'),
},
{
id: 'B7',
category: 'entity',
name: '다국어 hreflang',
rationale: '외국인 환자 질의(영·중·일)는 별도 엔진 표면. 언어 버전이 있다면 hreflang으로 연결해야 한다.',
weight: 2,
evidenceGrade: 'vendor',
control: 'direct',
method: 'auto',
howToCheck: 'link hreflang 태그 수',
levels: L('다국어 페이지 있으나 미연결', '단일 언어', '2개 언어 연결', '3개 이상 연결'),
},
// ───────────── C. 콘텐츠 (25) ─────────────
{
id: 'C1',
category: 'content',
name: '정의문형 첫 문단',
rationale: 'Google AI Mode의 query fan-out은 패시지 단위로 검색한다. "○○은 강남 신논현에 있는 가슴성형 전문 성형외과다"처럼 답을 먼저 써야 청크가 자기완결적이 된다.',
weight: 4,
evidenceGrade: 'academic',
control: 'direct',
method: 'semi',
howToCheck: '메인·시술 페이지 첫 200자에 [상호+지역+전문분야] 정의문 존재',
levels: L('없음 (슬로건·이미지만)', '슬로건형', '일부 페이지에 정의문', '전 핵심 페이지 정의문'),
},
{
id: 'C2',
category: 'content',
name: 'FAQ 섹션',
rationale: '실제 질문 형태 그대로의 H2/H3 + 답변은 답변엔진이 가장 잘 가져가는 구조. FAQPage 스키마와 결합.',
weight: 4,
evidenceGrade: 'academic',
control: 'direct',
method: 'auto',
howToCheck: 'FAQ/Q&A 섹션 탐지 + FAQPage 스키마',
levels: L('없음', '게시판형 Q&A만', 'FAQ 섹션 존재', 'FAQ + FAQPage 스키마 + 시술별'),
},
{
id: 'C3',
category: 'content',
name: '제목 계층 의미성',
rationale: 'H1은 페이지당 1개, 주제를 서술해야 한다. "VIEW SELFIE" 같은 라벨형 H1은 AI에게 아무 정보도 주지 않는다.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: 'H1 개수 = 1, H1/H2 텍스트가 명사구 서술형인지, 중복 H2 비율',
levels: L('H1 없음 또는 5개 이상', 'H1 다수·라벨형', 'H1 1개, H2 일부 라벨형', 'H1 1개 서술형, H2 논리 계층'),
},
{
id: 'C4',
category: 'content',
name: '구체 수치 (가격·시간·회복)',
rationale: '가격대·수술시간·회복기간·재수술률 같은 수치는 인용되는 콘텐츠의 공통 특징. (Princeton GEO 정합, 단 C-SEO Bench 반박 있음 → 효과 보장 아님)',
weight: 4,
evidenceGrade: 'academic',
control: 'direct',
method: 'semi',
howToCheck: '시술 페이지에서 원/분/일/% 단위 수치 밀도',
levels: L('수치 없음', '마케팅 문구 속 수치만', '시술별 일부 수치', '시술별 가격대·시간·회복 표기'),
},
{
id: 'C5',
category: 'content',
name: '표·비교 구조',
rationale: 'AI가 인용하는 콘텐츠는 구조화·표 중심 (인블로그 조사). 보형물 비교표·시술 비교표가 대표 예.',
weight: 2,
evidenceGrade: 'vendor',
control: 'direct',
method: 'auto',
howToCheck: '<table> 또는 정의 리스트 존재 (이미지 표 제외)',
levels: L('없음', '이미지로만 된 표', 'HTML 표 1~2개', 'HTML 표 다수'),
},
{
id: 'C6',
category: 'content',
name: '신선도 신호',
rationale: 'dateModified·최종 수정일 명시. 1년 이상 갱신 없는 사이트는 "폐업했나?" 오정보 위험.',
weight: 3,
evidenceGrade: 'academic',
control: 'direct',
method: 'auto',
howToCheck: 'sitemap lastmod 최신값, article:modified_time, 본문 갱신일',
levels: L('2년 이상 갱신 없음', '1년 이상', '6개월 이내', '3개월 이내 + dateModified 표기'),
},
{
id: 'C7',
category: 'content',
name: '전문가 E-E-A-T (의료진 / 변호사)',
rationale: '전문의 자격·경력·학회·수상, 변호사의 전관 경력·전문분야 등록이 텍스트로 존재해야 AI가 "믿을 만한 출처"로 판단할 근거가 생긴다. 이미지 안의 글자는 안 읽힌다.',
weight: 3,
evidenceGrade: 'academic',
control: 'direct',
method: 'semi',
howToCheck: '전문가 페이지 텍스트에 자격·경력 명시 여부',
levels: L('전문가 정보 없음', '이름·사진만', '자격·경력 텍스트', '+ 논문·학회·수상 + 전문가 스키마'),
},
{
id: 'C8',
category: 'content',
name: '패시지 자기완결성',
rationale: '한 단락만 떼어내도 "누가·어디서·무엇을"이 들어 있어야 인용된다. 대명사·"저희"로 시작하는 단락은 맥락을 잃는다.',
weight: 2,
evidenceGrade: 'academic',
control: 'direct',
method: 'manual',
howToCheck: '핵심 페이지 단락 샘플 10개 중 상호·시술명이 포함된 비율',
levels: L('0~20%', '20~50%', '50~80%', '80% 이상'),
},
// ───────────── D. 표면 (20) ─────────────
{
id: 'D1',
category: 'surface',
name: '업종 버티컬 프로필 (병의원: 강남언니 / 법률: 로톡)',
rationale: '2026-08 실측: 병의원 질의는 강남언니(ai-input=yes 명시)·닥터나우가 AI 인용을 장악. 법률은 로톡·로앤굿 등 변호사 디렉터리가 같은 역할. 여기 없으면 AI에겐 없는 업체.',
weight: 6,
evidenceGrade: 'measured',
control: 'direct',
method: 'manual',
howToCheck: '버티컬 프로필 존재·등록 항목 수·후기 수·최근 갱신 (병원 페이지 / 로펌·변호사 프로필)',
levels: L('미등록', '등록, 항목 3개 미만', '항목 다수·후기 활성', '+ 전문가·가격 갱신 3개월 이내'),
},
{
id: 'D2',
category: 'surface',
name: 'Google 비즈니스 프로필',
rationale: 'Gemini·Google AI Mode의 구조화 데이터 원천. 국내 성형외과 등록률이 낮아 선점 여지가 크다.',
weight: 4,
evidenceGrade: 'measured',
control: 'direct',
method: 'manual',
howToCheck: 'Google Maps 검색 → 소유권 확인·카테고리·사진·리뷰·NAP 일치',
levels: L('없음', '미소유 자동 생성', '소유·기본 정보', '소유·리뷰 응답·게시물 활성'),
},
{
id: 'D3',
category: 'surface',
name: '오픈웹 언급 (티스토리·유튜브·언론)',
rationale: 'Ahrefs 7.5만 브랜드: 웹 언급 상관 r=0.664 (백링크 0.218). 네이버 블로그·카페는 AI 차단이라 제외.',
weight: 4,
evidenceGrade: 'academic',
control: 'influence',
method: 'semi',
howToCheck: '검색 그라운딩으로 상호 언급 도메인 집계 (naver.com 제외)',
levels: L('자체 사이트 외 없음', '유튜브만', '유튜브 + 언론/티스토리', '다수 오픈 도메인에서 일관된 언급'),
},
{
id: 'D4',
category: 'surface',
name: '표면 간 NAP 완전 일치',
rationale: '홈페이지·강남언니·GBP·플레이스의 주소·전화가 한 글자라도 다르면 답변엔진이 동일 업체로 묶지 못한다.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'manual',
howToCheck: '표면별 NAP 표를 만들어 대조',
levels: L('전화번호 상이', '주소 표기 상이', '경미한 표기 차이', '완전 일치'),
},
{
id: 'D5',
category: 'surface',
name: '네이버 플레이스 (AI 브리핑 전용)',
rationale: '글로벌 AI에는 기여도 0. 단 네이버 AI 브리핑(검색의 20%→40%)은 별도 게임이며 플레이스↔홈페이지 연결이 중요.',
weight: 2,
evidenceGrade: 'measured',
control: 'direct',
method: 'semi',
howToCheck: '플레이스 존재·홈페이지 링크·리뷰 수',
levels: L('없음', '있음, 홈페이지 미연결', '연결·리뷰 활성', '연결·리뷰·소식 활성'),
},
{
id: 'D6',
category: 'surface',
name: '위키데이터/위키백과 엔티티',
rationale: 'LLM의 엔티티 앵커. 대형 병원만 해당하나 있으면 확정적.',
weight: 1,
evidenceGrade: 'estimate',
control: 'influence',
method: 'auto',
howToCheck: 'Wikidata API 상호 검색',
levels: L('없음', '언급만', '항목 존재', '항목 + 공식 사이트 연결'),
},
// ───────────── E. 측정 (10) ─────────────
{
id: 'E1',
category: 'measure',
name: 'AI 크롤러 로그 (IP 검증)',
rationale: 'AI가 우리를 읽었는가(선행 지표). 크롤러 UA의 최대 81.8%가 위조 → IP 검증 히트만 인정.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'manual',
howToCheck: 'Cloudflare AI Crawl Control 또는 서버로그 + bot_ip_verify.py',
levels: L('로그 접근 불가', '로그 있음, 미분석', 'UA 기준 집계', 'IP 검증 히트 집계'),
},
{
id: 'E2',
category: 'measure',
name: 'GA4 AI 유입 채널',
rationale: 'AI에서 사람이 왔는가(후행·매출 귀속). chatgpt.com·perplexity.ai 등 커스텀 채널그룹. 35~70%가 Direct로 유실되므로 하한값.',
weight: 3,
evidenceGrade: 'measured',
control: 'direct',
method: 'manual',
howToCheck: 'GA4 커스텀 채널그룹 존재 여부 (오너 접근 필요)',
levels: L('GA4 없음', 'GA4 있음, AI 채널 없음', '기본 AI Assistant 채널', '커스텀 채널 (Perplexity 포함)'),
},
{
id: 'E3',
category: 'measure',
name: 'GSC AI Overviews 노출',
rationale: 'Google AI 표면 노출 (2026-06~ Search Console UI 전용).',
weight: 2,
evidenceGrade: 'vendor',
control: 'direct',
method: 'manual',
howToCheck: 'GSC 등록 + AI Overviews 필터 확인',
levels: L('GSC 미등록', '등록만', '데이터 확인', '월간 추적'),
},
{
id: 'E4',
category: 'measure',
name: '기준선 스팟체크',
rationale: '질의 10개 × 5~7회 반복 수동 측정 → 언급률+신뢰구간. 단발 조회는 무효(분산 10~34%).',
weight: 2,
evidenceGrade: 'academic',
control: 'direct',
method: 'manual',
howToCheck: '04_baseline 진단 리포트 존재 여부',
levels: L('없음', '단발 조회만', '반복 측정 1회', '분기 반복 측정'),
},
// ───────────── F. 위생 (5) ─────────────
{
id: 'F1',
category: 'hygiene',
name: '이미지 대체텍스트',
rationale: '성형외과 사이트는 정보의 대부분이 이미지 안 글자. alt가 없으면 AI에게 그 정보는 없다.',
weight: 2,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: 'alt 누락 이미지 비율',
levels: L('50% 이상 누락', '20~50% 누락', '5~20% 누락', '5% 미만 누락'),
},
{
id: 'F2',
category: 'hygiene',
name: 'CMS 보안·최신성',
rationale: '지원 종료 CMS는 해킹 시 스팸 페이지가 주입되어 AI가 엉뚱한 내용을 인용할 위험.',
weight: 1,
evidenceGrade: 'estimate',
control: 'direct',
method: 'auto',
howToCheck: 'meta generator 버전 vs 최신 안정 버전',
levels: L('3년 이상 구버전', '1~3년', '1년 이내', '최신'),
},
{
id: 'F3',
category: 'hygiene',
name: '페이지 무게',
rationale: 'HTML 크기가 크면 크롤 예산 소모·요약 품질 저하.',
weight: 1,
evidenceGrade: 'estimate',
control: 'direct',
method: 'auto',
howToCheck: '초기 HTML 바이트',
levels: L('> 2MB', '> 800KB', '300~800KB', '< 300KB'),
},
{
id: 'F4',
category: 'hygiene',
name: '모바일 대응',
rationale: '모바일 인앱 브라우저 유입(ChatGPT 앱)이 주 경로.',
weight: 1,
evidenceGrade: 'measured',
control: 'direct',
method: 'auto',
howToCheck: 'viewport meta + 반응형',
levels: L('viewport 없음', '별도 m. 도메인', '반응형', '반응형 + CWV 양호'),
},
],
};
export const getCriterion = (id: string) =>
AEO_GEO_RUBRIC.criteria.find((c) => c.id === id);
export const getCategory = (id: string) =>
AEO_GEO_RUBRIC.categories.find((c) => c.id === id);