o2o-site-AEO/docs/NAVER_EO.md
민헌 76d51207c6 [feat] geo,docs,nginx: 네이버 탐색 모듈 geo 추가 — 발행 전/후 점검 · IndexNow 알리기 대행
네이버 쪽에는 창이 없었다. 서치어드바이저 소유확인이 안 붙어 사이트맵 제출·수집 요청·
진단을 쓸 수 없었고, 유일한 자동 통로인 IndexNow 는 조용히 0건이었다 —
indexnow.py 가 읽는 <out>/s/<slug>/sitemap.xml 을 프리렌더가 더는 굽지 않는데
(사이트 한 장 → 루트 사이트맵 통합) 발행 잡은 경고 한 줄만 남기고 성공한다.
조사 결과 AI 브리핑 출처는 네이버 생태계 편향이라, 네이버에서의 목표를 "인용" 이 아니라
"플레이스↔홈페이지 결합 + 웹문서 검색 노출" 로 다시 잡았다(docs/NAVER_EO.md).

- geo/: solution·admin 을 고치지 않고 import 만 하는 최상단 모듈. 밖에서 HTTP 로만 본다
  - naver/checks.py: 소유확인(상태코드가 아니라 내용 — SPA 폴백이 200 을 준다) · Yeti 랜딩 ·
    통보 URL 재현 · 웹문서 색인(근사) · 스마트플레이스 역방향 링크
  - naver/robots.py: 네이버 관점 판정 — Yeti·Daumoa · 사이트맵 지시 · JS/CSS 자산 차단
    (RFC 9309 그룹 경계: 규칙 뒤의 User-agent 는 새 그룹)
  - naver/notify.py: 루트 사이트맵에서 주소를 골라 IndexNow 통보. 백엔드가 고쳐지는 날
    GEO_NOTIFY_ENABLED=0 으로 끈다(담당 중복 = 429)
  - scripts/preflight.py(발행 전·오리진) · postflight.py(발행 후·200 확인 뒤에만 통보) ·
    watch.py(사이트맵 lastmod 변화만). 상태는 성공분만 geo/state/ 에 기록
  - naver/web_search.py: 웹문서검색 호출기 — 백엔드를 못 고쳐 여기 있다. 쿼터 카운터가 둘로 갈린다
- nginx/site.conf.example: 소유확인 location = 블록(주석). 메타태그는 solution/frontend 수정이라 제외
- .env.example: NAVER_SITE_VERIFICATION · GEO_NOTIFY_ENABLED · GEO_STATE_DIR
- docs: NAVER_EO.md(조사·설계) · AGENTS·README·ARCHITECTURE 4절·DEPLOY 2-2·DEVLOG

가짜 사이트맵·IndexNow 서버로 통보 7시나리오(slug 경계·dry-run·중복 없음·lastmod 변경분·
비200 미통보) · preflight 정상/고장 · robots 판정 · 소유확인 4분기 통과.
실도메인·pytest 는 미실행(.venv·.env 없음). solution/·admin/ 무변경.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B8SMKqBu9N723AxVBJhACW
2026-09-14 10:17:28 +09:00

216 lines
15 KiB
Markdown

