16개월 구글 서치 콘솔 데이터를 벡터 데이터베이스로 변환한 후 배운 점
metehan.ai조회수 083일 전
핵심
SEO 자동화 에이전트인 OpenClaw의 한계(과거 검색 성능 데이터 부재)를 보완하기 위해, 16개월간의 구글 서치 콘솔(GSC) 데이터를 ChromaDB 벡터 데이터베이스로 구축하고 생성형 AI(Gemini, Grok, Claude)로 자연어 쿼리가 가능하도록 개발. 이 과정에서 벡터 데이터베이스의 장단점을 명확히 파악했다.
구축한 시스템
파이프라인 구조:
- GSC API로 모든 데이터 추출(쿼리, 페이지, 클릭, 노출수(impressions), 클릭률(CTR), 순위, 날짜)
- 원본 행을 쿼리-페이지 쌍 문서로 집계하고, 계산된 트렌드(상승, 하락, 안정, 신규) 추가
- Gemini의 임베딩 모델로 모든 데이터를 벡터화하여 ChromaDB에 저장
- 벡터 데이터베이스에서 의미론적 검색을 수행하고 결과를 LLM으로 분석
LLM 제공자 다중화:
- Gemini Flash: 빠르고 무료, 빠른 확인용
- Grok: 200만 토큰 컨텍스트 윈도우로 벡터 DB에서 50개 대신 400개 문서 전송 가능
- Claude: 더 전략적이고 미묘한 권장사항 제공
경쟁사 콘텐츠 분석:
- Parallel.ai의 검색 및 추출 API로 자신의 페이지와 경쟁사 페이지를 스크래핑하여 LLM으로 콘텐츠 갭 분석 수행
- GSC 데이터는 순위를, 스크래핑된 콘텐츠는 그 이유를 알려줌
벡터 데이터베이스 접근의 문제점
수치적 정확성 부재:
- GSC 데이터는 구조화된 데이터(행과 열, 쿼리, 숫자, 날짜)로 SQL 데이터베이스를 위해 설계됨
- "노출수가 높지만 CTR이 낮은 쿼리 찾기"라고 물으면, 벡터 데이터베이스는 실제 계산을 하지 않음. 그 문장을 임베딩하고 의미론적으로 유사한 문서를 찾을 뿐
SELECT * FROM gsc WHERE impressions > 1000 AND ctr < 0.03같은 SQL 쿼리와는 근본적으로 다른 작동- 벡터 DB는 임베딩 공간에서 텍스트가 가까웠다는 이유만으로 노출수 200의 쿼리를 반환할 수 있고, 텍스트 표현이 맞지 않아 노출수 50,000의 쿼리를 놓칠 수 있음
- 수치적 정확성이 보장되지 않음
SQL의 우위:
- "상위 10개 페이지(클릭 기준)" 또는 "기기별 평균 CTR" 같은 집계에서 SQL은 정확한 답을 항상 제공하지만, 벡터 DB는 텍스트 유사성에 기반한 최선의 근사만 제공
벡터 데이터베이스가 실제로 도움이 되는 경우
의미론적 검색:
- "내 사이트에서 AI에 관한 콘텐츠는 어떻게 수행되나?"라고 물으면, 벡터 DB는 "neural network tutorial", "transformer architecture explained", "deep learning vs machine learning" 같은 쿼리를 찾음
- 이들은 "AI"라는 단어를 포함하지 않지만 의미론적으로 관련됨
- SQL에서 이를 얻으려면 가능한 모든 주제에 대해 수동으로 키워드 목록을 만들어야 하는데 확장성이 없음
자연어 인터페이스:
- "기술 SEO 콘텐츠에서 뭔가 일어나고 있나?"처럼 모호하고 탐색적인 질문을 던질 수 있음
- SQL에서는 질문을 작성하기 전에 정확히 무엇을 찾고 있는지 알아야 함
패턴 발견:
- 관련 쿼리가 임베딩 공간에서 클러스터를 이루면서 스프레드시트를 스크롤할 때는 놓칠 만한 패턴이 드러남
세 가지 접근법의 비교
| 특성 | 벡터 DB | GSC MCP 서버 | SQL DB | |------|---------|---------|--------| | 데이터 신선도 | 오래됨(새로고침 필요) | 실시간 | 오래됨(가져오기 필요) | | 수치 정확성 | 모호함 | 정확함 | 정확함 | | 의미론적 검색 | 예 | 아니오 | 아니오 | | 자연어 쿼리 | 예 | 아니오 | 아니오 | | 16개월 히스토리 | 예 | API 할당량으로 제한됨 | 예 | | 속도 | 즉시(로컬) | 느림(API 호출) | 즉시(로컬) | | 경쟁사 콘텐츠 분석 | 예(Parallel.ai 경유) | 아니오 | 아니오 | | 최적 용도 | 탐색 및 발견 | 실시간 빠른 조회 | 정확한 지표 필터링 |
이상적인 설정:
- 정확한 수치 쿼리를 위한 SQL + 의미론적 발견을 위한 벡터 DB + 상단의 LLM 레이어
- 현재 도구는 벡터 DB 쪽으로 기울어 있어 탐색 분석에 강하지만 정확한 지표 필터링에는 덜 정확
실제로 가치있는 부분
데이터 처리 파이프라인이 가장 중요:
- GSC API는 쿼리당 페이지당 날짜당 한 행을 반환. 16개월 동안 괜찮은 트래픽이 있는 사이트의 경우 수백만 행
- 데이터 프로세서가 이를 의미있는 문서로 집계: 총 클릭수, 평균 CTR, 가중 평균 순위, 최근 성능 대 과거 성능 비교 기반 트렌드 분류
- 이 집계 단계가 벡터 DB나 LLM에 닿기 전에 노이즈를 신호로 변환
- 없으면 원본 API 행을 임베딩하는데 대부분 무용지물
Parallel.ai 통합이 두 번째:
- GSC 데이터는 "무엇이 일어나고 있는가"만 알려줌
- 경쟁사가 뭘 다르게 하는지는 모름
- 실제 페이지 콘텐츠를 스크래핑하고 GSC 지표와 함께 LLM에 제공하면 분석이 "CTR이 낮다"에서 "경쟁사는 비교표와 FAQ 섹션이 있는데 당신은 없다"로 진화
사용 방법
오픈소스 공개:
- github.com/metehan777/vectordb-gsc
- Google Cloud 서비스 계정(Search Console API 접근), 무료 Gemini API 키, 선택사항으로 Grok/Claude/Parallel.ai 키 필요
설치 및 실행:
git clone https://github.com/metehan777/vectordb-gsc.git
cd vectordb-gsc
pip install -r requirements.txt
첫 실행:
python main.py extract # 16개월 데이터 끌어오기
python main.py process # ChromaDB에 임베딩
쿼리:
python main.py ask "which queries are declining?" --grok
python main.py audit "https://yoursite.com/page/" --grok
python main.py compete "your target keyword" --claude
다시 시작한다면
개선 사항:
- ChromaDB와 함께 DuckDB 추가
- 특정 수치나 임계값이 포함된 질문에는 SQL 사용
- 의미론적 발견과 주제 클러스터링에는 벡터 DB 사용
- LLM이 질문에 따라 어느 백엔드를 쿼리할지 결정
임베딩 방식 개선:
- 현재: 각 문서는 "Query: seo tools, Page: /blog/seo, Clicks: 150, Impressions: 5000" 같은 텍스트 설명
- 문제: 수치값이 임베딩 공간에서 손실됨
- 더 나은 방법: 지표를 메타데이터로 별도 저장하고 의미론적 콘텐츠(쿼리 텍스트, 페이지 URL, 주제)만 임베딩
현재 버전의 실제 가치:
- 패턴 찾기, 기회 발견, 일반적인 조언 대신 실제 데이터에 근거한 콘텐츠 추천
- MIT 라이선스로 공개, 개선 기여 환영