RAG와 임베딩 · 글 11편RAG와 임베딩
  1. RAG란 무엇인가 - 넣기, 쪼개기, 찾기, 답하기
  2. 문서를 붙여 넣을까, RAG를 만들까
  3. 임베딩이란 무엇인가
  4. 로컬 임베딩 모델 고르기
  5. 문서를 청크로 나누기
  6. 키워드 검색, 의미 검색, 하이브리드 검색
  7. 로컬 의미 검색 만들기 - 젬마 임베딩 실습 따라 읽기
  8. RAG 답변 평가와 자주 생기는 실패
  9. RAG, 긴 컨텍스트, 파인튜닝, LLM Wiki 비교
  10. RAG가 잘 되도록 사무 문서 준비하기
  11. 내부 문서를 색인할 때의 개인정보와 보안

이 글에서 다루는 것키워드 검색은 같은 말을, 의미 검색은 같은 뜻을 찾습니다. 두 방식의 차이, 임베딩 없이 검색 품질을 높이는 방법, 둘을 합치는 하이브리드 검색과 재순위를 정리합니다.

검색은 모델에게 줄 근거를 고르는 일

문서가 많아지면 전부를 모델에 넣을 수 없습니다. 그래서 질문과 관련된 조각을 먼저 골라야 합니다. 이 고르는 일이 검색입니다.

검색은 크게 둘로 나뉩니다. 키워드 검색은 같은 말을 잘 찾고, 의미 검색(시맨틱 검색)은 같은 뜻을 잘 찾습니다.

구분 키워드 검색(BM25) 의미 검색(벡터)
기준 단어 뜻
고유명사, 기관명 강함 경우에 따라 약함
조문 번호, 문서 번호 강함 약할 수 있음
표현이 다른 비슷한 문장 약함 강함
임베딩 모델 필요 없음 필요
구현 비교적 단순 더 복잡
결과 설명 어떤 단어로 찾았는지 보임 점수만 보임

둘 중 하나를 골라야 하는 것은 아닙니다. 함께 쓸 수 있습니다.

키워드 검색의 네 단계

키워드 검색도 수준이 여럿입니다.

방식 쉽게 말하면 잘하는 것
문자열 포함 검사 그 글자가 들어 있는지 확인 정확한 단어 찾기
Fuse.js 글자가 얼마나 비슷한지 비교 오타, 부분 일치
FTS(전문 검색) 단어가 어느 문서에 있는지 미리 색인 빠른 본문 검색
BM25 검색어가 중요한 문서에 점수를 줌 결과 순위

BM25는 단어가 있는지만 보지 않습니다. 세 가지를 함께 따집니다.

  • 검색어가 그 조각에 얼마나 자주 나오는가
  • 그 단어가 전체 문서에서 얼마나 드문가
  • 조각이 지나치게 길지는 않은가

모든 조각에 나오는 “기관”보다 몇 조각에만 나오는 “관내출장”에 높은 점수를 줍니다.

SQLite로 만들기

SQLite에는 FTS5라는 전문 검색 기능이 들어 있습니다. 파일 하나로 동작하고 서버가 필요 없습니다.

CREATE VIRTUAL TABLE documents USING fts5(title, content);

SELECT title, bm25(documents) AS score
FROM documents
WHERE documents MATCH '행정 자동화'
ORDER BY score;

별도의 벡터 데이터베이스 없이 로컬 문서 검색을 만들 수 있습니다. 문서명, 사업명, 법령명처럼 정확한 단어가 중요한 업무에서 실용적입니다.

파이썬으로 만들기

rank_bm25 라이브러리를 쓰면 몇 줄로 끝납니다.

from rank_bm25 import BM25Okapi
import re

def tok(s):  # 간단한 한국어 토큰화
    return re.findall(r"[가-힣]+|[a-zA-Z0-9]+", s)

corpus = [tok(c["text"]) for c in chunks]
bm = BM25Okapi(corpus)

def search(q, k=5):
    scores = bm.get_scores(tok(q))
    top = scores.argsort()[-k:][::-1]
    return [chunks[i] for i in top]

한국어에서 생기는 문제

키워드 검색은 글을 단어로 나누는 방식(토큰화)에 민감합니다. 한국어는 조사가 붙고 띄어쓰기가 일정하지 않습니다.

검색어 문서의 표현 결과
인공지능 인공 지능 토큰화 방식에 따라 못 찾음
행정 자동화 행정업무 자동화 띄어쓰기 기준으로 나누면 “행정”이 안 맞음
출장비 출장비는, 출장비를 조사를 떼지 않으면 못 찾음
자동차 차량 기본 상태에서는 못 찾음

대응 방법입니다.

  • 형태소 분석기(kiwi, okt 등)로 조사를 떼고 단어를 나눕니다.
  • 글자를 2~3자씩 겹쳐 자르는 N-gram 방식으로 색인합니다. 띄어쓰기와 복합어에 덜 민감해집니다.
  • 기관에서 쓰는 약어, 별칭, 업무 용어를 사전으로 만들어 둡니다.

검색이 조사나 복합어 때문에 실패하면 어떤 전처리를 넣었는지 기록합니다. 나중에 같은 문제를 다시 만났을 때 원인을 빨리 찾습니다.