# NAVER_EO — 네이버에서 탐색되게 만들기 (조사와 설계)
> 조사일 2026-09-11. 구현 현황은 [geo/README.md](../geo/README.md),
> 제품 판단은 [PRODUCT.md](PRODUCT.md), 발행 절차는 [DEPLOY.md](DEPLOY.md).
**이 문서를 쓴 이유.** 우리 AEO·SEO 는 구글·AI 크롤러를 겨냥해 만들어졌다. 네이버는
구조가 달라서 같은 노력이 같은 결과를 내지 않는다. 무엇이 다르고, 그래서 **무엇을 목표로
잡아야 하는지**를 먼저 정한다.
---
## 0. 한 문장으로
> 네이버에서 우리 목표는 **"AI 답변에 인용되기"가 아니라, "플레이스와 공식 홈페이지가 한
> 업소로 묶이고 웹문서 검색에 잡히기"** 다.
[PRODUCT.md 1절](PRODUCT.md)이 말하는 "AI 검색이 이 가게를 공식 홈페이지 기준으로 설명하게"는
ChatGPT·Perplexity·Gemini 에는 그대로 통한다. **네이버에서는 경로가 다르다** — 아래 2절이 근거다.
이 차이를 모른 채 같은 전략을 밀면, 되지 않는 일에 시간을 쓰고 **될 일(플레이스 결합)을 놓친다.**
---
## 1. 조사 — 사실과 출처
**출처 성격을 같이 적는다.** 네이버는 랭킹 요소를 공개하지 않아서 업계 관측이 많이 섞인다.
관측을 공식처럼 인용하면 그 위에 쌓은 설계가 조용히 틀린다.
| # | 사실 | 성격 |
|---|---|---|
| 1 | 네이버 검색은 **통합검색 → 스마트블록(에어서치) → AI 브리핑** 층으로 답을 조립한다. 하나의 키워드를 의도 단위 블록으로 쪼갠다 | 공식 + 관측 |
| 2 | **AI 브리핑**이 생성형 AI 검색의 본류다. 2025-03 도입, 답변 근거로 쓴 **출처 콘텐츠를 함께 제시**한다. 실험 서비스 `Cue:` 는 **2026-04-09 종료** | 공식(보도) |
| 3 | ★★ **AI 브리핑의 출처는 네이버 생태계(블로그·카페·지식iN)와 뉴스·공식문서 비중이 높다** | 업계 관측 |
| 4 | AI 브리핑에 인용되는 조건으로 관측되는 것 넷: **정의형·Q&A 구조 · 경험 기반 수치 · 주제 세분화(주제당 1문서) · 신뢰 신호(작성자·자격, Schema 마크업)** | 업계 관측 |
| 5 | **C-Rank**(출처의 신뢰도) · **D.I.A / D.I.A+**(문서가 질의 의도에 얼마나 맞나)는 **블로그 중심** 알고리즘이다. 웹문서/사이트에 그대로 적용된다는 근거는 없다 | 관측 |
| 6 | 웹문서·사이트 노출은 **보장되지 않는다.** 콘텐츠 품질과 이용자 선호를 종합해 네이버가 판단한다 | 공식 |
| 7 | ★ **사이트명·사이트설명·Open Graph 제목·Open Graph 설명이 품질 판단 기준에 들어간다** | 공식 |
| 8 | **복사·붙여넣기한 내용은 "유사 문서"로 판단해 노출에서 제외**한다. 스팸이 아니어도 품질을 떨어뜨린다고 보면 노출되지 않는다 | 공식 |
| 9 | 신규 사이트는 **수집·노출까지 약 2~14일** | 공식 |
| 10 | **Yeti** 는 JS 영향도를 측정·해석하지만 **SSR 을 권장**한다. robots.txt 로 JS·CSS 리소스를 막으면 **그 페이지가 수집되지 않는다** | 공식 |
| 11 | 서치어드바이저 기능: **소유확인 · 수집 요청 · 사이트맵/RSS 제출 · 웹페이지 최적화 진단 · 노출·클릭 통계** | 공식 |
| 12 | 진단이 보는 필수 항목: **`<title>` · `meta description` · `<h1>` · 이미지 `alt`** (+ 프로토콜 불일치 내부링크, 접근 차단 리소스 등 10여 유형) | 공식 |
| 13 | 통계는 **최대 90일**, 플랫폼별 노출·클릭, **검색 키워드 top10 · 검색 문서 top10** | 공식 |
| 14 | 소유확인은 **HTML 파일 업로드 또는 `<head>` 메타태그**. DNS TXT 를 받지 않는다 | 공식 |
| 15 | **IndexNow 지원 (2023-07)** — 새 페이지·수정·삭제를 통보할 수 있다 | 공식 |
| 16 | 플레이스 순위는 **정보 충실도보다 행동 데이터**(저장·예약·주문·길찾기·리뷰·재방문)가 무겁다. **사업자 인증으로 등록한 업체가 우선**되는 경향 | 업계 관측 |
---
## 2. 그래서 우리 제품에 무엇을 의미하나
### 2-1. ★ 가장 중요한 판단 — 네이버에서는 "인용"을 목표로 두지 않는다
조사 3·4 가 핵심이다. AI 브리핑은 **자기 생태계 문서를 우선 인용**하고, 인용 조건으로 관측된
것들(주제당 1문서, 경험 수치, 작성자 신뢰)은 **블로그 운영 전략**이다. 우리 산출물은 사장님
한 곳당 정적 한 장이고, 블로그를 운영하지 않는다.
**네이버 AI 브리핑 인용을 성공 기준으로 잡으면 안 된다.** 잡으면 두 가지가 따라온다:
① 되지 않는 일(생태계 밖 문서를 인용원으로 밀기)에 비용을 쓰고,
② "주제당 1문서" 를 따르려고 **[사이트 하나 = 한 장](ARCHITECTURE.md) 결정을 흔든다** —
그 결정은 페이지가 얇아지면 색인에서 버려진다는 근거로 내린 것이다(2026-08-31).
### 2-2. 네이버에서 우리가 실제로 가질 수 있는 자리 셋
| | 무엇 | 근거 | 지금 |
|---|---|---|---|
| **A. 웹문서 검색 노출** | "상호명" 질의에 공식 홈페이지가 잡힌다 | 조사 6·7·8·10 | 정적 HTML·OG 완비로 **조건은 이미 충족**. 등록이 안 돼 있다 |
| **B. 플레이스 ↔ 홈페이지 결합** | 스마트플레이스 "홈페이지" 칸이 우리 주소를 가리킨다 | 조사 16 | **비어 있다.** 사장님이 직접 넣어야 하고, 안내하는 자리가 없다 |
| **C. 공식 출처 지위** | 뉴스·공식문서 층에서 "그 업소의 1차 출처" 로 취급 | 조사 3·7 | 판단 근거가 약하다. 관측 대상 |
**A 와 B 가 이번 설계의 목표다.** C 는 A·B 가 서면 따라올 수 있는 것이지 직접 만들 수 없다.
### 2-3. 이미 하고 있어서 안 할 일
조사 7·8·10·12 가 요구하는 것은 **우리가 이미 다른 이유로 하고 있다.**
| 네이버가 보는 것 | 우리 쪽 이미 있는 자리 |
|---|---|
| SSR / 정적 HTML (조사 10) | 발행물이 정적 HTML — 제품 원칙 1번 |
| OG 제목·설명 (조사 7) | `seo/head.ts` 의 og:* + `og:locale ko_KR` |
| `<title>` · description · `h1` · `alt` (조사 12) | `seo/meta.ts`(길이 50~160자 보정) · 게이트가 alt 없는 사진을 안 싣는다 |
| 유사문서 회피 (조사 8) | **게이트 규칙 2 — 고유 콘텐츠 0건이면 발행 거부** |
| robots 로 JS·CSS 를 막지 않기 (조사 10) | `seo/robots.ts``Allow: /` 이고 앱 경로만 막는다 |
**네이버용으로 새로 만들 문서 최적화는 거의 없다.** 빈 것은 **등록·결합·측정**이다.
이게 이 조사의 결론이고, 아래 설계가 그 셋만 다루는 이유다.
---
## 3. 설계 — 네 층, 순서가 곧 우선순위
### L0. 등록 (전제 — 이게 없으면 나머지가 관측 불가)
```
소유확인 → 사이트맵 제출 → 수집 요청 → 진단 확인 → 통계 열림
```
- 소유확인은 **메타태그 또는 HTML 파일**뿐이다(조사 14). 우리 구성에서의 함정과 절차는
[DEPLOY.md 2-2단계](DEPLOY.md) — 루트의 `*.html` 은 nginx SPA 폴백으로 떨어져 **404 가 아니라
빌더 앱 HTML 이 200 으로** 나간다
-**등록 전에는 창이 아예 없다.** 사이트맵 제출·수집 요청·진단·통계가 전부 등록된 사이트에만
열린다. IndexNow 는 등록 없이도 동작하지만 **먹었는지 볼 방법이 없다**
- 오리진이 하나라 **루트에서 한 번** 하면 `/s/<slug>` 전부가 딸려온다
### L1. 문서 품질 — 진단 항목과 1:1 로 맞춘다
조사 12 의 필수 4항목은 우리가 이미 채운다(2-3절). 여기서 할 일은 **만드는 것이 아니라
어긋남을 잡는 것**이다. `geo/naver/checks.py` 가 보는 자리:
- `<title>` 존재·길이, `meta description` 존재·길이, `h1` 1개, 이미지 `alt` 누락 수
- 프로토콜 불일치 내부링크 — TLS 를 앞단 Apache 가 끊어 nginx `$scheme` 가 늘 `http`
이 구성에서 **실제로 밟을 수 있는 함정**이다([AGENTS.md](../AGENTS.md))
- ⚠️ **진단은 네이버가 자기 기준으로 다시 본다.** 우리 점검이 통과해도 진단이 지적할 수 있다 —
점검은 "명백히 빠진 것" 을 미리 잡는 것이고, 확정 판정은 서치어드바이저다
### L2. 엔티티 결합 — 여기가 네이버에서 가장 값어치 있는 자리
| | 방향 | 지금 |
|---|---|---|
| 우리 → 네이버 | `sameAs` 에 확정된 플레이스·예약 URL | **있다**(`seo/jsonld.ts`, 확정 채널만) |
| **네이버 → 우리** | 스마트플레이스 "홈페이지" 칸 = 발행본 주소 | ★ **없다. 이번 설계의 핵심 공백** |
| 값 일치 | 상호·주소·전화가 플레이스와 같아야 한다 | 수집이 플레이스에서 오므로 대개 같다. **틀어진 것을 잡는 점검이 없다** |
**역방향이 왜 중요한가.** 조사 16 에 따르면 플레이스는 사업자 인증 업체를 우선하고, 순위는
행동 데이터로 움직인다. **우리는 행동 데이터를 만들 수 없다.** 우리가 줄 수 있는 건
"이 업소의 공식 홈페이지가 여기다" 라는 **결합 신호 하나**이고, 그건 사장님이 스마트플레이스에
주소를 넣는 것으로만 생긴다. 비용 0, 우리가 통제 불가, 효과는 가장 큼 →
**제품이 해야 할 일은 "사장님이 그걸 하도록 만드는 것"** 이다(발행 완료 화면의 안내 한 줄).
### L3. AEO — 네이버판은 "인용" 이 아니라 "질문에 답하는 형태"만 가져온다
조사 4 의 넷 중 **우리 구조에 맞는 둘만** 취한다.
| 조건 | 취하나 | 왜 |
|---|---|---|
| 정의형·Q&A 구조 | **취한다** | 우리 FAQ·핵심정보 블록이 이미 그 형태다. `llms.txt` 도 같다 |
| 경험 기반 수치 | **취한다** | 확인된 fact(체크인 시각·주차 대수·요금)가 곧 수치다. **지어내지 않는다**는 규칙과 충돌하지 않는다 |
| 주제 세분화(주제당 1문서) | ❌ **안 한다** | "사이트 하나 = 한 장" 결정과 정면 충돌. 쪼개면 페이지가 얇아진다([ARCHITECTURE.md 5절](ARCHITECTURE.md)) |
| 작성자·자격 신뢰 신호 | **부분** | 사업자 정보·검증 시각은 있다. **개인 작성자 자격은 우리 제품에 없는 개념**이다 |
### L4. 측정 — 확정 창은 서치어드바이저 하나뿐이고 API 가 없다
| 무엇 | 어떻게 | 한계 |
|---|---|---|
| 확정 노출·클릭·키워드 top10 | 서치어드바이저 화면 | ★ **공개 API 가 없다.** 사람이 보는 수밖에 없다 |
| 색인 여부(근사) | **웹문서 검색 API**로 우리 호스트가 잡히나 | 통합검색 색인과 **같지 않다.** 잡히면 확실, 없으면 **미확정** |
| 역방향 링크 | **지역검색 API**의 `place_url` | 후보 5건·전화번호 없음 → 동명 업소 판별이 약하다. 단정하지 않는다 |
| 통보가 나갔나 | IndexNow 응답 + 통보 URL 존재 여부 | 먹었는지는 등록 후 서치어드바이저로만 |
⚠️ **쿼터.** 네이버 검색 API 는 앱당 **일 25,000회**이고 지역검색·웹문서검색이 **공유**한다.
사이트가 1,000개면 점검 1회에 2,000회다 — **전수 점검을 매일 돌릴 수 없다.**
→ 설계에 넣을 것: **표본 점검 + 변경분 우선**, 그리고 호출 예산을 코드가 알고 멈추는 상한.
---
## 4. 구현 계획 — 무엇을 언제
### 이미 있는 것 (`geo/naver/checks.py`)
소유확인 파일 · Yeti 로 랜딩 · IndexNow 통보 URL 재현 · 웹문서 색인(근사) · 역방향 링크.
### P1 — 지금 할 것 (제약 안에서 가능)
0. ~~알리기~~**완료.** `geo` 가 맡는다(발행 후 `postflight.py`, 자동은 `watch.py`)
1. **L1 진단 항목 점검 추가**`<title>`·description·`h1`·`alt`·프로토콜 불일치 링크.
발행본 HTML 을 받아 세는 것뿐이라 외부 호출이 0이다
2. **값 일치 점검** — 플레이스의 상호·주소·전화 vs 발행본 JSON-LD. 지역검색 1회로 본다
3. **호출 예산** — 점검 1회당 네이버 API 상한을 코드가 알고 넘으면 멈춘다(위 쿼터)
### P2 — 제약이 풀려야 하는 것
| | 왜 막혀 있나 |
|---|---|
| ~~IndexNow 고장 수정~~ | **우회했다**`geo/naver/notify.py` 가 루트 사이트맵을 읽어 대신 보낸다. 백엔드를 고치는 날 `GEO_NOTIFY_ENABLED=0` 으로 여기를 끈다 |
| 스마트플레이스 안내 UI | 발행 완료 화면은 `solution/frontend` 다. **L2 의 핵심 공백이 여기 걸려 있다** |
| 주기 재확인 잡 | `JobType`·`worker/handlers.py` 등록표가 백엔드에 있다. 우회하려면 `geo/Dockerfile` + 자기 스케줄러 |
| 점검 결과 저장·추이 | 표가 필요하고, **읽는 화면이 생긴 뒤에 만든다**([geo/README.md](../geo/README.md)) |
**P2 의 첫 줄이 가장 급하다.** L0~L2 를 다 해도 IndexNow 가 0건이면 네이버에 **알릴 통로가
없다** — 수집을 2~14일(조사 9) 기다리는 것과 즉시 통보의 차이다.
---
## 5. 아직 안 정한 것
- **L3 의 "주제 세분화" 를 영구히 거절할 것인가.** 지금은 거절이고 근거는 "한 장" 결정이다.
네이버 스마트블록에서 세분화가 실제로 얼마나 유리한지는 **우리 데이터로 측정한 적이 없다**
- **서치어드바이저 통계를 사람이 보는 것 말고 방법이 있나.** API 가 없다. 화면 캡처·수동 입력은
사람 손이 든다. 그럴 값어치가 있는지는 사이트 수가 늘어난 뒤 판단
- **네이버 AI 브리핑 인용이 정말 불가능한가.** 조사 3 은 **업계 관측**이다. 반증이 나오면
2-1 절을 다시 쓴다 — 그때 이 문서에 날짜와 함께 적는다
## 6. 하지 않는 것
| 안 한다 | 왜 |
|---|---|
| 블로그·카페 대량 발행으로 인용 노리기 | 유사문서 판정(조사 8) 대상이고, [PRODUCT.md 6절](PRODUCT.md) non-goal 이다 |
| 플레이스 행동 데이터 만들기(저장·리뷰 유도) | 어뷰징이다. 우리가 줄 것은 결합 신호뿐이다 |
| 네이버 검색창 긁어 순위 보기 | 봇 탐지 우회 영구 금지([DECISIONS.md](DECISIONS.md) 1-1). 공식 API 만 쓴다 |
| 키워드를 노린 문서 자동 증식 | 게이트 규칙 2 를 우회하는 짓이다. 게이트가 제품이다 |
---
## 출처
조사일 2026-09-11. 공식 문서(서치어드바이저·웹마스터 도구 안내)는 도구 화면 안에 있어 직접
링크가 어려운 것이 있고, 그 경우 이를 인용한 2차 자료를 적었다.
- 네이버 IndexNow 지원 — <https://news.hada.io/topic?id=19225>
- 네이버 AI 브리핑 · `Cue:` 종료 — <https://www.i-boss.co.kr/ab-2877-16898>
- AI 브리핑 인용 조건(관측) — <https://blog.oneplan.co.kr/naver-ai-search-optimization/>
- C-Rank · D.I.A(관측) — <https://locaposting.com/blog/naver-crank-dia-algorithm>
- 웹마스터 도구 노출 조건·품질 기준(공식 인용) — <https://www.imweb.me/faq?mode=view&category=29&category2=35&idx=623>
- 서치어드바이저 기능·진단 항목 — <https://www.interad.com/insights/naver-search-advisor-update>
- 소유확인·사이트맵 제출 절차 — <https://help.sixshop.com/learn-sixshop/store-manager/add-ons/naver-webmaster>
- 플레이스 순위 요소(관측) — <https://bbima.kr/blog/naver-place-ranking-2026>