웹 검색엔진을 처음부터 2개월 만에 3억 개 뉴럴 임베딩으로 구축하기
(blog.wilsonl.in)- 검색엔진 품질 저하와 Transformer 기반 임베딩 모델의 발전을 계기로, 2개월 동안 3억 개 임베딩 기반 웹 검색엔진을 개발한 경험을 다룸
- 총 200개의 GPU 클러스터, 대규모 분산 크롤러, RocksDB, HNSW 등의 고성능 인프라와 알고리듬을 통해, 실시간 자연어 이해 검색 구현
- 키워드 매칭이 아닌 의도 중심 질의 응답을 목표로, 문서 파싱과 문맥 보존을 위한 정규화, 청킹, 셋넌스 연결 등 다양한 NLP/ML 기법 적용
- 파이프라인, 스토리지, 서비스 메쉬, 벡터 인덱스 등 각 계층별로 대규모 분산 시스템 설계와 병목점/비용 최적화 방안 소개
- 최종적으로 초저지연, 대규모 분산, 고정확성의 개인 맞춤형 검색엔진이 탄생했음을 서술함
개요 및 동기
- 필자는 최근 검색엔진 품질 저하와 SEO 스팸, 비관련 콘텐츠 증가에 대한 문제의식, 그리고 Transformer 기반 임베딩 모델의 자연어 이해력이 높아진 환경에서 검색엔진을 처음부터 구축하기로 결정함
- 기존 검색엔진의 한계는 인간 수준의 질문 이해력 부족과 키워드 기반의 단순 매칭에서 비롯됨
- 좋은 품질의 콘텐츠가 항상 상위에 노출되도록 하고, 긴 뒷부분까지 고루 탐색하는 의도 중심 랭킹이 목표임
- 웹 검색엔진 구축 과정은 컴퓨터 과학, 언어학, 온톨로지, NLP, ML, 분산 시스템, 성능 엔지니어링 등 다양한 영역을 포괄함
- 이번 프로젝트는 2개월 동안 인프라나 사전 경험 없이 순수하게 혼자서 시작해 완전히 새로운 검색엔진을 구현하는 도전임
전체 시스템 구성
- 200개의 GPU 클러스터에서 SBERT 기반 텍스트 임베딩 3억 개를 생성함
- 동시 수백 대의 크롤러가 초당 50,000페이지를 수집, 총 2.8억 개 인덱스 구축
- RocksDB와 HNSW를 200코어, 4TB RAM, 82TB SSD에 샤딩하여 저장 및 인덱싱
- 쿼리 응답 전체 지연시간은 약 500ms 수준으로 설정함
- 전체 구조와 흐름은 크롤러, 파이프라인, 스토리지, 임베딩 벡터 인덱스, 서비스 메쉬, 프론트/백엔드 영역으로 분리됨
임베딩 기반 검색 실험 및 개선
Neural Embedding Playground
- SBERT 등 임베딩 모델을 활용한 검색은 기존 키워드 중심 검색보다 자연스러운 질의 이해와 정확도가 높음이 실험을 통해 확인됨
- 입력 쿼리의 의도를 문맥 및 문장 단위로 파악해 실제로 관련성이 높은 정답을 추출하는 것이 가능함
전통 검색 vs. 뉴럴 검색 예시
- 기존 검색: 무작위성 결과, 키워드 일치 위주
- 임베딩 검색: 질문의 맥락과 의도 파악, 정확한 핵심 문장 또는 개념 중심 결과 제공
- 복잡한 개념 결합, 암묵적/복합 질문, 품질 신호가 담긴 쿼리에 대해 의미 기반 정답 탐색 가능
웹 페이지 파싱 및 정규화
-
HTML에서 의미적 텍스트 요소만을 추출, 레이아웃·제어 요소 등 노이즈 제거하는 정규화 목표
-
WHATWG, MDN 등 표준에 맞춰 p, table, pre, blockquote, ul, ol, dl 등 테이블 구조 유지
-
메뉴, 네비게이션, 댓글, 인터페이스 등 크롬 요소 완전 제거
-
사이트별(예: en.wikipedia.org) 특수 규칙 적용하여 과도/부족 추출 문제 해결
-
의미 기반 구조화 데이터(meta, OpenGraph, schema.org 등)도 활용해 지식 그래프 구축과 랭킹 개선 가능
청킹 및 문맥 보존
문장 단위 청킹
- 임베딩 모델의 한계를 극복하기 위해 전체 페이지가 아닌 문장 기반 단위 청킹 적용
- 청킹 시 자연스러운 문장 경계, 문법, 축약, URL, 비공식 표현 등 다양한 경우의 수를 spaCy sentencizer로 정확히 구분함
문맥 보존 및 연결
- 문장 간 의존관계, 헤딩, 파라그래프, 표 등을 파악해 문맥 정보까지 함께 묶어서 임베딩
- 예를 들어 테이블 구조도 각 행의 의미를 잃지 않도록 상위 헤딩/조항 등을 연쇄적으로 연결해서 삽입함
문장 체인(Statement Chaining)
- DistilBERT 분류기로 한 문장과 이전 문장을 함께 분석하여, 문맥 의존성 확인 및 체인 추출을 자동화함
- 임베딩 시, 상위 종속 문장들을 모두 함께 포함해 문맥 유지력을 높임
프로토타입 활용 결과
- 샌드박스 환경에서 다양한 실전 쿼리 실험을 통해 기존 방법 대비 훨씬 정확한(문맥 맞춤형) 질의응답을 확인함
- 키워드 불일치, 생략/은유/복합 질문 등도 앱이 의도를 인식해 올바른 문맥 문장 매칭—숨은 지식과 관계도 효과적으로 발굴함
대규모 웹 크롤러(노드 기반)
- 업무 분산을 위한 워크 스틸링, 도메인 별 동시성/트래픽 제어, DNS/URL/헤더 검증 등 다양한 안정성 및 효율성 고려
- 크롤러는 비동기 I/O 기반 Promise, 디도스에 강한 메커니즘, 자원 관리(메모리, 딜레이, 백오프), 노이즈 도메인 탐지 등 적용
- URL 정규화, 프로토콜 및 포트/유저정보 제한, Canonicalization으로 중복/비정상 URL 필터링 강화를 진행함
파이프라인(분산 태스크 큐)
- 각 페이지 상태를 PostgreSQL에서 관리, 초반에는 직접 Polling/트랜잭션 활용
- 대규모 분산 환경(수천 크롤러)에서 스케일 문제, 대기열/락 병목 발생 → Rust 기반 인메모리 코디네이터로 큐 상태 관리
- 태스크 구조: 해시맵 기반 인덱스, 바이너리 힙, 도메인 그룹, 랜덤 Poll, 자리 바꾸기(swap_remove) 등 다양한 인덱싱
- 태스크별 메모리 100B 수준, 128GB 서버에서 1B 태스크도 처리 가능
- 이후 SQS 대체용 Open Source RocksDB 기반 대기열 개발, 1노드에서 30만 ops/초 지원
스토리지 설계(Oracle → PostgreSQL → RocksDB)
- 초반 Oracle Cloud(저비용 egress/저장), 이후 PostgreSQL(TOAST)까지 사용했으나, 쓰기확장/성능 한계에 직면
- PostgreSQL의 MVCC, Write Amplification, WAL 등의 특성상 대규모 병렬 INSERT 시 병목, 결국 KV 스토어인 RocksDB로 전환
- RocksDB의 블롭 별도 저장(BlobDB), SST 파일, 멀티 쓰레드, 해시 인덱싱 등으로 NVMe SSD 최대 성능 활용
- 64개의 RocksDB 샤드로 확장—각 샤드는 xxHash(key) 기반 라우팅, Serde+MessagePack 직렬화 사용
- 최종적으로 수천 클라이언트(크롤러/파서/벡터라이저)에서 20만 ops/초 처리, 메타 및 블롭 분리/압축 저장
서비스 메쉬 및 네트워킹
- 인프라 확장 시 서비스 인스턴스 자동 검색/통신 보안 위해 mTLS+HTTP2 기반 설계
- Node마다 루트 CA 기반 인증서 적용, MessagePack 직렬화 직접 이용, 내부 DNS 및 CoreDNS, 커스텀 클라이언트 SDK 등 개발
- 기존 VPN(ZeroTier, Tailscale) 사용 경험 있으나, 네트워크/성능/운영 상의 문제로 직접 HTTP+mTLS 선택
- 시스템 서비스 제어(systemd + cgroup + journald)로 관리 일원화, 경량화 및 표준화 실현
대규모 GPU 임베딩 생성 파이프라인
- 초기에 OpenAI API 활용, 비용 문제로 Runpod 등 고성능 GPU 환경으로 이전
- 파이프라인은 각 스테이지를 비동기로 분리, GPU 효율 90% 이상, 250대 GPU에서 초당 10만 embeddings 생성
- Rust 파이프라인, Python inference → named pipe로 IPC, 구조적 백프레셔(backpressure)로 자원 자동 튜닝
벡터 인덱싱(HNSW/샤딩)
- HNSW 알고리듬을 이용한 메모리 기반 벡터 서치, ANN(Approximate Nearest Neighbor)로 초저지연
- RAM 한계 도달 시 노드별 균등 샤딩(64노드), 각 샤드는 개별 HNSW 인덱스로 병렬 검색
- HNSW 특성상 대량 RAM 필요, 라이브 업데이트 한계 존재 → 결국 CoreNN이라는 디스크기반 오픈소스 벡터DB로 이전
- CoreNN은 128GB RAM, 단일 노드에서도 3B 임베딩 고정확 조회 가능
검색엔진 UX와 지연 최적화
- 검색엔진 UX는 즉시성 응답이 핵심(로드 인디케이터 X, 전통적 SSR)
- Cloudflare Argo 등으로 에지 PoP에 근접, HTTP/3 채택해 전송 지연 최소화
- 앱 서버 수준에서 모든 데이터 준비, 개별 API 라운드트립 최소화, 미니파이 및 압축된 페이지 즉각 응답
이 요약은 최신 자연어 처리·ML 기술이 적용된 대규모 웹 검색엔진이 어떻게 엔드-투-엔드로 2개월 만에 구축될 수 있는지, 시스템·알고리듬·인프라 전반에 걸친 주요 설계/최적화 사안을 구체적으로 안내함.
Hacker News 의견
-
OpenAI의 최신 임베딩 모델에서 배치 추론 시 100만 토큰당 $0.0001이라는 아주 낮은 비용을 제공한다는 점이 놀라움임, 10억 개 페이지를 각 1,000 토큰씩 임베딩해도 총 $100밖에 안 듦을 발견함, 자체적으로 Runpod 스팟 GPU로 추론을 돌리면 이보다 100배는 비싸게 됨, 이외 다른 API 비용은 논외임, OpenAI가 이렇게 도메인 특화 소스 데이터를 확보하려는 일종의 허니팟 전략 혹시 아닌지 궁금함
- OpenAI는 대부분 API를 통해 처리된 데이터로는 재학습을 하지 않음, 특별한 예외가 있지 않는 한 그런 일은 없다고 알고 있음
-
글 마지막에서는 Common Crawl 데이터를 추가할 생각을 언급함, 우리 팀의 웹 그래프 기반 랭킹 정보가 어떤 페이지를 크롤링할지 선정하는 데 큰 도움이 될 것 같음, 대규모 사례를 직접 보여주는 게 흥미로웠음, 벡터 데이터베이스가 의외로 비용 효율적이어서 놀람
-
진심으로 경탄을 표함, 글도 놀라울 만큼 잘 정리됨, 검색엔진의 핵심은 정제되고 필터링된 데이터라는 점에 동의함(쓰레기를 넣으면 쓰레기가 나옴), LLM 훈련에서도 결국 소량의 고품질 데이터가 더 중요하다는 것을 다시금 체감함, 모든 컨텐츠를 LLM이 심사해서 검색엔진을 만들면 어떤 성능일지 궁금증이 들음
- 현재 친구의 소규모 비즈니스 웹사이트 SEO를 직접 관리 중임, 기술적으로 손봐서 지역 맞춤 수작업 컨텐츠도 꽤 썼음, 2개월이 지나도록 Bing은 파비콘도 못 긁어감, Google도 1달이나 걸림, 여전히 완전 관련 없는 전국 규모 리드 수집 사이트, Yelp 블로그 스팸, 지역과 전혀 무관한 타업체 페이지가 상위에 노출됨, 뭔가 pagerank와 크롤링 체계가 제대로 작동하지 않는 게 확실해 보임
-
정말 존경심이 듦, 이렇게 많은 기술들을 모아 하나로 작동시키는 건 대단한 일임, 검색엔진의 결정적 가치는 실제 랭킹 알고리즘에 있다고 생각함, 이 프로젝트에서 LLM이 랭킹에 어떻게 사용되는지는 잘 모르겠음, 옛날 랭킹 기법 중에는 실제 사용자의 검색~클릭 데이터를 수집하는 게 있음, 이게 바로 인간의 검색어→클릭한 링크 Train 데이터임, 몇 번만 클릭해도 랭킹이 확실히 향상됨, 이 데이터를 뉴럴넷에 넣으면 분류 문제로 바꿔 랭킹을 개선할 수 있음, 더 많은 사람이 클릭할수록 가중치가 커짐
-
정말 놀랍다는 말밖에 없음, 실제로 꽤 잘 돌아감, 만약 1만 명이 월 $5씩 구독하면 비용을 충당할 수 있다면, 커뮤니티가 후원하는 검색엔진도 그리 허무맹랑하지 않을 것 같음
-
Encorder-only LLM을 아는 사람에게는 Google이 사실상 이미 끝났다는 게 명확함, Google이 아직 유지되는 건 전 세계 웹을 크롤링해서 인덱스를 항상 최신으로 만드는 데 오래 걸려서임, Common Crawl 같은 오픈 기관이나 유료 서비스가 실시간으로 웹 크롤링 문제를 해결한다면 Google의 25년 방어벽은 무너지게 되고, 검색 자체가 평준화될 것임
-
더 나아가 대기업 IT의 모든 기능별 대체가 실시간으로 진행 중인 모습을 우리는 목격하고 있음, 모델을 통해 이제 기업의 기술 barriers도 크게 낮아짐
-
-
한 사람이 여기까지 만들어냈다는 게 이제껏 상상도 못 했던 일임, 상용 검색엔진과 그렇게 멀리 있지 않은 것 같음, 어쩌면 Google도 따라갈 만한 거리임, 연간 $5만이면 되다니 말도 안 되는 저렴함이라, 당장이라도 시드머니로 보내고 싶을 정도임
-
정말 멋진 프로젝트임, 유명 검색엔진에서 잘 안 나오던 질문(고해상도 울트라와이드 모니터 추천 옵션)에 대해 여기서도 시도해봤지만, 여전히 대형 랭킹만 전문인 메타 페이지가 전문적인 정보를 가진 페이지보다 우선 노출되는 현상이 있음, 랭킹에 대한 집착이 너무 강해 보임, 내가 직접 답을 찾는다면 하드웨어 포럼, 블로그 몇 개 추려서 꼼꼼히 스펙과 장단점 비교해볼 것임, 이런 분석을 실제 사이트가 했는지 확인하기 어렵기 때문에 특수한 경우에는 구체적 데이터 인용 사이트를 더 높게 평가해야 합리적임, 유저 입장에서는 분석에 쓰인 원천 자료를 보고 싶음, 하지만 실제 검색엔진은 이렇게 바닥에서 위로 소스 근거를 올려주지는 않음
- 이건 애초에 검색 문제(search query)가 아닐 수도 있음, 정확하게 “정해진 답”이 존재하는 한 페이지가 아니라, 여러 출처 조합과 ‘추론’을 필요로 하는 질문임
-
정말 멋지다고 생각함, 전부를 이걸로 대체해볼까 했는데, 조금은 시간 낭비가 될 수도 있지만 그래도 꼭 여러 검색을 시도해보고 소감 남기겠음, 대체로 거의 맞는 곳으로 이끌긴 하는데 100%는 아니었음, 예를 들어 lemmy로 fediverse 찾으려 했더니 liberapay 페이지가 결과로 떴음, 꼭 Common Crawl 연동 약속을 지켜주고 archive.org 같은 다른 사이트도 참고해줬으면 함, AI 업계에 수십억이 투입되는데, 실제 이런 실험이 커뮤니티 펀딩이나 작업공유로라도 잘 굴러가 성공했으면 좋겠음, 솔직히 현 검색엔진 거의 독점 상황에 많은 사람들이 지쳐 있음, Ecosia도 자체 검색엔진 준비 중인 걸로 아는데 꼭 이 프로젝트와 협업하거나 도움받았으면 함, 나는 탈중앙화(Decentralized) 검색엔진을 진심으로 원함, 지속가능성 때문에 오픈소스는 아직 망설여지는 점 이해함, 하지만 수많은 돈이 별 의미 없이 낭비된다는 게 답답하고 이 프로젝트는 잠재력이 엄청나기에 제발 오픈소싱해주면 좋겠음, 커뮤니티가 결국 크라우드펀딩 등으로 지속가능 방안 찾아낼 수 있을 것이라 믿음, 아직 포스팅을 다 읽진 않았지만 너무 기대돼서 바로 사용부터 해봄, 글 자체가 아주 심도 깊고 이런 방식이 다른 사람에게도 충분히 참고가 될 거라 생각함, 솔직히 마법 같고 오랜만에 이런 프로젝트에 처음부터 끝까지 설렘을 느낌, 오픈소스가 힘든 것도, 제3국 배경도 알지만 진짜 내 돈 중 $50이라도 기부할 의향이 있음, 온라인 결제 단 한번도 안 해본 내가 이 정도로 기꺼이 후원하고 싶을 정도임, 그래서 꼭 Common Crawl 같이 활용해서 커뮤니티와 함께 했으면 함, 진심으로 이 프로젝트와 커리어 모두 응원함
-
최근 읽은 글 중 가장 통찰력 있었음, 비용을 줄이기 위해 선택한 요소와 실제 절감 포인트를 자세히 설명한 게 특히 좋았음, 뉴럴 서치에 초점을 맞췄지만 BM-25 + 임베딩을 결합한 하이브리드 검색도 시도해봤는지 궁금함, 그리고 어떤 리랭킹 모델들이 가장 유용하고 효율적이었는지도 묻고 싶음
-
정말 재미있는 경험담이었음, 나도 비즈니스 검색용으로 비슷한 걸 개발하고 있는데 비슷한 도전과제 많이 맞닥뜨림, 많은 사람이 크롤링/처리/인덱싱이 쉬울 거라 생각하지만, 대규모로 비용 효율적으로 하는 건 완전히 다른 문제임, wilsonzlin에게 박수 보냄, 관련 이야기 나눠보고 싶음, 이런 걸 e2e로 직접 만드는 사람은 정말 소수임