{
  "ruleSetVersion": "2026.09.4",
  "checkedAt": "2026-09-29T22:43:12.053Z",
  "requestedUrl": "https://ad-branch.com/guides/measure-seo-geo",
  "finalUrl": "https://ad-branch.com/guides/measure-seo-geo",
  "http": {
    "status": 200,
    "contentType": "text/html",
    "isHttps": true,
    "redirectCount": 0,
    "responseTimeMs": 5,
    "truncated": false
  },
  "rendering": {
    "verdict": "server-rendered",
    "textLength": 9525,
    "textToHtmlRatio": 0.1917,
    "notice": null
  },
  "seo": {
    "score": 100,
    "categories": [
      {
        "category": "search-access",
        "label": "검색 접근성",
        "weight": 20,
        "score": 100,
        "earnedPoints": 17,
        "maxPoints": 17,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 0
      },
      {
        "category": "metadata",
        "label": "메타데이터",
        "weight": 20,
        "score": 100,
        "earnedPoints": 18,
        "maxPoints": 18,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 2
      },
      {
        "category": "content-structure",
        "label": "콘텐츠 구조",
        "weight": 20,
        "score": 100,
        "earnedPoints": 15,
        "maxPoints": 15,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 1
      },
      {
        "category": "technical-seo",
        "label": "기술 SEO",
        "weight": 20,
        "score": 100,
        "earnedPoints": 20,
        "maxPoints": 20,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 0
      },
      {
        "category": "structured-data",
        "label": "구조화 데이터",
        "weight": 12,
        "score": 100,
        "earnedPoints": 12,
        "maxPoints": 12,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 0
      },
      {
        "category": "social-sharing",
        "label": "소셜 공유",
        "weight": 8,
        "score": 100,
        "earnedPoints": 8,
        "maxPoints": 8,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 0
      }
    ],
    "criticalCount": 0,
    "warningCount": 0,
    "passCount": 58,
    "unknownCount": 3,
    "excludedCount": 9
  },
  "geo": {
    "score": 97,
    "categories": [
      {
        "category": "ai-accessibility",
        "label": "AI 접근 가능성",
        "weight": 25,
        "score": 100,
        "earnedPoints": 21,
        "maxPoints": 21,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 1
      },
      {
        "category": "answer-clarity",
        "label": "답변 명확성",
        "weight": 25,
        "score": 93,
        "earnedPoints": 21.5,
        "maxPoints": 23,
        "criticalCount": 0,
        "warningCount": 1,
        "unknownCount": 0
      },
      {
        "category": "entity-clarity",
        "label": "엔티티 명확성",
        "weight": 15,
        "score": 100,
        "earnedPoints": 15,
        "maxPoints": 15,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 0
      },
      {
        "category": "evidence-trust",
        "label": "근거와 신뢰성",
        "weight": 20,
        "score": 95,
        "earnedPoints": 19,
        "maxPoints": 20,
        "criticalCount": 0,
        "warningCount": 1,
        "unknownCount": 0
      },
      {
        "category": "extractable-structure",
        "label": "정보 추출 구조",
        "weight": 15,
        "score": 100,
        "earnedPoints": 12,
        "maxPoints": 12,
        "criticalCount": 0,
        "warningCount": 0,
        "unknownCount": 1
      }
    ],
    "criticalCount": 0,
    "warningCount": 2,
    "passCount": 33,
    "unknownCount": 2,
    "excludedCount": 5
  },
  "checks": [
    {
      "id": "meta-robots-indexability",
      "engine": "seo",
      "category": "search-access",
      "title": "meta robots 색인 허용",
      "verdict": "pass",
      "maxPoints": 4,
      "earnedPoints": 4,
      "finding": "meta robots 에 색인을 막는 지시가 없습니다.",
      "evidence": "<meta name=\"robots\" content=\"index, follow\">",
      "impact": "noindex 가 있으면 이 페이지는 검색결과에서 제외됩니다. 다른 어떤 최적화보다 먼저 확인해야 합니다.",
      "howToFix": "공개해야 하는 페이지라면 noindex/none 토큰을 제거하거나 index,follow 로 바꾸세요.",
      "codeBefore": "<meta name=\"robots\" content=\"noindex, nofollow\">",
      "codeAfter": "<meta name=\"robots\" content=\"index, follow\">",
      "guideHref": "/guides/robots-txt",
      "priority": 1
    },
    {
      "id": "x-robots-tag-indexability",
      "engine": "seo",
      "category": "search-access",
      "title": "X-Robots-Tag 색인 허용",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "X-Robots-Tag 에 색인을 막는 지시가 없습니다.",
      "evidence": "응답에서 X-Robots-Tag 헤더를 찾지 못했습니다.",
      "impact": "HTTP 헤더의 noindex 는 HTML 에 보이지 않아 놓치기 쉽지만 meta robots 와 동일하게 색인을 막습니다.",
      "howToFix": "서버·CDN 설정에서 X-Robots-Tag 헤더의 noindex/none 을 제거하거나 공개 경로에서 제외하세요.",
      "codeBefore": "X-Robots-Tag: noindex, nofollow",
      "codeAfter": "X-Robots-Tag: index, follow",
      "guideHref": "/guides/robots-txt",
      "priority": 2
    },
    {
      "id": "robots-txt-path-allowed",
      "engine": "seo",
      "category": "search-access",
      "title": "robots.txt 현재 경로 허용",
      "verdict": "pass",
      "maxPoints": 4,
      "earnedPoints": 4,
      "finding": "robots.txt 에서 이 경로를 막는 Disallow 가 없습니다.",
      "evidence": "robots.txt 응답 200 — 현재 경로를 차단하는 규칙이 없습니다.",
      "impact": "robots.txt 에서 막힌 경로는 크롤러가 내용을 읽지 못해 검색결과 품질이 떨어지거나 노출되지 않을 수 있습니다.",
      "howToFix": "이 경로를 공개하려면 해당 Disallow 를 제거하거나, 더 구체적인 Allow 규칙을 추가하세요.",
      "codeBefore": "User-agent: *\nDisallow: /blog/",
      "codeAfter": "User-agent: *\nAllow: /blog/\nDisallow: /admin/",
      "guideHref": "/guides/robots-txt",
      "priority": 3
    },
    {
      "id": "naver-yeti-crawler-access",
      "engine": "seo",
      "category": "search-access",
      "title": "네이버 Yeti 크롤러 접근",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "Yeti 전용 그룹이 있고 사이트 전체를 막는 선언은 없습니다.",
      "evidence": "User-agent: Yeti 그룹 — 전체 차단 없음, Disallow 규칙 없음",
      "impact": "Yeti 는 네이버 검색의 크롤러입니다. Yeti 그룹이 사이트 전체를 막으면 한국어 일반 검색의 유입 경로 하나가 닫힙니다.",
      "howToFix": "네이버 검색 크롤을 허용하려면 Yeti 그룹의 Disallow: / 를 지우거나 공개 경로에 Allow 를 선언하세요. 비공개 사이트라면 현재 설정을 그대로 두어도 됩니다.",
      "codeBefore": "User-agent: Yeti\nDisallow: /",
      "codeAfter": "User-agent: Yeti\nAllow: /\nDisallow: /admin/",
      "guideHref": "/guides/robots-txt",
      "priority": 32.5
    },
    {
      "id": "sitemap-discovery",
      "engine": "seo",
      "category": "search-access",
      "title": "sitemap 발견ㆍ접근",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "접근 가능한 XML sitemap 을 찾았습니다(robots.txt 선언).",
      "evidence": "https://ad-branch.com/sitemap-index.xml — 응답 200, sitemapindex, URL 1개",
      "impact": "sitemap 은 색인의 필수 조건은 아니지만, 새 URL 과 갱신을 검색엔진에 빠르게 알리는 통로입니다.",
      "howToFix": "XML sitemap 을 생성해 공개 경로에 두고 robots.txt 에 Sitemap 줄로 선언하세요.",
      "codeBefore": "# robots.txt 에 Sitemap 선언 없음\nUser-agent: *\nAllow: /",
      "codeAfter": "User-agent: *\nAllow: /\nSitemap: https://example.com/sitemap.xml",
      "guideHref": "/guides/sitemap",
      "priority": 33
    },
    {
      "id": "robots-sitemap-absolute-url",
      "engine": "seo",
      "category": "search-access",
      "title": "robots.txt Sitemap 절대 URL",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "Sitemap 선언 1개가 모두 같은 호스트의 절대 URL 입니다.",
      "evidence": "Sitemap: https://ad-branch.com/sitemap-index.xml",
      "impact": "robots.txt 의 Sitemap 값은 절대 URL 이어야 합니다. 상대 경로는 크롤러가 sitemap 을 찾지 못하는 원인이 됩니다.",
      "howToFix": "Sitemap 줄에 scheme 과 호스트를 포함한 전체 URL 을 적으세요.",
      "codeBefore": "User-agent: *\nAllow: /\nSitemap: /sitemap.xml",
      "codeAfter": "User-agent: *\nAllow: /\nSitemap: https://example.com/sitemap.xml",
      "guideHref": "/guides/sitemap",
      "priority": 33.5
    },
    {
      "id": "sitemap-page-inclusion",
      "engine": "seo",
      "category": "search-access",
      "title": "sitemap 내 현재 URL 포함",
      "verdict": "not-applicable",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "발견한 파일이 sitemapindex 라 요청 한도상 하위 sitemap 을 읽지 않았습니다.",
      "evidence": "https://ad-branch.com/sitemap-index.xml — sitemapindex, 하위 sitemap 은 요청하지 않았습니다.",
      "impact": "sitemap 에 없는 URL 도 색인될 수 있지만, 포함하면 크롤러가 갱신을 더 빨리 발견합니다.",
      "howToFix": "sitemap 생성 규칙에 이 URL 을 포함하고 lastmod 를 실제 수정 시각으로 채우세요.",
      "codeBefore": "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n  <url><loc>https://example.com/</loc></url>\n</urlset>",
      "codeAfter": "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n  <url><loc>https://example.com/</loc></url>\n  <url><loc>https://example.com/blog/post</loc><lastmod>2026-09-03</lastmod></url>\n</urlset>",
      "guideHref": "/guides/sitemap",
      "priority": 34
    },
    {
      "id": "sitemap-lastmod",
      "engine": "seo",
      "category": "search-access",
      "title": "sitemap lastmod 제공",
      "verdict": "not-applicable",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "발견한 파일이 sitemapindex 라 하위 sitemap 의 lastmod 는 요청하지 않았습니다.",
      "evidence": "https://ad-branch.com/sitemap-index.xml: sitemapindex, 하위 sitemap 은 요청하지 않았습니다.",
      "impact": "Google 은 lastmod 가 일관되고 검증 가능하게 정확할 때 이 값을 사용합니다. 값이 없거나 형식이 틀리면 수정 사실을 알리는 통로 하나를 잃습니다.",
      "howToFix": "현재 URL 항목에 실제 마지막 수정일을 W3C Datetime 형식(예: 2026-09-23 또는 2026-09-23T10:00:00+09:00)으로 넣고, 배포할 때마다 오늘 날짜로 덮어쓰지 마세요.",
      "codeBefore": "<url>\n  <loc>https://example.com/blog/post</loc>\n</url>",
      "codeAfter": "<url>\n  <loc>https://example.com/blog/post</loc>\n  <lastmod>2026-09-23</lastmod>\n</url>",
      "guideHref": "/guides/sitemap",
      "priority": 34.5
    },
    {
      "id": "initial-html-content",
      "engine": "seo",
      "category": "search-access",
      "title": "초기 HTML 본문 존재",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "초기 HTML 에 읽을 수 있는 본문이 있습니다.",
      "evidence": "가시 텍스트 9525자, 의미 요소 69개(제목 24 + 문단 45), script 7개",
      "impact": "검색엔진과 AI 크롤러는 최초 HTML 을 먼저 읽습니다. 본문이 JavaScript 로만 그려지면 내용이 없는 페이지로 읽힐 수 있습니다.",
      "howToFix": "핵심 본문과 제목을 서버 렌더링(SSR/SSG)으로 초기 HTML 에 포함하세요.",
      "codeBefore": "<div id=\"root\"></div>\n<script src=\"/app.js\"></script>",
      "codeAfter": "<main>\n  <h1 class=\"page-title\">페이지 제목</h1>\n  <p>핵심 내용을 초기 HTML 에 포함합니다.</p>\n</main>\n<script src=\"/app.js\"></script>",
      "guideHref": "/guides/seo-geo-difference",
      "priority": 13
    },
    {
      "id": "ai-crawler-directive",
      "engine": "seo",
      "category": "search-access",
      "title": "AI 크롤러 접근 지시",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "robots.txt 에서 AI 관련 토큰의 전체 차단 선언을 찾지 못했습니다.",
      "evidence": "허용된 AI 관련 토큰: GPTBot, ClaudeBot, CCBot, meta-externalagent, Amazonbot, MistralAI-Training, AI2Bot, Bytespider, Google-Extended, Applebot-Extended, OAI-SearchBot, Claude-SearchBot, PerplexityBot, meta-webindexer, MistralAI-Index, Amzn-SearchBot, DuckAssistBot, YandexAdditional, ChatGPT-User, Claude-User, Perplexity-User, meta-externalfetcher, MistralAI-User, Amzn-User",
      "impact": "AI 크롤러를 막으면 AI 검색이 이 페이지를 읽지 못할 수 있습니다. 다만 허용해도 인용·노출이 보장되지는 않습니다.",
      "howToFix": "AI 검색이 읽기를 원하면 robots.txt 에서 해당 봇의 Disallow 를 지우고, 원치 않으면 그대로 두세요. Google-Extended 는 크롤러가 아니라 Gemini 학습·grounding 사용을 제어하는 제품 토큰이며 Google Search 색인·순위에 영향이 없으므로 따로 결정하세요.",
      "codeBefore": "User-agent: OAI-SearchBot\nDisallow: /",
      "codeAfter": "User-agent: OAI-SearchBot\nAllow: /",
      "guideHref": "/guides/ai-crawler-access",
      "priority": 55
    },
    {
      "id": "crawlable-anchor-href",
      "engine": "seo",
      "category": "search-access",
      "title": "크롤러가 따를 수 있는 링크",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "링크 66개 모두 크롤러가 따라갈 수 있는 href 를 가지고 있습니다.",
      "evidence": "https://ad-branch.com/guides/measure-seo-geo#main-content / https://ad-branch.com/ / https://ad-branch.com/seo-geo-check…",
      "impact": "href 가 없거나 javascript: 로 시작하는 링크는 크롤러가 따라가지 못해 연결된 페이지가 발견되지 않을 수 있습니다.",
      "howToFix": "탐색용 링크는 실제 URL 을 가진 <a href> 로 만들고, 동작이 필요하면 button 요소를 쓰세요.",
      "codeBefore": "<a href=\"javascript:void(0)\" onclick=\"go()\">다음 글</a>",
      "codeAfter": "<a href=\"/blog/next-post\">다음 글</a>",
      "guideHref": "/guides/seo-checklist",
      "priority": 35
    },
    {
      "id": "feed-discovery",
      "engine": "seo",
      "category": "search-access",
      "title": "RSS·Atom 피드 알림",
      "verdict": "pass",
      "maxPoints": 0,
      "earnedPoints": 0,
      "finding": "RSS·Atom 피드 알림 링크를 찾았습니다.",
      "evidence": "RSS https://ad-branch.com/rss.xml",
      "impact": "피드는 새 글과 갱신을 알리는 보조 통로입니다. Google 은 RSS 2.0·Atom 1.0 피드를 사이트맵으로 받고, 네이버 서치어드바이저도 RSS 제출을 받습니다. 점수에는 넣지 않는 안내 항목입니다.",
      "howToFix": "블로그·뉴스처럼 글이 쌓이는 사이트라면 피드를 만들고 <head> 에 alternate 링크로 알리세요.",
      "codeBefore": null,
      "codeAfter": "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"사이트 이름\" href=\"https://example.com/rss.xml\">",
      "guideHref": "/guides/sitemap",
      "priority": 60
    },
    {
      "id": "title-missing",
      "engine": "seo",
      "category": "metadata",
      "title": "title 누락",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "내용이 있는 title 이 하나 있습니다.",
      "evidence": "<title>SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치</title>",
      "impact": "title 은 검색결과 제목의 기본 재료입니다. 없으면 Google 이 임의의 문구로 대체해 클릭률이 떨어질 수 있습니다.",
      "howToFix": "<head> 안에 페이지 내용을 요약하는 <title> 을 정확히 하나만 두세요.",
      "codeBefore": "<head>\n  <meta charset=\"utf-8\">\n</head>",
      "codeAfter": "<head>\n  <meta charset=\"utf-8\">\n  <title>페이지 주제를 담은 제목 — 사이트 이름</title>\n</head>",
      "guideHref": "/guides/title-meta-description",
      "priority": 9
    },
    {
      "id": "title-length",
      "engine": "seo",
      "category": "metadata",
      "title": "title 권장 길이",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "title 이 권장 범위(30~60자) 안입니다.",
      "evidence": "<title>SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치</title> — 46자",
      "impact": "30~60자는 검색결과 표시 폭을 고려한 업계 권장값입니다. Google 이 강제하는 글자 수는 아닙니다.",
      "howToFix": "핵심 키워드를 앞에 두고 30~60자 사이로 다듬으세요.",
      "codeBefore": "<title>홈</title>",
      "codeAfter": "<title>무료 SEO·GEO 검사기 사용법과 결과 읽는 법 — 애드브랜치</title>",
      "guideHref": "/guides/title-meta-description",
      "priority": 21
    },
    {
      "id": "meta-description-missing",
      "engine": "seo",
      "category": "metadata",
      "title": "meta description 누락",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "meta description 이 있습니다.",
      "evidence": "<meta name=\"description\" content=\"고치기 전에 기준선을 기록하고, 반영 시간을 감안해 재측정 시점을 정한 뒤 Search Console·Bing·네이버·AI 크롤러 로그를 도구별로 나눠 읽는 순서를 정리합니다.\">",
      "impact": "description 이 없으면 Google 이 본문에서 임의로 스니펫을 만들어 의도한 요약이 노출되지 않을 수 있습니다.",
      "howToFix": "페이지 내용을 요약한 meta description 을 하나만 두세요.",
      "codeBefore": "<head>\n  <title>페이지 제목</title>\n</head>",
      "codeAfter": "<head>\n  <title>페이지 제목</title>\n  <meta name=\"description\" content=\"이 페이지가 무엇을 알려 주는지 한두 문장으로 요약합니다.\">\n</head>",
      "guideHref": "/guides/title-meta-description",
      "priority": 11
    },
    {
      "id": "meta-description-length",
      "engine": "seo",
      "category": "metadata",
      "title": "meta description 권장 길이",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "description 이 권장 범위(70~160자) 안입니다.",
      "evidence": "고치기 전에 기준선을 기록하고, 반영 시간을 감안해 재측정 시점을 정한 뒤 Search Console·Bing·네이버·AI 크롤러 로그를 도구별로 나눠 읽는 순서를 정리합니다. — 98자",
      "impact": "70~160자는 가독성을 위한 업계 권장값이며, Google 은 질의에 따라 스니펫을 다시 쓸 수 있습니다.",
      "howToFix": "핵심 정보를 앞쪽에 두고 70~160자로 정리하세요.",
      "codeBefore": "<meta name=\"description\" content=\"소개\">",
      "codeAfter": "<meta name=\"description\" content=\"URL 하나로 SEO 와 GEO 를 함께 점검하고, 문제마다 근거와 수정 코드를 확인하는 방법을 정리했습니다.\">",
      "guideHref": "/guides/title-meta-description",
      "priority": 22
    },
    {
      "id": "canonical-missing",
      "engine": "seo",
      "category": "metadata",
      "title": "canonical 누락",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "절대 URL 로 된 canonical 선언이 있습니다.",
      "evidence": "<link rel=\"canonical\" href=\"https://ad-branch.com/guides/measure-seo-geo\">",
      "impact": "대표 URL 을 명시하지 않으면 파라미터·www 변형 등 중복 URL 중 어느 것이 대표로 선택될지 통제하기 어렵습니다.",
      "howToFix": "<head> 에 절대 URL 로 된 rel=canonical 링크를 하나만 두세요.",
      "codeBefore": "<link rel=\"canonical\" href=\"/blog/post\">",
      "codeAfter": "<link rel=\"canonical\" href=\"https://example.com/blog/post\">",
      "guideHref": "/guides/canonical",
      "priority": 5
    },
    {
      "id": "canonical-target-valid",
      "engine": "seo",
      "category": "metadata",
      "title": "canonical 대상 유효성",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "canonical 이 같은 origin 의 유효한 HTTPS URL 입니다. 대상 URL 의 실제 응답과 색인 여부는 추가 요청을 하지 않아 확인하지 않았습니다.",
      "evidence": "canonical https://ad-branch.com/guides/measure-seo-geo = 최종 URL https://ad-branch.com/guides/measure-seo-geo",
      "impact": "다른 도메인이나 해석 불가한 URL 을 canonical 로 지정하면 이 페이지가 색인 대표에서 밀려날 수 있습니다.",
      "howToFix": "canonical 은 같은 사이트의 HTTPS 정식 URL 을 fragment 없이 지정하세요.",
      "codeBefore": "<link rel=\"canonical\" href=\"https://another-site.example/page#section\">",
      "codeAfter": "<link rel=\"canonical\" href=\"https://example.com/blog/post\">",
      "guideHref": "/guides/canonical",
      "priority": 4
    },
    {
      "id": "canonical-self-reference",
      "engine": "seo",
      "category": "metadata",
      "title": "자기참조 canonical",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "canonical 이 현재 URL 을 자기참조합니다.",
      "evidence": "canonical https://ad-branch.com/guides/measure-seo-geo = 최종 URL https://ad-branch.com/guides/measure-seo-geo",
      "impact": "자기참조 canonical 은 파라미터가 붙은 변형 URL 이 색인되는 것을 줄여 줍니다.",
      "howToFix": "특별한 이유가 없다면 canonical 을 현재 페이지의 정식 URL 과 같게 맞추세요.",
      "codeBefore": "<link rel=\"canonical\" href=\"https://example.com/blog/post?utm_source=newsletter\">",
      "codeAfter": "<link rel=\"canonical\" href=\"https://example.com/blog/post\">",
      "guideHref": "/guides/canonical",
      "priority": 17
    },
    {
      "id": "meta-robots-directive-quality",
      "engine": "seo",
      "category": "metadata",
      "title": "meta robots nofollow 조합",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "색인·추적을 제한하는 지시가 없습니다.",
      "evidence": "수집한 지시: index, follow",
      "impact": "noindex 와 nofollow 를 함께 쓰면 색인 제거와 링크 추적 차단을 동시에 요청하게 되어 사이트 내부 발견 경로가 끊길 수 있습니다.",
      "howToFix": "색인만 막으려면 noindex,follow 를 쓰고, 공개 페이지에는 제한 지시를 두지 마세요.",
      "codeBefore": "<meta name=\"robots\" content=\"noindex, nofollow\">",
      "codeAfter": "<meta name=\"robots\" content=\"noindex, follow\">",
      "guideHref": "/guides/robots-txt",
      "priority": 18
    },
    {
      "id": "hreflang-syntax",
      "engine": "seo",
      "category": "metadata",
      "title": "hreflang 선언 문법",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "hreflang 선언이 없습니다. 다국어 페이지가 아니라면 문제가 아닙니다.",
      "evidence": "초기 HTML 의 link 요소에서 hreflang 선언을 찾지 못했습니다. HTTP Link 헤더는 이 검사의 수집 범위 밖입니다.",
      "impact": "language tag 나 URL 이 잘못된 hreflang 은 통째로 무시되어 언어별 페이지 연결이 끊깁니다.",
      "howToFix": "hreflang 값은 BCP 47 형식(ko, en-US)으로, href 는 절대 URL 로 적으세요.",
      "codeBefore": "<link rel=\"alternate\" hreflang=\"korean\" href=\"/ko/\">",
      "codeAfter": "<link rel=\"alternate\" hreflang=\"ko\" href=\"https://example.com/ko/\">\n<link rel=\"alternate\" hreflang=\"en-US\" href=\"https://example.com/en/\">\n<link rel=\"alternate\" hreflang=\"x-default\" href=\"https://example.com/\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 23
    },
    {
      "id": "hreflang-reciprocal",
      "engine": "seo",
      "category": "metadata",
      "title": "hreflang 상호참조",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "hreflang 선언이 없어 상호참조 요구가 발생하지 않습니다. 다른 언어 페이지가 이 페이지를 되참조하는지는 추가 요청을 하지 않아 확인할 수 없습니다.",
      "evidence": "초기 HTML 에서 hreflang 선언을 찾지 못했습니다.",
      "impact": "각 언어 버전은 자기 자신을 포함한 모든 변형을 참조해야 Google 이 언어 묶음을 인식합니다.",
      "howToFix": "현재 페이지 URL 을 가리키는 self alternate 선언을 추가하세요.",
      "codeBefore": "<link rel=\"alternate\" hreflang=\"en\" href=\"https://example.com/en/post\">",
      "codeAfter": "<link rel=\"alternate\" hreflang=\"ko\" href=\"https://example.com/blog/post\">\n<link rel=\"alternate\" hreflang=\"en\" href=\"https://example.com/en/post\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 24
    },
    {
      "id": "title-duplicate-sitewide",
      "engine": "seo",
      "category": "metadata",
      "title": "사이트 전체 title 중복",
      "verdict": "unknown",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "단일 페이지 검사로는 확인할 수 없습니다. 다른 URL 을 크롤링해 비교하지 않기 때문입니다.",
      "evidence": "현재 페이지 title: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치",
      "impact": "여러 페이지가 같은 title 을 쓰면 검색결과에서 구분되지 않아 클릭률이 낮아질 수 있습니다.",
      "howToFix": "페이지마다 내용을 구분하는 고유한 title 을 쓰고, 템플릿에는 페이지 고유 값을 넣으세요.",
      "codeBefore": "<title>블로그 | 사이트 이름</title>",
      "codeAfter": "<title>{{ 글 제목 }} | 사이트 이름</title>",
      "guideHref": "/guides/title-meta-description",
      "priority": 57
    },
    {
      "id": "description-duplicate-sitewide",
      "engine": "seo",
      "category": "metadata",
      "title": "사이트 전체 description 중복",
      "verdict": "unknown",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "단일 페이지 검사로는 확인할 수 없습니다. 다른 URL 을 크롤링해 비교하지 않기 때문입니다.",
      "evidence": "현재 페이지 description: 고치기 전에 기준선을 기록하고, 반영 시간을 감안해 재측정 시점을 정한 뒤 Search Console·Bing·네이버·AI 크롤러 로그를 도구별…",
      "impact": "같은 description 이 반복되면 Google 이 이를 무시하고 본문에서 스니펫을 새로 만들 가능성이 큽니다.",
      "howToFix": "페이지마다 내용을 요약한 고유한 description 을 작성하세요.",
      "codeBefore": "<meta name=\"description\" content=\"사이트 공통 소개 문구\">",
      "codeAfter": "<meta name=\"description\" content=\"이 글이 다루는 내용을 한두 문장으로 요약합니다.\">",
      "guideHref": "/guides/title-meta-description",
      "priority": 58
    },
    {
      "id": "title-description-repetition",
      "engine": "seo",
      "category": "metadata",
      "title": "제목·설명 반복 키워드",
      "verdict": "pass",
      "maxPoints": 0,
      "earnedPoints": 0,
      "finding": "제목과 설명에서 과도하게 반복된 키워드를 찾지 못했습니다.",
      "evidence": "토큰 수 확인: title 10개, description 22개",
      "impact": "네이버 서치어드바이저는 title 과 description 에 2회 이상 반복되는 키워드, 제목과 같은 설명은 검색 노출에 불이익을 받을 수 있다고 안내합니다. 반복 기준은 공개되지 않아 이 검사는 애드브랜치가 정한 기준으로 표시만 하고 점수에는 넣지 않습니다.",
      "howToFix": "같은 단어를 되풀이하지 말고, 제목은 주제를 한 번에 설명하는 문구로, 설명은 제목과 다른 1~2문장 요약으로 쓰세요.",
      "codeBefore": "<title>SEO SEO 최적화 가이드</title>",
      "codeAfter": "<title>검색엔진 최적화 실전 가이드</title>",
      "guideHref": "/guides/title-meta-description",
      "priority": 59
    },
    {
      "id": "document-language-consistency",
      "engine": "seo",
      "category": "metadata",
      "title": "문서 언어 일관성",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "선언한 lang 과 감지된 본문 언어가 일치합니다.",
      "evidence": "<html lang=\"ko\"> — 본문 9525자, 감지된 주 언어: ko",
      "impact": "선언한 언어와 실제 본문 언어가 다르면 번역·음성 지원과 지역별 노출 판단이 어긋날 수 있습니다.",
      "howToFix": "html 요소의 lang 을 실제 본문 언어와 같게 맞추세요.",
      "codeBefore": "<html lang=\"en\">",
      "codeAfter": "<html lang=\"ko\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 56
    },
    {
      "id": "h1-missing",
      "engine": "seo",
      "category": "content-structure",
      "title": "H1 누락",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "내용이 있는 H1 이 있습니다.",
      "evidence": "H1: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기",
      "impact": "H1 은 페이지의 주제를 사람과 크롤러에게 알리는 가장 강한 본문 신호입니다.",
      "howToFix": "본문 맨 위에 페이지 주제를 담은 H1 을 하나 두세요.",
      "codeBefore": "<div class=\"title\">페이지 주제</div>",
      "codeAfter": "<h1 class=\"page-title\">페이지 주제</h1>",
      "guideHref": "/guides/heading-structure",
      "priority": 10
    },
    {
      "id": "h1-multiple",
      "engine": "seo",
      "category": "content-structure",
      "title": "H1 복수 사용",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "H1 이 하나입니다.",
      "evidence": "H1: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기",
      "impact": "HTML5 에서 H1 이 여러 개인 것은 오류가 아니지만, 페이지 주제가 하나라면 H1 도 하나일 때 의미가 분명합니다.",
      "howToFix": "주제를 대표하는 H1 하나만 남기고 나머지는 H2 로 낮추세요.",
      "codeBefore": "<h1 class=\"page-title\">섹션 A</h1>\n<h1 class=\"page-title\">섹션 B</h1>",
      "codeAfter": "<h1 class=\"page-title\">페이지 주제</h1>\n<h2>섹션 A</h2>\n<h2>섹션 B</h2>",
      "guideHref": "/guides/heading-structure",
      "priority": 49
    },
    {
      "id": "h1-title-topic-alignment",
      "engine": "seo",
      "category": "content-structure",
      "title": "H1-title 주제 일치",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "title 과 H1 이 같은 주제를 가리킵니다(토큰 유사도 0.90).",
      "evidence": "title: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치 / H1: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기",
      "impact": "title 과 H1 이 전혀 다른 주제를 말하면 검색결과 제목과 페이지 내용이 어긋나 보일 수 있습니다.",
      "howToFix": "title 과 H1 이 같은 핵심 키워드를 공유하도록 다듬으세요.",
      "codeBefore": "<title>회사 소개</title>\n<h1 class=\"page-title\">오늘의 점심 메뉴</h1>",
      "codeAfter": "<title>회사 소개 — 애드브랜치</title>\n<h1 class=\"page-title\">애드브랜치 회사 소개</h1>",
      "guideHref": "/guides/heading-structure",
      "priority": 26
    },
    {
      "id": "heading-order",
      "engine": "seo",
      "category": "content-structure",
      "title": "제목 단계 순서",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "제목 단계를 건너뛴 곳이 없습니다.",
      "evidence": "제목 순서: H1 → H2 → H2 → H3 → H3 → H3 → H3 → H2 → H2 → H2 → H2 → H3 → H2 → H2 → H3 → H3 → H3 → H2 → H2 → H2 → H3 → H3 → H3 → H3",
      "impact": "단계를 건너뛴 제목은 문서 구조를 흐리게 만들어 보조기술과 크롤러의 구간 이해를 어렵게 합니다.",
      "howToFix": "제목은 H1 → H2 → H3 순서로 한 단계씩만 내려가게 배치하세요.",
      "codeBefore": "<h1 class=\"page-title\">주제</h1>\n<h4>세부 항목</h4>",
      "codeAfter": "<h1 class=\"page-title\">주제</h1>\n<h2>세부 항목</h2>",
      "guideHref": "/guides/heading-structure",
      "priority": 25
    },
    {
      "id": "empty-heading",
      "engine": "seo",
      "category": "content-structure",
      "title": "빈 제목",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "제목 24개 모두 텍스트가 있습니다.",
      "evidence": "H1 SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 / H2 왜 기준선부터 남겨야 하는가 / H2 기준선 표: 무엇을 어디서 읽나 / H3 Google: 성과 보고서와 생성형 AI 성과 보고서…",
      "impact": "내용이 없는 제목 요소는 문서 개요를 왜곡하고 보조기술 사용자에게 빈 항목으로 읽힙니다.",
      "howToFix": "장식용으로 제목 태그를 쓰지 말고, 빈 제목은 제거하거나 텍스트를 채우세요.",
      "codeBefore": "<h2><img src=\"/icon.svg\"></h2>",
      "codeAfter": "<h2>섹션 제목 <img src=\"/icon.svg\" alt=\"\"></h2>",
      "guideHref": "/guides/heading-structure",
      "priority": 28
    },
    {
      "id": "body-text-amount",
      "engine": "seo",
      "category": "content-structure",
      "title": "본문 텍스트 존재",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "초기 HTML 에 300자 이상의 본문이 있습니다.",
      "evidence": "가시 텍스트 9525자, 텍스트/HTML 비율 0.192",
      "impact": "초기 HTML 에 읽을 본문이 없으면 검색엔진이 주제를 판단할 근거가 부족합니다. 글자 수 자체가 순위 요건은 아닙니다.",
      "howToFix": "페이지의 핵심 설명을 초기 HTML 본문에 포함하세요.",
      "codeBefore": "<main><div id=\"app\"></div></main>",
      "codeAfter": "<main>\n  <h1 class=\"page-title\">페이지 주제</h1>\n  <p>이 페이지가 다루는 내용을 문단으로 설명합니다.</p>\n</main>",
      "guideHref": "/guides/seo-checklist",
      "priority": 12
    },
    {
      "id": "first-paragraph-topic",
      "engine": "seo",
      "category": "content-structure",
      "title": "첫 문단 주제 명확성",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "첫 문단이 주제 단어(재측정)를 담고 있습니다.",
      "evidence": "첫 문단: 고치기 전에 기준선을 기록하고, 반영 시간을 감안해 재측정 시점을 정한 뒤 Search C…",
      "impact": "첫 문단은 사람과 AI 검색이 페이지 주제를 판단하는 첫 근거입니다.",
      "howToFix": "첫 문단에서 이 페이지가 무엇을 다루는지 핵심어를 포함해 한두 문장으로 밝히세요.",
      "codeBefore": "<p>안녕하세요!</p>",
      "codeAfter": "<p>이 글은 애드브랜치 검사기로 SEO 와 GEO 문제를 찾는 방법을 단계별로 설명합니다.</p>",
      "guideHref": "/guides/geo-checklist",
      "priority": 37
    },
    {
      "id": "paragraph-structure",
      "engine": "seo",
      "category": "content-structure",
      "title": "문단 구조",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "본문이 문단으로 나뉘어 있습니다.",
      "evidence": "본문 9525자, 문단 45개",
      "impact": "긴 글이 문단으로 나뉘지 않으면 읽기 어렵고, 답변 추출 단위도 커져 인용되기 어렵습니다.",
      "howToFix": "주제 단위로 <p> 를 나누고, 한 문단에 한 가지 내용만 담으세요.",
      "codeBefore": "<div>문장1 문장2 문장3 …</div>",
      "codeAfter": "<p>문장1</p>\n<p>문장2</p>",
      "guideHref": "/guides/heading-structure",
      "priority": 38
    },
    {
      "id": "extractable-content-structure",
      "engine": "seo",
      "category": "content-structure",
      "title": "목록ㆍ표ㆍ정의 구조",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "추출하기 쉬운 목록·표 구조가 있습니다.",
      "evidence": "목록 6개, 표 3개, 정의 목록 1개 (본문 9525자)",
      "impact": "목록과 표는 사람과 AI 검색이 항목을 추출하기 쉽게 합니다. SEO 필수 조건은 아닙니다.",
      "howToFix": "절차·비교·항목 나열은 <ul>, <ol>, <table>, <dl> 로 표현하세요.",
      "codeBefore": "<p>1. 첫째 2. 둘째 3. 셋째</p>",
      "codeAfter": "<ol>\n  <li>첫째</li>\n  <li>둘째</li>\n  <li>셋째</li>\n</ol>",
      "guideHref": "/guides/geo-checklist",
      "priority": 50
    },
    {
      "id": "image-alt-missing",
      "engine": "seo",
      "category": "content-structure",
      "title": "의미 있는 이미지 alt 누락",
      "verdict": "not-applicable",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "이미지가 없어 이 규칙을 적용하지 않습니다.",
      "evidence": "초기 HTML 에서 <img> 요소를 찾지 못했습니다.",
      "impact": "alt 가 없으면 보조기술 사용자와 이미지 검색이 이미지의 내용을 알 수 없습니다.",
      "howToFix": "정보를 전달하는 이미지에는 내용을 설명하는 alt 를 쓰고, 장식 이미지에는 alt=\"\" 를 쓰세요.",
      "codeBefore": "<img src=\"/img/chart.png\">",
      "codeAfter": "<img src=\"/img/chart.png\" alt=\"2026년 분기별 검색 유입 추이 그래프\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 27
    },
    {
      "id": "decorative-image-empty-alt",
      "engine": "seo",
      "category": "content-structure",
      "title": "장식 이미지 빈 alt",
      "verdict": "not-applicable",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "이미지가 없어 이 규칙을 적용하지 않습니다.",
      "evidence": "초기 HTML 에서 <img> 요소를 찾지 못했습니다.",
      "impact": "장식 이미지에 파일명 같은 alt 를 넣으면 보조기술이 의미 없는 문자열을 읽어 줍니다.",
      "howToFix": "장식 목적 이미지는 alt=\"\" 로 비워 보조기술이 건너뛰게 하세요.",
      "codeBefore": "<img src=\"/img/banner_01.png\" alt=\"banner_01.png\">",
      "codeAfter": "<img src=\"/img/banner_01.png\" alt=\"\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 52
    },
    {
      "id": "image-dimensions",
      "engine": "seo",
      "category": "content-structure",
      "title": "이미지 widthㆍheight",
      "verdict": "not-applicable",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "이미지가 없어 이 규칙을 적용하지 않습니다.",
      "evidence": "초기 HTML 에서 <img> 요소를 찾지 못했습니다.",
      "impact": "width/height 가 있으면 브라우저가 공간을 미리 잡아 레이아웃 이동(CLS)을 줄일 수 있습니다.",
      "howToFix": "이미지마다 실제 비율에 맞는 width, height 속성을 지정하세요.",
      "codeBefore": "<img src=\"/img/hero.png\" alt=\"히어로 이미지\">",
      "codeAfter": "<img src=\"/img/hero.png\" alt=\"히어로 이미지\" width=\"1200\" height=\"630\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 51
    },
    {
      "id": "empty-link",
      "engine": "seo",
      "category": "content-structure",
      "title": "빈 링크",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "링크 66개 모두 텍스트 이름을 가지고 있습니다.",
      "evidence": "https://ad-branch.com/guides/measure-seo-geo#main-content → 본문으로 건너뛰기 / https://ad-branch.com/ → ↗ 애드브랜치 / https://ad-br…",
      "impact": "접근 가능한 이름이 없는 링크는 보조기술에서 목적지를 알 수 없고 앵커 텍스트 신호도 잃습니다.",
      "howToFix": "링크에 텍스트를 넣거나, 아이콘 링크라면 aria-label 또는 이미지 alt 로 이름을 주세요.",
      "codeBefore": "<a href=\"/pricing\"><svg …></svg></a>",
      "codeAfter": "<a href=\"/pricing\" aria-label=\"요금제 보기\"><svg …></svg></a>",
      "guideHref": "/guides/seo-checklist",
      "priority": 29
    },
    {
      "id": "anchor-text-descriptive",
      "engine": "seo",
      "category": "content-structure",
      "title": "설명적인 링크 텍스트",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "내부 링크 54개 중 모호한 텍스트가 0% 입니다. 이미지 링크의 문맥 의미는 DOM 만으로 판정하지 않았습니다.",
      "evidence": "본문으로 건너뛰기 → https://ad-branch.com/guides/measure-seo-geo#main-content / ↗ 애드브랜치 → https://ad-branch.com/ / 검사기 → https:/…",
      "impact": "‘여기’, ‘더보기’ 같은 링크 텍스트는 목적지를 설명하지 못해 사용자와 크롤러 모두에게 정보가 되지 않습니다.",
      "howToFix": "링크 텍스트에 목적지의 주제를 넣으세요.",
      "codeBefore": "<a href=\"/guides/sitemap\">여기</a>",
      "codeAfter": "<a href=\"/guides/sitemap\">sitemap.xml 만드는 방법</a>",
      "guideHref": "/guides/seo-checklist",
      "priority": 53
    },
    {
      "id": "link-rel-disclosure",
      "engine": "seo",
      "category": "content-structure",
      "title": "sponsoredㆍugc 링크 rel",
      "verdict": "unknown",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "외부 링크의 상업·사용자생성 관계는 HTML 만으로 확정할 수 없어 rel 표식 필요 여부를 판정하지 않습니다.",
      "evidence": "rel 표식이 없는 외부 링크 11개: https://support.google.com/webmasters/answer/7042828 / https://developers.google…",
      "impact": "유료·사용자생성 링크에 rel 표식이 없으면 링크 신호가 의도치 않게 전달될 수 있습니다.",
      "howToFix": "광고·제휴 링크는 rel=\"sponsored\", 사용자 작성 링크는 rel=\"ugc\" 로 표시하세요.",
      "codeBefore": "<a href=\"https://partner.example.com/offer\">제휴 상품</a>",
      "codeAfter": "<a href=\"https://partner.example.com/offer\" rel=\"sponsored nofollow\">제휴 상품</a>",
      "guideHref": "/guides/seo-checklist",
      "priority": 54
    },
    {
      "id": "http-status-success",
      "engine": "seo",
      "category": "technical-seo",
      "title": "최종 HTTP 성공 상태",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "최종 응답이 성공 상태입니다.",
      "evidence": "https://ad-branch.com/guides/measure-seo-geo → HTTP 200 OK",
      "impact": "오류 응답은 색인에서 제외되거나 기존 색인이 제거되는 직접적인 원인입니다.",
      "howToFix": "정상 페이지는 200 을 반환해야 합니다. 이전된 페이지는 301 로 최종 200 URL 까지 연결하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/seo-checklist",
      "priority": 6
    },
    {
      "id": "site-404-probe",
      "engine": "seo",
      "category": "technical-seo",
      "title": "없는 URL의 404 응답",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "없는 URL이 404 상태로 응답해 문서가 없다는 신호를 분명히 보냅니다.",
      "evidence": "GET https://ad-branch.com/adbranch-404-check-c0cfe6fca52e → 404",
      "impact": "없는 주소에도 200 응답을 돌려주면 검색엔진이 빈 안내 화면을 문서로 오해하거나 soft 404로 분류하느라 크롤링을 낭비하고, 사용자는 '없는 페이지'라는 신호를 받지 못합니다.",
      "howToFix": "존재하지 않는 경로에는 404(또는 410) 상태 코드와 안내 페이지를 함께 돌려주세요. SPA 호스팅에서 모든 경로를 index.html로 되돌리는 규칙이 흔한 원인입니다.",
      "codeBefore": "# 모든 경로를 index.html 로 되돌리는 설정\n/*  /index.html  200",
      "codeAfter": "# 없는 경로는 404 페이지와 404 상태로\n/*  /404.html  404",
      "guideHref": "/guides/soft-404",
      "priority": 21
    },
    {
      "id": "soft-404-signals",
      "engine": "seo",
      "category": "technical-seo",
      "title": "soft 404 신호",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "200 응답이며 제목·본문 앞부분에서 부재 안내 신호를 찾지 못했습니다.",
      "evidence": "HTTP 200 / title \"SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치\" / 본문 9525자",
      "impact": "없는 문서에 200 을 돌려주면 검색엔진이 빈 페이지를 색인 후보로 다루게 되어 크롤 예산이 낭비되고 품질 신호가 나빠집니다.",
      "howToFix": "존재하지 않는 URL 은 404(또는 영구 이전이면 301)를 반환하세요. 안내 문구만 바꾸고 200 을 유지하면 soft 404 로 남습니다.",
      "codeBefore": "GET /deleted-page\nHTTP/1.1 200 OK\n\n<title>페이지를 찾을 수 없습니다</title>",
      "codeAfter": "GET /deleted-page\nHTTP/1.1 404 Not Found\n\n<title>페이지를 찾을 수 없습니다</title>",
      "guideHref": "/guides/seo-checklist",
      "priority": 6.5
    },
    {
      "id": "https-enabled",
      "engine": "seo",
      "category": "technical-seo",
      "title": "HTTPS 사용",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "최종 URL 이 HTTPS 이며 중간 HTTP 홉이 없습니다.",
      "evidence": "최종 URL https://ad-branch.com/guides/measure-seo-geo / 리디렉션 경로: https://ad-branch.com/guides/measure-seo-geo",
      "impact": "HTTPS 는 사용자 보호의 기본이며 브라우저 경고와 혼합 콘텐츠 문제를 막습니다.",
      "howToFix": "인증서를 설치하고 HTTP 요청을 HTTPS 로 301 리디렉션하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/seo-checklist",
      "priority": 7
    },
    {
      "id": "final-url-consistency",
      "engine": "seo",
      "category": "technical-seo",
      "title": "최종 URL 일관성",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "입력 URL 이 최대 1회 리디렉션으로 최종 URL 에 도달하고 canonical 과도 일치합니다.",
      "evidence": "입력 https://ad-branch.com/guides/measure-seo-geo → 최종 https://ad-branch.com/guides/measure-seo-geo (리디렉션 0회) / canonical https://ad-branch.com/guides/measure-seo-geo",
      "impact": "입력 URL, 최종 URL, canonical 이 어긋나면 크롤 예산이 낭비되고 대표 URL 선택이 불안정해집니다.",
      "howToFix": "www·슬래시·파라미터 정책을 하나로 정하고 한 번의 리디렉션으로 정식 URL 에 도달하게 하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/canonical",
      "priority": 19
    },
    {
      "id": "redirect-chain-length",
      "engine": "seo",
      "category": "technical-seo",
      "title": "redirect 체인 길이",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "리디렉션이 0회로 짧습니다.",
      "evidence": "리디렉션 0회: https://ad-branch.com/guides/measure-seo-geo",
      "impact": "리디렉션이 길수록 크롤 지연과 신호 손실이 커지고, 순환하면 아예 색인되지 않습니다.",
      "howToFix": "중간 홉을 제거해 최종 URL 로 한 번에 연결하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/canonical",
      "priority": 20
    },
    {
      "id": "response-time",
      "engine": "seo",
      "category": "technical-seo",
      "title": "응답 시간",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "응답이 2초 이내입니다.",
      "evidence": "최종 HTML 헤더 수신까지 5ms (검사 시점 단일 관측치)",
      "impact": "느린 응답은 크롤 효율과 사용자 이탈에 영향을 줍니다. 이 값은 단일 관측치이며 Core Web Vitals 대체값이 아닙니다.",
      "howToFix": "캐시·CDN·서버 렌더링 비용을 점검해 첫 바이트 도착 시간을 줄이세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/seo-checklist",
      "priority": 36
    },
    {
      "id": "html-content-type",
      "engine": "seo",
      "category": "technical-seo",
      "title": "HTML Content-Type",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "HTML 로 선언된 응답입니다.",
      "evidence": "Content-Type: text/html",
      "impact": "Content-Type 이 HTML 이 아니면 브라우저와 크롤러가 문서를 HTML 로 파싱하지 않습니다.",
      "howToFix": "HTML 문서는 text/html; charset=utf-8 로 응답하세요.",
      "codeBefore": "Content-Type: application/octet-stream",
      "codeAfter": "Content-Type: text/html; charset=utf-8",
      "guideHref": "/guides/seo-checklist",
      "priority": 8
    },
    {
      "id": "viewport-meta",
      "engine": "seo",
      "category": "technical-seo",
      "title": "viewport 선언",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "width=device-width 가 선언되어 있습니다.",
      "evidence": "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
      "impact": "viewport 선언이 없으면 모바일에서 데스크톱 폭으로 렌더링되어 읽기 어려워집니다.",
      "howToFix": "head 에 <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> 을 두세요.",
      "codeBefore": "<head>\n  <title>페이지</title>\n</head>",
      "codeAfter": "<head>\n  <title>페이지</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n</head>",
      "guideHref": "/guides/seo-checklist",
      "priority": 30
    },
    {
      "id": "charset-declaration",
      "engine": "seo",
      "category": "technical-seo",
      "title": "charset 선언",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "유효한 charset(utf-8) 이 선언되어 있습니다.",
      "evidence": "meta charset: utf-8 / 헤더 charset: 없음",
      "impact": "인코딩 선언이 없거나 어긋나면 한글이 깨져 표시되고 텍스트 추출도 잘못됩니다.",
      "howToFix": "head 최상단에 <meta charset=\"utf-8\"> 을 두고 응답 헤더의 charset 과 같게 맞추세요.",
      "codeBefore": "<head>\n  <title>페이지</title>\n</head>",
      "codeAfter": "<head>\n  <meta charset=\"utf-8\">\n  <title>페이지</title>\n</head>",
      "guideHref": "/guides/seo-checklist",
      "priority": 31
    },
    {
      "id": "html-lang",
      "engine": "seo",
      "category": "technical-seo",
      "title": "html lang 선언",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "유효한 lang 값이 선언되어 있습니다.",
      "evidence": "<html lang=\"ko\">",
      "impact": "lang 선언은 보조기술의 발음과 번역 판단, 언어별 검색 처리를 돕습니다.",
      "howToFix": "html 요소에 BCP 47 형식의 lang 값을 지정하세요.",
      "codeBefore": "<html>",
      "codeAfter": "<html lang=\"ko\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 32
    },
    {
      "id": "first-image-lazy-loading",
      "engine": "seo",
      "category": "technical-seo",
      "title": "첫 화면 이미지 지연 로딩",
      "verdict": "not-applicable",
      "maxPoints": 0,
      "earnedPoints": 0,
      "finding": "문서에서 검사할 이미지를 찾지 못했습니다.",
      "evidence": "초기 HTML 에 img 요소가 없습니다.",
      "impact": "첫 화면에 보이는 이미지, 특히 LCP 이미지를 loading=\"lazy\" 로 지정하면 표시가 늦어질 수 있습니다. web.dev 는 첫 화면 이미지와 LCP 이미지에 브라우저 기본(eager) 로딩을 권합니다. 문서의 첫 이미지가 로고처럼 작은 요소일 수도 있으니 실제 첫 화면 요소인지 확인하세요. 점수에는 넣지 않습니다.",
      "howToFix": "첫 화면에 보이는 첫 이미지에서 loading=\"lazy\" 를 빼고, 가장 큰 이미지라면 fetchpriority=\"high\" 와 width·height 를 지정하세요.",
      "codeBefore": "<img src=\"/hero.jpg\" alt=\"대표 이미지\" loading=\"lazy\">",
      "codeAfter": "<img src=\"/hero.jpg\" alt=\"대표 이미지\" fetchpriority=\"high\" width=\"1200\" height=\"630\">",
      "guideHref": "/guides/image-loading",
      "priority": 37
    },
    {
      "id": "json-ld-present",
      "engine": "seo",
      "category": "structured-data",
      "title": "JSON-LD 존재",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "JSON-LD 블록이 4개 있습니다.",
      "evidence": "발견한 @type: Organization, WebSite, Article, BreadcrumbList, FAQPage (블록 4개)",
      "impact": "구조화 데이터는 일반 색인의 필수 조건은 아니지만 페이지 엔티티를 명확히 알리는 데 도움이 됩니다. Rich Result 를 보장하지는 않습니다.",
      "howToFix": "페이지 유형에 맞는 JSON-LD 를 head 또는 body 에 추가하세요.",
      "codeBefore": "<head>\n  <title>글 제목</title>\n</head>",
      "codeAfter": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Article\",\n  \"headline\": \"글 제목\",\n  \"image\": \"https://example.com/og/post.png\",\n  \"datePublished\": \"2026-09-03\"\n}\n</script>",
      "guideHref": "/guides/structured-data",
      "priority": 42
    },
    {
      "id": "json-ld-visible-match",
      "engine": "seo",
      "category": "structured-data",
      "title": "구조화 데이터와 본문 일치",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "확인 가능한 구조화 데이터 항목이 화면 본문과 일치합니다.",
      "evidence": "질문 3개, 답변 3개, headline 1개",
      "impact": "Google 구조화 데이터 일반 지침은 독자에게 보이지 않는 내용을 마크업하지 말고 페이지 내용을 그대로 나타내라고 합니다. 어긋나면 리치 결과 자격을 잃는 수동 조치 대상이 될 수 있습니다(순위와는 별개라고 Google 이 설명).",
      "howToFix": "FAQPage 의 질문·답변과 Article 계열의 headline 을 화면 본문과 같은 문장으로 맞추고, 화면에서 지운 문답은 JSON-LD 에서도 지우세요.",
      "codeBefore": "<h1>화면 제목</h1>\n<script type=\"application/ld+json\">{\"@type\":\"Article\",\"headline\":\"다른 제목\"}</script>",
      "codeAfter": "<h1>화면 제목</h1>\n<script type=\"application/ld+json\">{\"@type\":\"Article\",\"headline\":\"화면 제목\"}</script>",
      "guideHref": "/guides/structured-data",
      "priority": 16
    },
    {
      "id": "json-ld-valid-json",
      "engine": "seo",
      "category": "structured-data",
      "title": "JSON-LD JSON 문법",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "JSON-LD 블록 4개가 모두 정상 파싱됩니다.",
      "evidence": "파싱 성공 4/4 블록",
      "impact": "JSON 문법이 깨지면 블록 전체가 무시되어 구조화 데이터가 아예 없는 것과 같아집니다.",
      "howToFix": "따옴표·쉼표를 점검하고 JSON 검사기로 통과시킨 뒤 배포하세요.",
      "codeBefore": "<script type=\"application/ld+json\">\n{ \"@type\": \"Article\", }\n</script>",
      "codeAfter": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Article\",\n  \"headline\": \"글 제목\",\n  \"image\": \"https://example.com/og/post.png\",\n  \"datePublished\": \"2026-09-03\"\n}\n</script>",
      "guideHref": "/guides/structured-data",
      "priority": 14
    },
    {
      "id": "json-ld-context",
      "engine": "seo",
      "category": "structured-data",
      "title": "JSON-LD @context",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "모든 Schema.org 노드가 schema.org @context 를 상속합니다.",
      "evidence": "@context: https://schema.org / @context: https://schema.org / @context: https://schema.org / @context: https://schema.or…",
      "impact": "@context 가 없으면 Schema.org 타입으로 해석되지 않아 마크업이 무시됩니다.",
      "howToFix": "최상위 객체에 \"@context\": \"https://schema.org\" 를 넣으세요.",
      "codeBefore": "<script type=\"application/ld+json\">\n{ \"@type\": \"Article\", \"headline\": \"글 제목\" }\n</script>",
      "codeAfter": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Article\",\n  \"headline\": \"글 제목\",\n  \"image\": \"https://example.com/og/post.png\",\n  \"datePublished\": \"2026-09-03\"\n}\n</script>",
      "guideHref": "/guides/structured-data",
      "priority": 15
    },
    {
      "id": "json-ld-type",
      "engine": "seo",
      "category": "structured-data",
      "title": "JSON-LD @type",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "모든 JSON-LD 블록에 @type 이 있습니다.",
      "evidence": "발견한 @type: Organization, WebSite, Article, BreadcrumbList, FAQPage",
      "impact": "@type 이 없으면 어떤 엔티티인지 해석되지 않아 구조화 데이터가 쓰이지 않습니다.",
      "howToFix": "각 주 엔티티에 Article, WebPage 처럼 구체적인 @type 을 지정하세요.",
      "codeBefore": "<script type=\"application/ld+json\">\n{ \"@context\": \"https://schema.org\", \"name\": \"이름\" }\n</script>",
      "codeAfter": "<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Article\",\n  \"headline\": \"글 제목\",\n  \"image\": \"https://example.com/og/post.png\",\n  \"datePublished\": \"2026-09-03\"\n}\n</script>",
      "guideHref": "/guides/structured-data",
      "priority": 41
    },
    {
      "id": "article-required-properties",
      "engine": "seo",
      "category": "structured-data",
      "title": "Article 권장 정보 점검",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "이 규칙이 확인하는 Article 정보가 모두 있습니다. 실제 내용의 정확성은 별도 검토가 필요합니다.",
      "evidence": "Article 노드 1개 — headline: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 / image: https://ad-branch.com/og/default.png / datePublished: 2026-09-24",
      "impact": "Google Article 문서는 적용 가능한 권장 속성을 안내하며 필수 속성을 정하지 않습니다. 이 규칙의 치명적 판정은 애드브랜치의 자체 우선순위이며, Google의 색인·리치 결과 자격 판정이 아닙니다.",
      "howToFix": "본문에 실제로 해당하는 headline, image, datePublished 정보를 확인하고 날짜는 ISO 8601로 적으세요. 점수만을 위해 이미지·날짜·작성자를 만들어 넣지 마세요.",
      "codeBefore": "{ \"@context\": \"https://schema.org\", \"@type\": \"Article\", \"headline\": \"글 제목\" }",
      "codeAfter": "{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Article\",\n  \"headline\": \"글 제목\",\n  \"image\": \"https://example.com/og/post.png\",\n  \"datePublished\": \"2026-09-03\",\n  \"dateModified\": \"2026-09-03\",\n  \"author\": { \"@type\": \"Person\", \"name\": \"글쓴이\" }\n}",
      "guideHref": "/guides/structured-data",
      "priority": 39
    },
    {
      "id": "webpage-core-properties",
      "engine": "seo",
      "category": "structured-data",
      "title": "WebPage 핵심 속성",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "WebPage 노드에 name 과 url 이 모두 있습니다.",
      "evidence": "WebPage 노드 — name: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 / url: https://ad-branch.com/guides/measure-seo-geo",
      "impact": "name 과 url 이 있어야 이 문서가 어떤 페이지를 가리키는지 분명해집니다. Schema.org 가 강제하는 필수 속성은 아닙니다.",
      "howToFix": "WebPage 노드에 name 과 정식 url 을 넣으세요.",
      "codeBefore": "{ \"@context\": \"https://schema.org\", \"@type\": \"WebPage\", \"name\": \"페이지 이름\" }",
      "codeAfter": "{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"WebPage\",\n  \"name\": \"페이지 이름\",\n  \"url\": \"https://example.com/blog/post\"\n}",
      "guideHref": "/guides/structured-data",
      "priority": 43
    },
    {
      "id": "organization-core-properties",
      "engine": "seo",
      "category": "structured-data",
      "title": "Organization 핵심 속성",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "Organization 노드의 name·url 이 유효합니다.",
      "evidence": "Organization 노드 — name: 애드브랜치 / url: https://ad-branch.com/ / logo: 없음",
      "impact": "발행 주체의 이름·URL·로고는 AI 검색과 검색결과가 엔티티를 식별하는 데 도움이 됩니다. Schema.org 필수 속성은 아닙니다.",
      "howToFix": "Organization 노드에 name, url 을 넣고 logo 는 절대 URL 로 지정하세요.",
      "codeBefore": "{ \"@context\": \"https://schema.org\", \"@type\": \"Organization\", \"name\": \"회사 이름\" }",
      "codeAfter": "{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Organization\",\n  \"name\": \"회사 이름\",\n  \"url\": \"https://example.com\",\n  \"logo\": \"https://example.com/logo.png\"\n}",
      "guideHref": "/guides/structured-data",
      "priority": 44
    },
    {
      "id": "breadcrumb-required-properties",
      "engine": "seo",
      "category": "structured-data",
      "title": "BreadcrumbList 필수 속성",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "breadcrumb 항목 3개가 모두 필수 속성을 갖췄습니다.",
      "evidence": "1. 홈 → https://ad-branch.com/ / 2. 가이드 → https://ad-branch.com/guides / 3. SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 → https://ad-branch.com/guides/measure-seo-geo",
      "impact": "position·name·item 이 빠지면 breadcrumb 마크업 전체가 무시됩니다.",
      "howToFix": "각 ListItem 에 1부터 연속된 position, name, item 을 넣으세요(마지막 항목의 item 은 생략할 수 있습니다).",
      "codeBefore": "{ \"@type\": \"BreadcrumbList\", \"itemListElement\": [{ \"@type\": \"ListItem\", \"position\": 1 }] }",
      "codeAfter": "{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    { \"@type\": \"ListItem\", \"position\": 1, \"name\": \"홈\", \"item\": \"https://example.com/\" },\n    { \"@type\": \"ListItem\", \"position\": 2, \"name\": \"블로그\", \"item\": \"https://example.com/blog\" }\n  ]\n}",
      "guideHref": "/guides/structured-data",
      "priority": 40
    },
    {
      "id": "open-graph-required-properties",
      "engine": "seo",
      "category": "social-sharing",
      "title": "Open Graph 핵심 속성",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "Open Graph 필수 속성 4개가 모두 있습니다.",
      "evidence": "og:title: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치 / og:type: article / og:image: https://ad-branch.com/og/default.png / og:url: https://ad-branch.com/gui…",
      "impact": "OGP 가 정한 네 필수 속성이 없으면 공유 미리보기가 빈 카드나 임의의 텍스트로 표시됩니다. Google 색인의 직접 조건은 아닙니다.",
      "howToFix": "og:title, og:type, og:image, og:url 네 개를 모두 채우세요.",
      "codeBefore": "<head>\n  <title>페이지 제목</title>\n</head>",
      "codeAfter": "<meta property=\"og:title\" content=\"페이지 제목\">\n<meta property=\"og:type\" content=\"article\">\n<meta property=\"og:image\" content=\"https://example.com/og/post.png\">\n<meta property=\"og:url\" content=\"https://example.com/blog/post\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 16
    },
    {
      "id": "open-graph-content-quality",
      "engine": "seo",
      "category": "social-sharing",
      "title": "Open Graph 텍스트 품질",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "og 텍스트 길이와 주제가 페이지와 맞습니다.",
      "evidence": "og:title(46자): SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치 / og:description(98자): 고치기 전에 기준선을 기록하고, 반영 시간을 감안해 재측정 시점을 정한 뒤 Search Console·Bing·네이버·AI 크롤러 로그를 도구별로 나눠 읽는 순서를 정리합…",
      "impact": "og 텍스트가 너무 길거나 페이지 주제와 다르면 공유 카드가 잘리거나 내용을 잘못 전달합니다.",
      "howToFix": "og:title 은 95자 이내, og:description 은 50~200자로 쓰고 페이지 제목·설명과 주제를 맞추세요.",
      "codeBefore": "<meta property=\"og:description\" content=\"환영합니다\">",
      "codeAfter": "<meta property=\"og:description\" content=\"URL 하나로 SEO 와 GEO 문제를 함께 점검하고 수정 코드까지 확인하는 방법을 정리했습니다.\">",
      "guideHref": "/guides/title-meta-description",
      "priority": 46
    },
    {
      "id": "open-graph-image-url",
      "engine": "seo",
      "category": "social-sharing",
      "title": "Open Graph 이미지 URL",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "og:image 가 유효한 HTTPS 절대 URL 입니다. 이미지 응답과 실제 미리보기 생성 여부는 확인하지 않았습니다.",
      "evidence": "<meta property=\"og:image\" content=\"https://ad-branch.com/og/default.png\">",
      "impact": "상대 경로나 HTTP 이미지는 플랫폼이 가져오지 못해 미리보기가 비어 보일 수 있습니다.",
      "howToFix": "og:image 는 https 로 시작하는 절대 URL 로 지정하세요.",
      "codeBefore": "<meta property=\"og:image\" content=\"/og/post.png\">",
      "codeAfter": "<meta property=\"og:image\" content=\"https://example.com/og/post.png\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 45
    },
    {
      "id": "twitter-card-type",
      "engine": "seo",
      "category": "social-sharing",
      "title": "Twitter Card 유형",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "허용된 card 유형(summary_large_image)입니다.",
      "evidence": "<meta name=\"twitter:card\" content=\"summary_large_image\">",
      "impact": "card 유형이 잘못되면 X 가 카드 마크업을 무시합니다. 표시 자체는 플랫폼이 결정합니다.",
      "howToFix": "twitter:card 를 summary, summary_large_image, app, player 중 하나로 지정하세요.",
      "codeBefore": "<meta name=\"twitter:card\" content=\"large_card\">",
      "codeAfter": "<meta name=\"twitter:card\" content=\"summary_large_image\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 47
    },
    {
      "id": "twitter-card-content",
      "engine": "seo",
      "category": "social-sharing",
      "title": "Twitter Card 콘텐츠",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "카드에 쓸 제목과 이미지가 있습니다(og 대체 포함). 플랫폼의 실제 렌더 결과는 확인하지 않았습니다.",
      "evidence": "twitter:card: summary_large_image / 제목: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치 / 이미지: https://ad-branch.com/og/default.png",
      "impact": "제목과 이미지가 모두 없으면 카드가 비어 보일 수 있습니다. 플랫폼이 OG 로 대체할지는 보장되지 않습니다.",
      "howToFix": "twitter:title·twitter:image 를 넣거나 동등한 og:title·og:image 를 채우세요.",
      "codeBefore": "<meta name=\"twitter:card\" content=\"summary_large_image\">",
      "codeAfter": "<meta name=\"twitter:card\" content=\"summary_large_image\">\n<meta name=\"twitter:title\" content=\"페이지 제목\">\n<meta name=\"twitter:image\" content=\"https://example.com/og/post.png\">",
      "guideHref": "/guides/seo-checklist",
      "priority": 48
    },
    {
      "id": "geo-a01-initial-body-text",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "초기 HTML 본문 존재",
      "verdict": "pass",
      "maxPoints": 7,
      "earnedPoints": 7,
      "finding": "초기 HTML 응답 안에서 본문 텍스트를 충분히 찾았습니다.",
      "evidence": "초기 HTML 본문 9525자, 단어 2017개 (기준: 200자 이상 · 80단어 이상)",
      "impact": "본문이 초기 응답에 들어 있으면 공개 HTML만 읽는 도구가 주제를 파악하기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하고, 본문을 클라이언트에서만 그리도록 바꾸지 않는지 배포 때마다 확인하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 493
    },
    {
      "id": "geo-a02-js-render-dependency",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "JS 렌더링 의존 가능성",
      "verdict": "pass",
      "maxPoints": 5,
      "earnedPoints": 5,
      "finding": "초기 HTML 응답만으로 본문을 읽을 수 있는 상태입니다.",
      "evidence": "텍스트/HTML 비율 0.1917 (기준 0.02), script 7개",
      "impact": "렌더링 없이 본문을 읽을 수 있으면 공개 HTML을 그대로 수집하는 도구가 내용을 확인하기 쉬운 구조입니다.",
      "howToFix": "현재 상태를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 495
    },
    {
      "id": "geo-a03-robots-meta-index",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "HTML robots 색인 제한 부재",
      "verdict": "pass",
      "maxPoints": 4,
      "earnedPoints": 4,
      "finding": "HTML robots 메타에 색인 제한 지시가 없습니다.",
      "evidence": "meta robots: index, follow",
      "impact": "문서 수준 색인 제한이 없어 협조적 크롤러가 문서를 읽을 수 있는 상태입니다. 실제 수집 여부는 사업자 정책에 따라 달라질 수 있습니다.",
      "howToFix": "추가 조치가 필요하지 않습니다. X-Robots-Tag 응답 헤더는 이 검사 범위 밖입니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/ai-crawler-access",
      "priority": 496
    },
    {
      "id": "geo-a04-access-block-signals",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "읽기 차단 화면 신호 부재",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "본문 앞부분에서 읽기 차단으로 보이는 문구를 찾지 못했습니다.",
      "evidence": "차단 문구 신호 없음",
      "impact": "본문을 바로 읽을 수 있는 상태로 보이며, 그만큼 내용 확인이 쉬운 구조입니다.",
      "howToFix": "추가 조치가 필요하지 않습니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/ai-crawler-access",
      "priority": 497
    },
    {
      "id": "geo-a05-noscript-fallback",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "대체 본문 안내",
      "verdict": "not-applicable",
      "maxPoints": 2,
      "earnedPoints": 0,
      "finding": "초기 HTML에서 본문을 읽을 수 있어 대체 본문 안내는 평가하지 않았습니다.",
      "evidence": "A02(JS 렌더링 의존 가능성) 통과",
      "impact": "이 항목은 렌더링 의존이 의심될 때만 의미가 있어 점수에서 제외했습니다. 제외는 감점이 아니며, 공개 HTML과 콘텐츠 구조를 바탕으로 한 휴리스틱 평가입니다.",
      "howToFix": "추가 조치가 필요하지 않습니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/ai-crawler-access",
      "priority": 598
    },
    {
      "id": "geo-a06-html-lang",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "문서 언어 선언",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "html 요소에 올바른 형식의 lang 값이 있습니다.",
      "evidence": "<html lang=\"ko\">",
      "impact": "문서 언어가 선언되어 있으면 기계가 언어를 판단하기 쉬운 구조입니다.",
      "howToFix": "현재 설정을 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 498
    },
    {
      "id": "geo-a07-main-landmark",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "콘텐츠 주 영역 표시",
      "verdict": "unknown",
      "maxPoints": 2,
      "earnedPoints": 0,
      "finding": "main/article 영역의 텍스트 비율 정보가 검사 스냅샷에 없어 판정하지 못했습니다.",
      "evidence": "본문 문단 45개 — 초기 HTML 기준 검사라 렌더링 이후 구조는 확인하지 못했습니다.",
      "impact": "주 영역 표시는 문서 구획을 알리는 신호이지만 이번 검사에서는 확인하지 못했습니다. 확인하지 못한 항목은 감점하지 않습니다.",
      "howToFix": "본문 전체를 <main> 또는 <article> 로 감싸면 문서의 주 콘텐츠 구획이 명확해집니다.",
      "codeBefore": null,
      "codeAfter": "<main><article><h1>제목</h1><p>본문…</p></article></main>",
      "guideHref": "/guides/heading-structure",
      "priority": 298
    },
    {
      "id": "geo-a08-ai-crawler-robots",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "AI 크롤러 robots.txt 접근 지시",
      "verdict": "pass",
      "maxPoints": 0,
      "earnedPoints": 0,
      "finding": "확인한 AI 관련 크롤러와 통제 토큰에서 전체 차단 선언을 찾지 못했습니다.",
      "evidence": "검사한 UA 24종 중 robots.txt 에 전용 그룹이 있는 UA: GPTBot, ClaudeBot, Google-Extended, OAI-SearchBot, Claude-SearchBot, PerplexityBot, ChatGPT-User, Claude-User, Perplexit…",
      "impact": "협조적 크롤러의 접근 지시가 허용 상태입니다. 실제 수집·학습·표시는 사업자 정책과 시점에 따라 달라질 수 있습니다.",
      "howToFix": "현재 설정을 유지하고 정책이 바뀌면 목적별 토큰을 다시 확인하세요. 사용자 요청형 도구는 제공사마다 robots.txt 적용 범위가 다릅니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/ai-crawler-access",
      "priority": 500
    },
    {
      "id": "geo-a09-robots-path-access",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "robots.txt 의 현재 경로 접근 지시",
      "verdict": "pass",
      "maxPoints": 0,
      "earnedPoints": 0,
      "finding": "robots.txt 규칙상 현재 경로를 막는 선언을 찾지 못했습니다.",
      "evidence": "현재 경로에 대한 Disallow 규칙 없음",
      "impact": "협조적 크롤러의 접근 지시가 허용 상태입니다. 실제 수집 여부는 사업자 정책에 따라 달라질 수 있습니다.",
      "howToFix": "추가 조치가 필요하지 않습니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/ai-crawler-access",
      "priority": 500
    },
    {
      "id": "geo-a10-llms-txt",
      "engine": "geo",
      "category": "ai-accessibility",
      "title": "llms.txt 안내 파일",
      "verdict": "pass",
      "maxPoints": 0,
      "earnedPoints": 0,
      "finding": "llms.txt 에 제안 형식의 H1 제목이 있습니다.",
      "evidence": "첫 줄: # 애드브랜치 (AdBranch); 요약 줄 있음; 링크 43개; 본문 전체 확인",
      "impact": "llms.txt 는 AI 도구에 사이트의 핵심 문서를 안내하려는 공개 제안 형식입니다(표준 문서가 아님). Google 은 검색과 검색의 AI 기능에서 이 파일을 쓰지 않는다고 밝혔고, 다른 AI 서비스가 읽을 가능성에 대한 공식 확인은 찾기 어렵습니다. 점수에는 넣지 않는 참고 항목입니다.",
      "howToFix": "만든다면 사이트 루트 /llms.txt 에 UTF-8 텍스트로 첫 줄 '# 사이트 이름', 이어서 '> 한 줄 요약', 핵심 페이지 링크 목록을 두세요. 검색 노출만을 위해 만들 필요는 없습니다.",
      "codeBefore": null,
      "codeAfter": "# 애드브랜치\n> SEO·GEO 검사기와 실전 가이드를 제공합니다.\n\n- [SEO·GEO 검사기](https://ad-branch.com/)\n- [가이드](https://ad-branch.com/guides/)",
      "guideHref": "/guides/llms-txt",
      "priority": 500
    },
    {
      "id": "geo-b01-title-h1-topic",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "제목과 H1 의 주제어 일치",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "title 과 H1 이 같은 주제어를 공유합니다.",
      "evidence": "title: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 | 애드브랜치 / H1: SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 / 토큰 일치도 0.90 (기준 0.20)",
      "impact": "제목이 일관되면 문서가 무엇을 다루는지 파악하기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 497
    },
    {
      "id": "geo-b02-lead-direct-answer",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "첫 문단의 직접 답변",
      "verdict": "pass",
      "maxPoints": 5,
      "earnedPoints": 5,
      "finding": "첫 문단이 적정 길이이고 제목의 주제어를 포함한 완결 문장으로 시작합니다.",
      "evidence": "첫 문단 98자(기준 80~450자), 주제어 중첩 2개, 문장 종결 있음",
      "impact": "도입부에서 주제를 바로 다루면 답변 후보 문단을 찾기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 495
    },
    {
      "id": "geo-b03-lead-definition",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "첫 문단의 정의/결론 문장",
      "verdict": "warning",
      "maxPoints": 3,
      "earnedPoints": 1.5,
      "finding": "첫 문단에서 정의 또는 결론 문장 형태를 찾지 못했습니다.",
      "evidence": "첫 문단: 고치기 전에 기준선을 기록하고, 반영 시간을 감안해 재측정 시점을 정한 뒤 Search Console·Bing·네이버·AI 크롤러 로그를 도구별로 나눠 읽는 순서…",
      "impact": "정의가 없으면 문단만 떼어 읽었을 때 주제가 전달되지 않을 가능성이 있습니다.",
      "howToFix": "\"A란 B이다\" 또는 \"결론: …\" 형태의 문장을 첫 문단에 넣으세요.",
      "codeBefore": null,
      "codeAfter": "<p>GEO란 생성형 검색이 문서를 이해하도록 구조를 정리하는 작업이다.</p>",
      "guideHref": "/guides/geo-checklist",
      "priority": 197
    },
    {
      "id": "geo-b04-summary-block",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "핵심 요약 블록",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "요약에 해당하는 소제목·문단 또는 적정 길이의 meta description 을 찾았습니다.",
      "evidence": "고치기 전에 기준선을 기록하고, 반영 시간을 감안해 재측정 시점을 정한 뒤 Search Console·Bing·네이버·AI 크롤러 로그를 도구별로 나눠 읽는 순서를 정리합니다.",
      "impact": "짧은 요약이 있으면 문서의 핵심을 한 덩어리로 확인하기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 497
    },
    {
      "id": "geo-b05-scope-audience",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "범위·대상 명시",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "문서 앞부분에서 대상 독자 또는 범위를 밝히는 표현을 찾았습니다.",
      "evidence": "SEO·GEO 개선 효과를 측정하는 법: 기준선, 재측정, 지표 읽기 본문으로 건너뛰기 ↗ 애드브랜치 검사기 검사 항목 가이드 검사 방법론 소개 ☾ ☀ 무료 검사 시작 → 메뉴 검…",
      "impact": "대상과 범위가 드러나면 어떤 질문에 맞는 문서인지 판단하기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 498
    },
    {
      "id": "geo-b06-ambiguous-words",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "모호한 표현 과다 없음",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "모호한 표현의 비율이 기준 이내입니다.",
      "evidence": "모호 표현 4개 / 단어 2017개 = 0.20% (기준 1.50% 이하) · 예: 등",
      "impact": "구체적인 표현이 많으면 문장 단위로 의미를 파악하기 쉬운 구조입니다.",
      "howToFix": "현재 문체를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 498
    },
    {
      "id": "geo-b07-duplicate-lead",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "중복 도입부 과다 없음",
      "verdict": "not-applicable",
      "maxPoints": 2,
      "earnedPoints": 0,
      "finding": "비교할 도입부 문단이 2개 미만이라 판정하지 않았습니다.",
      "evidence": "문단 1개",
      "impact": "비교 대상이 없어 점수에서 제외했습니다. 제외는 감점이 아니며, 공개 HTML과 콘텐츠 구조를 바탕으로 한 휴리스틱 평가입니다.",
      "howToFix": "문단이 늘어나면 이 항목을 다시 판정합니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 598
    },
    {
      "id": "geo-b08-sentence-length",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "문장 길이 과다 없음",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "문장 평균 길이가 읽기 쉬운 범위 안에 있습니다.",
      "evidence": "문장 109개, 평균 86.4자 (기준 15~120자)",
      "impact": "적당한 길이의 문장은 한 문장만 떼어도 뜻이 통해 인용하기 쉬운 구조입니다.",
      "howToFix": "현재 문체를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 498
    },
    {
      "id": "geo-b09-question-heading-answer",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "질문형 소제목의 답변 문단",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "질문형 소제목마다 충분한 길이의 답변 문단이 이어집니다.",
      "evidence": "질문형 소제목 5개 중 80자 이상 답변 5개",
      "impact": "질문과 답이 붙어 있으면 문답 단위로 내용을 뽑아내기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 497
    },
    {
      "id": "geo-b10-self-contained-paragraphs",
      "engine": "geo",
      "category": "answer-clarity",
      "title": "문단 자립성(맥락 의존 표현)",
      "verdict": "info",
      "maxPoints": 0,
      "earnedPoints": 0,
      "finding": "일부 문단에 맥락 의존 표현이 있습니다.",
      "evidence": "맥락 의존 표현이 있는 문단 1개 / 전체 45개 · 예: 측정에서 가장 자주 생기는 오해는 도구가 보여 주는 값이 “지금”의 값이…",
      "impact": "문단을 떼어 읽었을 때 '위에서 말한', '아래 표' 같은 표현이 가리키는 대상이 사라지면 뜻이 통하지 않습니다. 이 검사는 독자와 발췌 모두를 위해 교차 참조 표현을 찾는 애드브랜치의 가독성 휴리스틱이며 점수에는 넣지 않습니다. Google 은 AI 를 위해 글을 쪼개거나 새로 쓸 필요는 없다고 밝혔습니다.",
      "howToFix": "가리키는 대상을 문단 안에 직접 쓰세요. '위에서 말한 설정' 대신 'robots.txt 의 Disallow 설정'처럼 주어와 대상을 다시 밝히면 그 문단만 읽어도 뜻이 통합니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 400
    },
    {
      "id": "geo-c01-publisher-name",
      "engine": "geo",
      "category": "entity-clarity",
      "title": "발행 조직/사이트명",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "문서를 발행한 조직 또는 사이트 이름을 찾았습니다.",
      "evidence": "발견한 이름: 애드브랜치, 애드브랜치 편집팀",
      "impact": "발행 주체가 드러나면 문서의 출처를 확인하기 쉬운 구조입니다. 조직의 실제 신뢰도는 판단하지 않습니다.",
      "howToFix": "현재 표기를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/structured-data",
      "priority": 497
    },
    {
      "id": "geo-c02-author-info",
      "engine": "geo",
      "category": "entity-clarity",
      "title": "작성자 정보",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "작성자 정보를 찾았습니다.",
      "evidence": "작성자 후보: 애드브랜치 편집팀",
      "impact": "작성자가 밝혀져 있으면 누가 쓴 문서인지 확인하기 쉬운 구조입니다. 전문성이나 사실성은 별도 검토가 필요합니다.",
      "howToFix": "현재 표기를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 497
    },
    {
      "id": "geo-c03-dates",
      "engine": "geo",
      "category": "entity-clarity",
      "title": "게시/수정 날짜",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "ISO 형식의 게시 또는 수정 날짜를 찾았습니다.",
      "evidence": "날짜: 2026-09-24",
      "impact": "날짜가 있으면 어느 시점의 정보인지 확인하기 쉬운 구조입니다. 실제 최신성은 이 검사로 판단하지 않습니다.",
      "howToFix": "내용을 고칠 때 dateModified 도 함께 갱신하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 498
    },
    {
      "id": "geo-c04-entity-consistency",
      "engine": "geo",
      "category": "entity-clarity",
      "title": "엔티티명 일관성",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "조직명 표기가 대체로 일관됩니다.",
      "evidence": "후보: 애드브랜치, 애드브랜치 편집팀",
      "impact": "표기가 일관되면 같은 주체를 가리킨다고 판단하기 쉬운 구조입니다.",
      "howToFix": "현재 표기를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/structured-data",
      "priority": 498
    },
    {
      "id": "geo-c05-contact-path",
      "engine": "geo",
      "category": "entity-clarity",
      "title": "연락/소개 경로",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "소개·문의·개인정보 등 책임 주체로 이어지는 링크를 찾았습니다.",
      "evidence": "링크 5개 (예: https://ad-branch.com/about, https://ad-branch.com/about, https://ad-branch.com/…)",
      "impact": "연락 경로가 있으면 문서의 책임 주체를 확인하기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 498
    },
    {
      "id": "geo-c06-jsonld-type",
      "engine": "geo",
      "category": "entity-clarity",
      "title": "페이지 적합 JSON-LD 유형",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "페이지 유형에 맞는 JSON-LD 유형과 필수 속성을 찾았습니다.",
      "evidence": "발견한 @type: Organization, WebSite, Article, WebPage, BreadcrumbList, ListItem, FAQPage, Question, Answer",
      "impact": "유형에 맞는 구조화 데이터는 기계가 문서 정보를 이해하는 데 도움이 될 수 있으나 표시를 보장하지 않습니다.",
      "howToFix": "내용이 바뀌면 구조화 데이터 값도 함께 갱신하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/structured-data",
      "priority": 498
    },
    {
      "id": "geo-c07-date-integrity",
      "engine": "geo",
      "category": "entity-clarity",
      "title": "게시·수정 날짜 정합성",
      "verdict": "pass",
      "maxPoints": 1,
      "earnedPoints": 1,
      "finding": "확인한 게시·수정 날짜의 형식과 시간 순서가 서로 맞습니다.",
      "evidence": "meta 게시일: 2026-09-24\nmeta 수정일: 2026-09-24\nJSON-LD 노드 1 게시일: 2026-09-24\nJSON-LD 노드 1 수정일: 2026-09-24",
      "impact": "Google 은 화면과 구조화 데이터의 날짜를 일치시키고 미래 날짜를 쓰지 말라고 안내합니다. 앞뒤가 맞지 않는 날짜는 문서의 신선도와 작성 주체에 대한 신뢰를 떨어뜨릴 가능성이 있습니다.",
      "howToFix": "게시일은 처음 공개한 날, 수정일은 내용을 실질적으로 고친 날로 두고 화면 표기·meta·JSON-LD 를 같은 값으로 맞추세요. 내용 변경 없이 날짜만 바꾸지 마세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/publication-dates",
      "priority": 499
    },
    {
      "id": "geo-c08-entity-sameas",
      "engine": "geo",
      "category": "entity-clarity",
      "title": "조직·작성자 외부 프로필 연결",
      "verdict": "info",
      "maxPoints": 0,
      "earnedPoints": 0,
      "finding": "조직 또는 작성자 노드에 sameAs 가 없습니다.",
      "evidence": "유형: Organization · 대상 노드 3개 · sameAs 없음",
      "impact": "Google 은 Organization 구조화 데이터의 권장 속성으로 sameAs 를 둡니다. 실제로 운영하는 공식 프로필을 연결하면 검색엔진과 AI 가 이 조직이나 사람을 같은 이름의 다른 대상과 구분하기 쉬운 구조입니다. 점수에는 넣지 않는 안내 항목입니다.",
      "howToFix": "Organization 또는 Person 노드에 실제로 운영하는 공식 프로필 URL 만 sameAs 배열로 넣으세요. 없는 계정을 만들어 넣을 필요는 없습니다.",
      "codeBefore": null,
      "codeAfter": "{\"@context\":\"https://schema.org\",\"@type\":\"Organization\",\"@id\":\"https://example.com/#organization\",\"sameAs\":[\"https://www.linkedin.com/company/example\"]}",
      "guideHref": "/guides/entity-identity",
      "priority": 400
    },
    {
      "id": "geo-d01-external-source-density",
      "engine": "geo",
      "category": "evidence-trust",
      "title": "본문 외부 출처 링크 밀도",
      "verdict": "pass",
      "maxPoints": 5,
      "earnedPoints": 5,
      "finding": "본문 분량 대비 외부 출처 링크가 기준을 넘습니다.",
      "evidence": "외부 링크 11개 / 단어 2017개 = 1,000단어당 5.45개 (기준 1개 이상)",
      "impact": "출처 링크가 있으면 주장을 확인할 경로가 함께 제시된 구조입니다. 링크 수가 많다고 좋은 출처라는 뜻은 아니며, 출처의 정확성·권위는 판단하지 않습니다.",
      "howToFix": "현재 구조를 유지하고 링크가 살아 있는지 주기적으로 확인하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 495
    },
    {
      "id": "geo-d02-references-section",
      "engine": "geo",
      "category": "evidence-trust",
      "title": "참고/출처 섹션",
      "verdict": "warning",
      "maxPoints": 2,
      "earnedPoints": 1,
      "finding": "참고/출처 구획과 외부 링크의 조합을 찾지 못했습니다.",
      "evidence": "참고 구획 없음 / 외부 링크 11개",
      "impact": "근거 목록이 없으면 문서가 무엇을 참고했는지 확인하기 어려울 가능성이 있습니다.",
      "howToFix": "본문 끝에 \"참고 자료\" 소제목을 두고 인용한 문서의 링크를 나열하세요.",
      "codeBefore": null,
      "codeAfter": "<h2>참고 자료</h2>\n<ul><li><a href=\"https://example.org/report\">2026 조사 보고서</a></li></ul>",
      "guideHref": "/guides/geo-checklist",
      "priority": 198
    },
    {
      "id": "geo-d03-number-source-link",
      "engine": "geo",
      "category": "evidence-trust",
      "title": "수치의 근거 연결",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "수치와 함께 출처·조사·기준을 밝히는 표현이나 외부 링크를 찾았습니다.",
      "evidence": "수치 20개, 근거 표현 있음, 외부 링크 11개",
      "impact": "수치에 근거가 붙어 있으면 값을 확인하기 쉬운 구조입니다. 수치의 참·거짓은 HTML만으로 판정할 수 없습니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 497
    },
    {
      "id": "geo-d04-as-of-date",
      "engine": "geo",
      "category": "evidence-trust",
      "title": "기준일/데이터 시점",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "수치와 함께 연도 또는 기준 시점 표현을 찾았습니다.",
      "evidence": "수치 20개, 기준 시점 표현 있음",
      "impact": "시점이 적혀 있으면 언제 기준의 값인지 확인하기 쉬운 구조입니다.",
      "howToFix": "값이 바뀌면 기준 시점도 함께 갱신하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 498
    },
    {
      "id": "geo-d05-citation-context",
      "engine": "geo",
      "category": "evidence-trust",
      "title": "주장과 인용의 인접성",
      "verdict": "pass",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "설명 문단 안에서 출처 링크를 찾았습니다.",
      "evidence": "외부 링크 11개 중 30자 이상 문단 안에 있는 링크 11개",
      "impact": "주장 옆에 근거가 붙어 있으면 어떤 문장을 뒷받침하는 링크인지 확인하기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 497
    },
    {
      "id": "geo-d06-review-info",
      "engine": "geo",
      "category": "evidence-trust",
      "title": "검토/편집 정보",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "검토 또는 감수자를 밝히는 표기를 찾았습니다.",
      "evidence": "Search Console",
      "impact": "제작 과정을 밝히면 문서가 어떻게 만들어졌는지 확인하기 쉬운 구조입니다. 실제 검토 수행 여부는 확인하지 못합니다.",
      "howToFix": "현재 표기를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 498
    },
    {
      "id": "geo-d07-quotation-block",
      "engine": "geo",
      "category": "evidence-trust",
      "title": "인용문 구조",
      "verdict": "info",
      "maxPoints": 3,
      "earnedPoints": 3,
      "finding": "인용문 블록을 찾지 못했습니다. 모든 문서에 인용문이 필요한 것은 아니라 참고로 남깁니다.",
      "evidence": "blockquote/q 0개",
      "impact": "인용문이 없다고 문제로 보지는 않습니다. 원문을 그대로 옮길 때 blockquote 를 쓰면 구분이 쉬워질 수 있습니다.",
      "howToFix": "원문 문장을 옮길 때 <blockquote> 안에 넣고 출처를 밝히세요.",
      "codeBefore": null,
      "codeAfter": "<blockquote cite=\"https://example.org/report\">인용 문장…</blockquote>",
      "guideHref": "/guides/geo-checklist",
      "priority": 397
    },
    {
      "id": "geo-e01-subheading-density",
      "engine": "geo",
      "category": "extractable-structure",
      "title": "논리적 소제목 밀도",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "본문 분량 대비 소제목 밀도가 적정합니다.",
      "evidence": "H2/H3 23개, 단어 2017개, 300단어당 3.42개",
      "impact": "소제목이 있으면 문서 구조를 따라 필요한 구획만 읽기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 498
    },
    {
      "id": "geo-e02-heading-order",
      "engine": "geo",
      "category": "extractable-structure",
      "title": "제목 단계 순서",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "제목 단계가 건너뛰지 않고 순서대로 이어집니다.",
      "evidence": "제목 24개, 단계 건너뜀 0회",
      "impact": "단계가 순서대로면 문서 개요를 구조 그대로 읽기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 498
    },
    {
      "id": "geo-e03-qa-structure",
      "engine": "geo",
      "category": "extractable-structure",
      "title": "Q&A 구조",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "FAQPage 구조화 데이터에서 질문과 답변 쌍을 찾았습니다.",
      "evidence": "FAQPage Question/acceptedAnswer 3쌍",
      "impact": "질문과 답이 쌍으로 표시되면 문답 단위로 내용을 뽑아내기 쉬운 구조입니다. 리치 결과 표시 여부와는 무관합니다.",
      "howToFix": "화면에 보이는 내용과 구조화 데이터의 답변을 같게 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 498
    },
    {
      "id": "geo-e04-definition-structure",
      "engine": "geo",
      "category": "extractable-structure",
      "title": "정의문 구조",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "정의 목록 또는 정의문 형태의 문장을 찾았습니다.",
      "evidence": "정의 목록(dl) 1개, 정의문 패턴 0개",
      "impact": "개념 정의가 분명하면 용어 단위로 내용을 뽑아내기 쉬운 구조입니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/geo-checklist",
      "priority": 498
    },
    {
      "id": "geo-e05-step-structure",
      "engine": "geo",
      "category": "extractable-structure",
      "title": "단계별 설명",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "순서를 나타내는 표현과 항목 구조를 찾았습니다.",
      "evidence": "단계 표현 8개, 목록 항목 34개",
      "impact": "절차가 순서대로 나뉘어 있으면 단계 단위로 내용을 옮기기 쉬운 구조입니다.",
      "howToFix": "절차는 <ol> 순서 목록으로 감싸면 순서 의미가 더 분명해집니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 498
    },
    {
      "id": "geo-e06-list-or-table",
      "engine": "geo",
      "category": "extractable-structure",
      "title": "목록 또는 표",
      "verdict": "pass",
      "maxPoints": 2,
      "earnedPoints": 2,
      "finding": "목록 또는 표로 정리된 구조를 찾았습니다.",
      "evidence": "목록 항목 34개, 표 3개",
      "impact": "항목이 구조화되어 있으면 값 단위로 내용을 옮기기 쉬운 구조입니다. 내용의 정확성은 판단하지 않습니다.",
      "howToFix": "현재 구조를 유지하세요.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 498
    },
    {
      "id": "geo-e07-table-header",
      "engine": "geo",
      "category": "extractable-structure",
      "title": "표 헤더·캡션",
      "verdict": "unknown",
      "maxPoints": 2,
      "earnedPoints": 0,
      "finding": "표 3개를 찾았지만 th/caption 정보가 검사 스냅샷에 없어 판정하지 못했습니다.",
      "evidence": "table 3개, th/caption 수집 정보 없음",
      "impact": "표의 머리글 유무를 확인하지 못해 감점하지 않았습니다. 실제 구조는 다를 수 있습니다.",
      "howToFix": "각 표에 <th> 머리글과 <caption> 설명을 넣으면 표의 의미가 분명해집니다.",
      "codeBefore": null,
      "codeAfter": "<table><caption>요금 비교</caption><tr><th>구분</th><th>월 요금</th></tr></table>",
      "guideHref": "/guides/heading-structure",
      "priority": 298
    },
    {
      "id": "geo-e08-paragraph-length",
      "engine": "geo",
      "category": "extractable-structure",
      "title": "짧은 문단 비율",
      "verdict": "not-applicable",
      "maxPoints": 1,
      "earnedPoints": 0,
      "finding": "40자 이상 문단이 3개 미만이라 문단 길이 분포를 판정하지 않았습니다.",
      "evidence": "40자 이상 문단 1개",
      "impact": "표본이 작으면 비율이 흔들릴 가능성이 있어 점수에서 제외했습니다.",
      "howToFix": "본문이 길어지면 이 항목을 다시 판정합니다.",
      "codeBefore": null,
      "codeAfter": null,
      "guideHref": "/guides/heading-structure",
      "priority": 599
    }
  ],
  "topPriorityIds": ["geo-b03-lead-definition", "geo-d02-references-section"],
  "limitations": [
    "사이트 전체의 title과 meta description 중복은 단일 페이지 검사로 확인할 수 없습니다.",
    "다른 페이지에서 연결되지 않는 고립 페이지 여부는 확인할 수 없습니다.",
    "사이트 전체 내부 링크 그래프와 링크 구조는 확인할 수 없습니다.",
    "여러 페이지가 같은 검색어를 겨루는 키워드 충돌은 확인할 수 없습니다.",
    "다른 URL과의 콘텐츠 중복은 확인할 수 없습니다.",
    "각 링크 대상의 실제 HTTP 상태 코드와 리디렉션은 확인할 수 없습니다.",
    "JavaScript 렌더링 이후의 제목, 본문, 링크 및 구조화 데이터는 확인할 수 없습니다."
  ],
  "subrequestCount": 5
}
