6P by neo 4달전 | favorite | 댓글 1개

파이썬으로 만든 80줄짜리 검색 엔진

  • 지난 9월에 Wallapop의 검색 데이터 과학자로 합류하여 Solr이라는 오픈 소스 검색 엔진을 다루는 일을 함.
  • 검색 엔진의 기본 원리를 이해하고자 파이썬을 사용하여 처음부터 검색 엔진을 만들기로 결정함.
  • 목표는 "소규모 웹사이트 발견성 위기"를 해결하는 것으로, 구글과 같은 검색 엔진을 사용하여 찾을 수 없는 작은 웹사이트들을 다시 위대하게 만드는 것임.
  • 이 글에서는 파이썬을 사용하여 검색 엔진을 만드는 과정을 안내하며, 작성한 모든 코드는 GitHub의 microsearch 리포지토리에서 확인할 수 있음.
  • 구현된 검색 엔진은 생산 준비가 완료된 검색 엔진이 아니라, 검색 엔진이 내부적으로 어떻게 작동하는지 보여주는 사용 가능한 장난감 예제임.

microsearch

  • microsearch를 구성하는 요소들을 살펴보고 각 요소를 어떻게 만들었는지 탐구함: (1) 크롤러, (2) 역 인덱스, (3) 순위 매기기, (4) 인터페이스.

크롤러

  • 검색 엔진을 만들기 위한 첫 번째 단계는 검색할 데이터를 확보하는 것임.
  • "로컬 구글"을 만들고자 하는 의도로 팔로우하는 블로그의 데이터를 사용하여 검색 엔진을 구축함.
  • 크롤링은 특정 블로그 목록의 모든 포스트를 다운로드하고 정리하는 과정을 포함함.
  • 더 빠르게 하기 위해 asyncio 파이썬 라이브러리를 사용하여 크롤링 시간을 20분에서 20초로 단축함.
  • 642개의 RSS 피드를 사용하였으며, 이 중 약 100개는 자주 읽는 블로그이고 나머지 500개는 surprisetalk 블로그 프로젝트에서 가져옴.

역 인덱스

  • 역 인덱스는 키워드를 문서에 매핑하는 데이터 구조로, 특정 단어가 나타나는 문서를 쉽게 찾을 수 있게 함.
  • 사용자가 쿼리를 검색할 때 역 인덱스를 사용하여 쿼리의 키워드와 일치하는 모든 문서를 검색함.
  • 역 인덱스의 논리는 SearchEngine이라는 클래스 내에 정의되어 있으며, 두 개의 사전을 초기화하여 구현함.

순위 매기기

  • 주어진 쿼리에 대해 일치하는 문서 세트가 있으면 이를 정렬하는 방법이 필요함.
  • 가장 유명한 순위 매기기 방법은 구글의 PageRank이지만, BM25와 같이 내용을 기반으로 문서를 순위 매기는 다른 옵션도 존재함.
  • BM25 점수 계산 방법을 포함하여 SearchEngine 클래스의 누락된 부분을 구현함.

인터페이스

  • 검색 엔진을 구축한 후에는 이를 어떤 방식으로든 공개하고 싶음.
  • FastAPI 앱을 구축하여 검색 엔진을 노출하는 엔드포인트를 제공하고, 검색을 수행할 수 있는 간단한 웹페이지를 렌더링함.
  • 출력을 쉽게 읽을 수 있도록 상위 N개의 URL만 선택하기로 결정함.

누락된 기능

  • 검색 엔진을 자주 다루는 독자라면 구현에서 많은 기능이 누락되었다는 것을 알 수 있음.
  • 쿼리 연산자, n-gram 인덱싱, 쿼리 또는 문서 확장, 크롤링과 인덱싱을 동시에 수행하는 기능 등이 누락되어 있음.

결론

  • 이 프로젝트를 진행하며 Solr의 내부 작동 방식에 대해 더 잘 이해하게 되었고, 비동기 코드 작성의 놀라움을 배움.
  • 개인 검색 엔진을 만들기 위한 다음 단계로 검색 엔진에 의미 검색 기능을 구현할 계획임.