임베딩 없이 뜻을 따라가는 방법

“연차”로 물었는데 문서에는 “휴가”라고 적혀 있는 문제는 임베딩 없이도 상당 부분 풀 수 있습니다. 질문을 그대로 한 번 검색하지 않고, 검색어를 넓힌 뒤 검색합니다. 이를 질의 확장이라고 합니다.

  1. 질문에서 핵심어를 뽑습니다.
  2. 동의어와 관련어로 넓힙니다.
  3. FTS와 BM25로 여러 후보를 찾습니다.
  4. 상위 조각만 모델에 넣습니다.

2번을 언어 모델에게 맡길 수 있습니다.

질문: 예산 낭비 사업을 찾아줘

검색용 구조:
{
  "keywords": ["예산 낭비", "예산 과다", "불용액",
               "집행률 저조", "성과 미달", "중복 사업"],
  "date_from": "2024-01-01"
}

여기서 모델은 답을 만들지 않고 검색어를 만듭니다. 실제로 문서를 고르는 일은 SQL과 BM25가 합니다. 어떤 단어로 검색했는지 눈으로 확인할 수 있어서, 결과가 이상할 때 원인을 찾기 쉽습니다.

방법 개념 특징
질의 확장 질문을 관련 키워드로 넓힘 벡터 데이터베이스 없이 가능
동의어 사전 자동차=차량처럼 연결 사람이 통제하기 쉬움
임베딩 문장을 숫자 벡터로 변환 의미 유사도에 강함

하이브리드 검색

키워드 검색과 의미 검색을 함께 돌리고 결과를 합치는 방식입니다. 질문의 종류에 따라 어느 쪽이 맞는지가 다르기 때문입니다.

질문 잘 맞는 검색
“AI-2026-00451 문서를 찾아줘” 키워드
“성과가 좋지 않았던 사업을 찾아줘” 의미
“최근 3년 복지 분야 AI 사업만” 날짜는 SQL 조건, 나머지는 키워드와 의미

결과를 합치는 방법

두 검색의 점수는 범위가 다릅니다. BM25 점수와 코사인 유사도를 그대로 더하면 한쪽이 전체를 덮습니다. 세 가지 방법이 있습니다.

  1. 합치고 중복 제거. 키워드 상위 5개와 의미 상위 5개를 합친 뒤 같은 조각을 하나로 줄입니다. 처음에는 이것으로 충분합니다.
  2. 순위로 합치기. 점수 대신 순위를 씁니다. RRF(Reciprocal Rank Fusion)가 대표적입니다. 두 검색에서 모두 상위에 오른 조각이 위로 올라갑니다.
  3. 점수를 맞춘 뒤 가중치 주기. 두 점수를 같은 범위로 정규화하고 비율을 정해 더합니다. 조문 번호를 묻는 질문에는 키워드 쪽에, 뜻을 묻는 질문에는 의미 쪽에 가중치를 더 줍니다.

어느 방법이든 결과마다 두 검색의 점수와 최종 점수를 함께 남깁니다. 왜 그 조각이 올라왔는지 설명할 수 있어야 고칠 수 있습니다. 한쪽 점수가 전체를 압도하면 정규화와 후보 수를 먼저 확인합니다.

재순위(리랭킹)

재순위는 검색이 가져온 후보를 다시 정렬하는 단계입니다. 1차 검색으로 후보를 넉넉히(예: 20개) 뽑고, 질문과 각 후보를 더 꼼꼼히 비교해 상위 몇 개만 남깁니다.

질문 → 키워드 검색 + 의미 검색 → 후보 합치기 → 재순위 → 상위 3~5개 → 모델

재순위 전용 모델(리랭커)을 쓰는 방법이 있고, 대화 모델에게 “이 조각이 질문에 답하는 데 쓸모 있는가”를 판단하게 하는 방법도 있습니다. 둘 다 시간이 더 걸립니다. 강의의 도구 선택표에서도 재순위는 마지막 단계에 놓입니다. 검색 결과에 정답 조각이 들어 있는데 순위가 낮아서 잘리는 문제가 확인될 때 넣습니다.

권장 순서

문자열 검색 → FTS → BM25 → 질의 확장 → 의미 검색 → 하이브리드 → 재순위 순서로 올라갑니다. 각 단계에서 실제로 놓치는 질문이 생길 때 다음 기술을 더합니다.

내가 원하는 것 먼저 써 볼 것
정확한 단어, 사업명, 기관명 찾기 FTS, BM25
오타나 비슷한 문자열 찾기 Fuse.js, N-gram
뜻은 같은데 표현이 다른 문서 찾기 질의 확장, 임베딩
정확한 단어와 뜻 둘 다 중요 하이브리드
벡터 데이터베이스 없이 시작 SQLite FTS5와 BM25, 질의 확장

연습으로는 문서 20~100건을 SQLite에 넣고 FTS5와 BM25 검색을 먼저 만듭니다. 그다음 동의어를 넓혀 결과가 얼마나 달라지는지 봅니다. 마지막으로 임베딩 검색을 더해 같은 질문으로 세 결과를 나란히 비교합니다.

다음에 읽을 글