LLM WikiAccess-protected knowledge portal

Go 수집기 — 기존 vs 변경

무엇이·왜·어떻게 바뀌었나 + 바뀐 수집 시퀀스

crawler-lib-golang · 2026-05 · 기반: go-missing-index-path 분석

!한 장 요약

1왜 바꿨나 — "누락"의 정체

최초 분석(docs/go-missing-index-path-report.md)의 핵심: 누락 점검 스크립트의 비교 기준은 이랬다.

index Path → 소문자로 변환 DB PRODUCT_KEY → LOWER(product_key) 두 문자열이 같으면 found, 아니면 "not found(누락)"

따라서 "not found"는 "Go 모듈이 실제로 없음"이 아니다. 정확히는 "index path를 소문자로 만든 값과 같은 PRODUCT_KEY가 DB에 없음"일 뿐이다.

Go의 진짜 키는 go.modmodule 라인에 선언된 값(declared module path)이다. 그래서 index가 준 Path수집 후보로만 보고, worker가 proxy.golang.org/{path}/@v/{version}.mod를 확인해 선언된 module path를 대표 PRODUCT_KEY로 저장해야 한다.

processed=6 의 의미 — "수집 실패"가 아니라 "이 index path는 대표 키가 아니라서, go.mod에 선언된 module path 쪽으로 저장했다"는 표시.

2한눈 비교

항목기존 (V1)변경 (V2)
목록 테이블 grainindex path 1개당 1행, 버전 미저장(INDEX_PATH, INDEX_VERSION) 이벤트당 1행, 버전 저장
식별 · 중복 비교LOWER() 비교 (대소문자 무시)해시 PK sha256(path@version) + 식별 컬럼 as_cs
대표 키(PRODUCT_KEY)index path를 그대로go.moddeclared module path
존재 판단 기준pkg.go.dev 의존 → 404면 누락 오판proxy(@v/list@latest). pkg.go.dev는 metadata만
alias/.git·subpath·declared-diff미해결 → "누락"으로 빠짐분류 후 declared로 저장, index행 processed=6
대소문자 다른 모듈ai_ci로 한 행에 합쳐져 손실gatheringdb as_cs 테이블로 둘 다 보존
재수집개념 약함RESYNC 컬럼(이벤트별) / GO_RESYNC_ALL(전체)
저장 위치labradordb (ai_ci)gatheringdb (as_cs, Go 전용)

3"누락처럼 보인" 6패턴 → V2 처리

분석 보고서의 실제 사례를 패턴으로 묶은 것. 모두 "진짜 없음"이 아니라 식별/해결 문제였다.

패턴실제 예시V2 처리
proxy만 있음
(pkg.go.dev 404)
codeberg.org/go-toolbox/x
codeberg.org/elbtech/polival
proxy 기준 수집. @v/list 비면 @latest 한 개만 저장. metadata는 빈값 가능
declared가 index에 없음…/juxianjinggan/src
2024-contexts.shylinux.com/x/juxianjinggan
index path로 fetch한 버전을 쓰되 저장 키만 declared로. index행 processed=6 (declared 자체 proxy는 404라 재조회 불가)
alias .git / repo≠module…/go-latex/latex.git…/latex
codeberg.org/godoc/godocs.iogodocs.io
대표는 module path 하나. alias/repo path 행은 processed=6
subpath(하위 패키지)41.neocities.org/diana/widevine…/diana.mod의 module root를 대표 키로 저장
대문자 포함eduVPN/vpn-ca, goern/HookedGo별개 모듈로 보존. proxy 조회는 대문자를 !+소문자로 escape (edu!v!p!n)
중복 index 이벤트같은 path 여러 번중복 제거 후 1회만 판단

4수집 시퀀스 — 기존 vs 변경

기존 V1 index path 기준

  1. index에서 Path 받음 (버전은 목록에 안 남김)
  2. Path.lower()LOWER(PRODUCT_KEY) 비교로 존재 확인
  3. 없으면 그 index path 그대로 수집 시도
  4. declared path 해결·alias/subpath 분기·proxy fallback이 약함

→ alias/.git·subpath·declared-diff·proxy-only가 누락되거나 잘못된 키로 저장. 대소문자 다른 모듈은 합쳐짐.

변경 V2 이벤트 단위 worker

  1. 이벤트 (INDEX_PATH, INDEX_VERSION) claim
  2. DB에 있으면 스킵 (단 RESYNC=1이면 건너뛰고 재수집)
  3. proxy에서 그 버전 go.mod fetch (없으면 @latest fallback)
  4. module 라인 → declared. store = declared or index
  5. 분류: same / alias_git / subpath / declared_diff
  6. version·product·license를 store(declared) 기준으로 빌드
  7. 한 트랜잭션 저장 — 같으면 processed=1, 다르면 processed=6, deprecated=1
핵심 차이: ① 큐 단위가 (path)→(path,version), ② index path를 그대로 쓰지 않고 go.mod로 진짜 키 해결, ③ 존재 판단을 proxy로.

5식별 & 대소문자

기존

키 = index path 비교 = LOWER(...) (대소문자 무시) 저장 = ai_ci 테이블 결과 = Foo/Bar 와 foo/bar 가 같은 키 → 한 행으로 덮어쓰기 (손실)

변경

큐 PK = sha256(path @ version) (byte 기준) 식별 = as_cs (대소문자 구분) 저장 = gatheringdb as_cs 테이블 결과 = Foo/Bar 와 foo/bar 가 다른 키 → 둘 다 보존
버전 테이블 ~1,900만 행 중 대문자 포함 경로 ~114만 건. 기존엔 충돌 위험, 변경 후엔 보존. (단 proxy 조회 URL은 대문자를 ! escape — 이건 기존·변경 공통 규칙)

6존재 판단 기준의 전환

소스기존 역할변경 역할
index.golang.org목록(후보) 제공목록(후보) 제공 — 동일
proxy.golang.org보조존재의 기준 (@v/list@latest)
pkg.go.dev존재 판단에 사용 → 404면 누락 오판metadata 보강만 (404여도 proxy 있으면 수집)
규칙: 존재는 proxy가, 설명/라이선스 등 metadata는 pkg.go.dev가 담당. pkg.go.dev가 404여도 proxy에 있으면 수집하고, metadata만 비워 둔다.

7요약

index path를 소문자로 비교하던 방식에서 → 이벤트 단위 큐 + go.mod로 진짜 module path 해결 + proxy 기준 존재 판단 + 대소문자 구분 저장으로 바꿔, 누락·오저장·대소문자 손실을 없앴다.