학술 검색 엔진 내부: Indexing, Ranking, and Retrieval

발행: (2026년 1월 11일 오후 04:35 GMT+9)
4 min read
원문: Dev.to

Source: Dev.to

실제로 무엇을 만들고 있나요?

실용적인 학술 검색 엔진을 구축하기 위해 단순한 데이터베이스 쿼리를 넘어 역색인(Inverted Index) 을 구현했습니다. 이는 대부분의 현대 검색 엔진이 사용하는 핵심 자료구조입니다.

스택

  • 핵심: Python (논리 및 자료구조)
  • 웹 프레임워크: Flask (API 및 UI)
  • 프론트엔드: HTML, CSS & 순수 JavaScript (경량, 단일 파일)

비밀 소스

맞춤형 역색인과 BM25 순위 알고리즘 을 결합한 형태입니다.

“아하!” 순간: 단순 빈도만으로는 안 되는 이유

용어 빈도만으로 순위를 매기면 단어가 많기만 한 문서가 유리해집니다.
BM25는 다음을 통해 이를 보완합니다:

  1. 흔한 단어에 패널티 부여 (역문서 빈도, IDF).
  2. 문서 길이에 따라 정규화 (길이 정규화).

BM25 점수 함수 (Python)

import math

def score_bm25(n, f, qf, r, N, dl, avdl, k1=1.5, b=0.75, k2=100):
    """
    n   – number of documents containing the term
    f   – term frequency in the document
    qf  – term frequency in the query
    r   – number of relevant documents containing the term
    N   – total number of documents
    dl  – document length
    avdl– average document length
    """
    # Scaling factor based on document length
    K = k1 * ((1 - b) + b * (dl / avdl))

    # Relevance component
    first = math.log(((r + 0.5) / (N - r + 0.5)) /
                     ((n - r + 0.5) / (N - n - (N - r) + 0.5)))
    second = ((k1 + 1) * f) / (K + f)
    third = ((k2 + 1) * qf) / (k2 + qf)

    return first * second * third

인덱싱: 무거운 작업

역색인은 교과서의 색인과 같은 방식으로 동작합니다: 각 용어가 나타나는 문서 ID 목록에 매핑됩니다.

간소화된 인덱싱 과정 (Python)

from collections import defaultdict

inverted_index = defaultdict(list)

for doc_id, text in corpus.items():
    tokens = preprocess(text)          # strip punctuation, lowercase, etc.
    for term in tokens:
        inverted_index[term].append(doc_id)

트레이드‑오프:

  • 장점: 메모리 내 인덱스 → 서브밀리초 수준 조회.
  • 단점: 높은 RAM 사용량; 작은 규모에서는 허용 가능
fetch('response.json')
    .then(res => res.json())
    .then(data => {
        const resultsDiv = document.getElementById('results');
        resultsDiv.innerHTML = ''; // Clear old results

        data.forEach(paper => {
            const item = `
                <h3>${paper.title}</h3>
                <p>${paper.abstract}</p>
            `;
            resultsDiv.innerHTML += item;
        });
    })
    .catch(err => console.error('Search error:', err));

직접 해보기

전체 소스 코드는 오픈소스입니다. 저장소를 클론하고 README에 따라 설정한 뒤 로컬에서 애플리케이션을 실행하면 인덱싱 및 순위 파이프라인을 직접 탐색할 수 있습니다.

Back to Blog

관련 글

더 보기 »