GN⁺의 의견

  • 이 글에서 가장 중요한 것은 소규모 웹사이트의 발견성을 개선하기 위해 개인이 직접 검색 엔진을 만들 수 있다는 점임.
  • 파이썬과 오픈 소스 라이브러리를 활용하여 복잡한 기능을 가진 검색 엔진을 단순화하여 구현한 경험은 초급 소프트웨어 엔지니어에게도 영감을 줄 수 있음.
  • 비동기 프로그래밍의 효율성과 데이터 구조의 중요성을 실제 예제를 통해 보여줌으로써, 이 글은 기술적 통찰력과 실용적인 학습 기회를 제공함.
Hacker News 의견
  • Pandas를 이용한 BM25 검색 엔진 개발

    • 개발자가 Pandas에서 작동하는 빠른 BM25 검색 엔진을 개발 중임.
    • Pandas를 사용하는 이유는 BM25 알고리즘 외에도 최신성, 인기도 등 다른 요소들을 쉽게 결합할 수 있기 때문.
    • 문구 매칭에는 많은 예외 사례가 있으며, 가능한 한 적은 메모리를 사용하여 위치 정보를 압축하는 것이 중요함.
  • 코드 리뷰: SearchEngine 클래스

    • k1b라는 파라미터의 의미를 모르겠으며, 코드에 주석이 전혀 없음.
    • _documents는 URL을 키로, 해당 URL의 내용을 값으로 가질 것으로 추정.
    • 코드에 문서화가 잘 되어 있지 않아 아쉬움. 문서화가 잘 되어 있었다면 검색 엔진 구축 학습 자료로 유용할 수 있었을 것.
  • 검색 엔진의 복잡성

    • 검색 엔진의 주된 어려움은 데이터의 양을 다루는 것임.
    • 로직 자체는 의외로 간단하며, 프로젝트는 불필요한 부분을 대부분 제거하여 성공적임.
    • 검색 엔진을 크게 만드는 것이 아니라 데이터를 더 작게 만들거나 신호 대 잡음 비율을 높이는 접근이 중요함.
  • 코드 행 수에 대한 의견

    • 외부 의존성을 사용하는 상황에서 코드 행 수를 자랑하는 것의 의미에 의문을 제기함.
    • 코드베이스에 대한 SI 단위는 없지만, 인지 부하를 어떻게든 측정해야 한다는 의견.
  • 코드 내의 표현에 대한 농담

    • 코드 내의 chunk for chunk in chunks if chunk 표현을 보고 나무꾼에 관한 농담이 떠오름.
  • 추천 엔진 코드 예시

    • 검색 엔진과 함께 사용할 수 있는 파이썬으로 작성된 20줄 미만의 추천 엔진 코드 제공.
    • 세션 로그에서 클릭된 URL을 기반으로 추천을 생성함.
    • 로그에 입력된 쿼리와 클릭된 URL을 혼합하여 사용하면 맞춤법 검사 제안도 얻을 수 있음.
  • 파싱 라이브러리 성능 비교

    • lxml.htmllxml.html.cleanBeautifulSoup보다 훨씬 빠를 수 있음을 언급함.
  • 키워드 사용에 대한 조언

    • 영어 검색 결과의 품질을 높이기 위해 1-gram 대신 2-gram과 3-gram을 사용할 것을 권장함.
    • n-gram은 문맥을 유지하는 데 도움이 됨.
  • 교육적인 프로젝트에 대한 의견

    • 프로젝트가 매우 멋지고 교육적이지만, 실제 배포는 하지 말 것을 권함.
    • 몇 만 개의 문서를 다루는 더 큰 규모의 프로젝트에는 SQLite의 FTS5를 사용하는 것이 해답임.
  • 파이썬을 이용한 대규모 데이터 처리에 대한 의문

    • 대규모 데이터를 빠르게 처리해야 하는 작업에 파이썬(느린 언어)을 사용하는 것이 정말 좋은 생각인지에 대한 의문 제기.