[LLM Wiki 20] LLM은 어디에 쓰이는가: Query Expansion부터 Rerank와 답변 생성까지
검색형 LLM 시스템에서 LLM이 어디에 들어가고, 각 단계가 어떤 context를 보고 어떤 출력을 만드는지 QMD와 LLM Wiki 관점에서 깊게 정리한다.

“LLM은 어디에 쓰이는가?”라고 물으면 보통 최종 답변을 쓰는 ChatGPT 같은 모델을 떠올린다. 하지만 RAG, QMD, LLM Wiki 같은 검색형 시스템에서는 LLM이 마지막 답변 생성기에만 들어가지 않는다.
오히려 좋은 검색형 시스템은 여러 종류의 모델을 작은 역할로 나눈다. 어떤 모델은 질문을 검색 가능한 표현으로 바꾸고, 어떤 모델은 텍스트를 vector로 바꾸고, 어떤 모델은 후보 문서를 다시 줄 세우고, 마지막 모델은 근거를 읽고 답변한다.
중요한 질문은 “LLM이 쓰였나?”가 아니다.
각 단계의 모델은 무엇을 입력으로 받고, 무엇을 출력하며, 그 출력이 다음 단계에서 어떻게 쓰이는가?
이 관점으로 보면 local LLM, embedding model, reranker, query expansion model, main answer LLM의 위치가 분명해진다. QMD가 왜 단순한 “검색 CLI”가 아니라 LLM Wiki의 retrieval layer에 가까운지도 여기서 보인다.
한 덩어리 LLM이 아니라 역할 분해다
검색형 시스템을 아주 단순하게 그리면 다음 흐름이다.
- 사용자가 질문한다.
- 질문을 검색용 표현으로 바꾼다.
- 질문과 문서를 vector로 바꾼다.
- BM25와 vector search로 후보를 찾는다.
- 여러 결과 목록을 RRF 같은 방식으로 합친다.
- 후보 chunk를 다시 골라 rerank한다.
- agent가 필요하면 추가 검색이나 원문 조회를 한다.
- main LLM이 근거를 읽고 답변한다.
여기서 “LLM”이라는 말은 너무 넓다. 실제로는 다음 네 종류가 섞인다.
- 생성 모델: query expansion, HyDE, 최종 답변처럼 텍스트를 새로 만든다.
- 표현 모델: embedding처럼 텍스트를 vector로 바꾼다.
- 판별 모델: reranker처럼 query와 candidate의 관련성을 평가한다.
- 제어 모델: agent처럼 어떤 도구를 언제 호출할지 결정한다.
이 네 역할을 구분하지 않으면 설계가 흐려진다. “local LLM을 쓴다”는 말도 정확하지 않다. local LLM을 최종 답변에 쓸 수도 있고, query expansion에만 쓸 수도 있고, rerank에만 쓸 수도 있다. 비용, 지연 시간, 품질, privacy 효과는 경우마다 완전히 다르다.
Context 경계가 핵심이다

검색형 시스템에서 가장 중요한 차이는 각 모델이 보는 context다.
사람에게는 하나의 동작처럼 보인다. 사용자가 질문하고, 시스템이 문서를 찾고, 답변한다. 하지만 내부에서는 여러 모델이 서로 다른 정보만 보고 판단한다.
Query Expansion 모델은 대개 사용자 질문과 출력 형식만 본다. 아직 실제 문서는 없다. Embedding 모델은 문서 chunk 하나나 query 하나만 본다. Reranker는 query와 후보 chunk 한 쌍을 본다. Agent는 사용자 요청, 도구 목록, 이전 검색 결과를 본다. Main LLM은 최종 후보 근거와 대화 맥락을 함께 본다.
이 경계를 정확히 잡아야 한다. Query Expansion 단계에서 실제 문서를 본다고 착각하면 hallucination을 정답처럼 믿게 된다. Reranker가 전체 corpus를 다시 읽는다고 착각하면 비용 계산이 틀어진다. Main LLM이 모든 문서를 다 본다고 착각하면 retrieval 품질 문제를 prompt 문제로 잘못 진단한다.
1. Query Expansion: 답을 만드는 게 아니라 검색어를 만든다
Query Expansion은 짧고 모호한 사용자 질문을 검색기가 잘 찾을 수 있는 여러 표현으로 바꾸는 단계다.
이 단계의 context는 작다.
- 사용자 원 질문
- 검색 대상 도메인에 대한 짧은 힌트
- 출력 형식 규칙
- 필요한 경우 언어, 파일명, 제품명 같은 제약
예를 들어 사용자가 이렇게 묻는다.
가격 때문에 막힌 고객 미팅 찾아줘
이 질문은 사람이 보면 이해할 수 있지만 검색기에게는 애매하다. 회의록에는 “가격”이라는 단어 대신 “예산”, “견적”, “approval”, “procurement”, “renewal cost” 같은 표현이 나올 수 있다.
Query Expansion 모델은 답변을 만들지 않는다. 검색에 던질 표현을 만든다.
lex: 가격 예산 견적 고객 미팅
lex: pricing budget procurement customer meeting
vec: customer meetings delayed because of budget approval or pricing concerns
hyde: The customer liked the product but postponed the decision because the annual subscription cost exceeded the approved budget.
여기서 lex는 BM25, FTS5 같은 lexical search에 적합하다. vec는 semantic search에 적합하다. hyde는 질문 자체보다 문서처럼 생긴 passage를 embedding하기 위한 재료다.
QMD에서 흥미로운 부분은 query expansion을 “비슷한 말 만들기”로 끝내지 않는다는 점이다. 검색 경로별로 typed query를 만든다. 즉 expansion의 출력이 바로 검색 전략이 된다.
2. Embedding: 의미를 숫자 공간에 올린다
Embedding 모델은 텍스트를 vector로 바꾼다. 출력은 자연어 문장이 아니라 숫자 배열이다.
이 모델의 context는 보통 단일 텍스트다.
- 문서 chunk 하나
- 사용자 query 하나
- query expansion이 만든 vec query 하나
- HyDE가 만든 가상 passage 하나
Embedding 모델은 “답하라”는 명령을 수행하지 않는다. 대신 텍스트의 의미가 비슷하면 vector 공간에서 가깝게 놓이도록 변환한다.
예를 들어 다음 두 문장은 단어가 다르지만 retrieval 관점에서는 가까워야 한다.
가격 때문에 도입이 지연됐다.
The rollout was delayed because procurement did not approve the subscription cost.
BM25는 두 문장을 잘 연결하지 못할 수 있다. 공유하는 단어가 거의 없기 때문이다. Embedding은 의미 유사성을 통해 이 간격을 줄인다.
하지만 embedding도 만능은 아니다. 정확한 함수명, 에러 메시지, 설정 키, 파일명처럼 글자 자체가 중요한 검색에서는 BM25가 더 강할 수 있다. 그래서 QMD 같은 시스템은 embedding만 쓰지 않고 BM25와 vector search를 같이 쓴다.
3. HyDE: 가상의 답을 믿는 게 아니라 검색 미끼로 쓴다
HyDE는 Hypothetical Document Embeddings의 줄임말이다. 질문을 바로 embedding하지 않고, 먼저 “이 질문에 답이 들어 있을 법한 가상 문서”를 만든 뒤 그 문서를 embedding한다.
흐름은 이렇다.
질문 → 가상 답변 passage 생성 → passage embedding → 실제 문서 vector와 비교
예를 들어 질문이 너무 짧다.
인증 설정 어디서 해?
이 질문 자체를 embedding하면 너무 추상적일 수 있다. HyDE generator는 다음처럼 실제 문서에 나올 법한 passage를 만든다.
Authentication settings are configured with AUTH_SECRET, provider credentials, session options, and callback URLs in the environment configuration.
이 passage를 embedding하면 AUTH_SECRET, provider credentials, callback URLs 같은 실제 문서 표현과 가까워질 가능성이 높아진다.
여기서 조심할 점이 있다. HyDE passage는 근거가 아니다. 실제 문서를 찾기 위한 중간 산출물이다. HyDE가 만든 문장을 답변에 섞으면 안 된다. 최종 답변은 반드시 검색된 실제 문서를 근거로 만들어야 한다.
이 구분이 HyDE의 핵심이다. HyDE는 hallucination을 답으로 쓰는 기술이 아니라, hallucination처럼 생긴 가상 문서를 검색 query로만 쓰는 기술이다.
4. BM25와 Vector Search: LLM이 아닌 검색기도 여전히 중요하다
LLM 글에서 자주 놓치는 부분이 있다. retrieval pipeline의 모든 단계가 LLM은 아니다.
BM25, FTS5, sqlite-vec, HNSW, RRF 같은 부분은 전통적인 검색, 데이터베이스, 랭킹 알고리즘이다. 이 계층이 튼튼해야 LLM도 좋은 근거를 받는다.
BM25는 정확한 단어에 강하다.
- 함수명
- 에러 메시지
- 설정 키
- 파일 경로
- 사람 이름
- 제품명
Vector search는 의미 유사성에 강하다.
- 표현이 다른 같은 의미
- 한국어, 영어가 섞인 질문
- 회의록처럼 문장이 길고 표현이 다양할 때
- 사용자가 정확한 키워드를 모를 때
좋은 retrieval system은 둘 중 하나를 고르는 것이 아니라 둘을 섞는다. QMD도 이 방향에 가깝다. lex query는 FTS5/BM25 쪽으로 보내고, vec, hyde query는 vector search 쪽으로 보낸 뒤 결과를 합친다.
5. RRF: 점수가 아니라 순위를 합친다
BM25 결과와 vector search 결과는 점수 스케일이 다르다. BM25 점수와 cosine similarity를 그냥 더하면 의미가 깨진다.
RRF, Reciprocal Rank Fusion은 이 문제를 단순하게 푼다. 점수 자체가 아니라 각 결과 목록에서의 순위를 본다.
score(doc) = 1 / (k + rank)
어떤 문서가 BM25에서도 상위권이고 vector search에서도 상위권이면 RRF 점수가 높아진다. 한 검색기에서만 높게 나온 문서보다 여러 검색기에서 꾸준히 상위권인 문서를 더 믿는 방식이다.
여기에는 LLM이 꼭 필요하지 않다. 오히려 이 단계는 deterministic한 랭킹 알고리즘으로 두는 편이 운영하기 좋다. 모델을 쓰는 단계와 알고리즘으로 합치는 단계를 나눠야 디버깅이 가능하다.
QMD가 RRF를 쓰는 이유도 여기에 있다. query expansion이 만든 여러 query와 BM25, vector 결과를 한 번에 섞으려면 점수 통일보다는 순위 기반 fusion이 현실적이다.
6. Reranker: 후보를 다시 읽는 판별 모델
Reranker는 1차 검색 후보를 다시 읽고 query와 얼마나 맞는지 평가한다.
이 단계의 context는 좁지만 강하다.
- 사용자 query
- 후보 chunk 하나
- 관련성 판단 규칙
Reranker는 전체 문서 저장소를 다 읽지 않는다. BM25와 vector search가 이미 줄인 후보만 본다. 예를 들어 후보 50개가 있으면 query와 각 candidate chunk를 비교해 다시 순서를 매긴다.
Query:
가격 때문에 막힌 고객 미팅 찾아줘
Candidate:
고객은 기능에는 만족했지만 예산 승인 문제로 구매 결정을 다음 분기로 미뤘다.
이 후보는 “가격”이라는 단어가 없어도 질문과 관련이 높다. BM25만으로는 놓칠 수 있지만 reranker는 query와 chunk를 함께 읽기 때문에 관련성을 더 잘 판단할 수 있다.
Reranker의 출력은 보통 답변이 아니다. 점수나 순위다. 그래서 reranker는 생성 모델이라기보다 판별 모델에 가깝다.
QMD에서 local reranker GGUF 모델이 들어가는 위치가 여기다. local LLM을 “대화 모델”로 쓰는 것이 아니라 후보 평가자로 쓰는 것이다.
7. Chunk Selection: 문서 전체가 아니라 답변에 넣을 조각을 고른다
검색 결과가 문서 단위로만 오면 main LLM에게 너무 많은 내용을 넘기게 된다. 긴 회의록 하나가 상위 결과로 잡혔다고 해서 전체 회의록을 다 context에 넣는 것은 낭비다.
그래서 retrieval system은 보통 문서를 chunk로 나눈다. 그리고 상위 문서 안에서도 질문과 관련된 chunk를 고른다.
이 단계는 시스템마다 구현이 다르다. 단순히 search hit 주변 문단을 가져올 수도 있고, chunk embedding을 따로 만들 수도 있고, reranker로 chunk 후보를 다시 고를 수도 있다.
중요한 점은 main LLM이 보는 context는 “검색된 문서 전체”가 아니라 “선택된 근거 조각”이라는 것이다. 답변 품질이 나쁘다면 main LLM보다 chunk selection이 문제일 수 있다.
LLM Wiki에서는 이 문제가 더 커진다. 회의록, 결정 기록, 프로젝트 문서, 스키마 문서가 섞여 있기 때문이다. 질문이 “지난번 가격 이슈 어떻게 정리됐지?”라면 회의록 전문보다 결정 카드, 액션 카드, 관련 고객 카드가 더 중요할 수 있다.
8. Agent LLM: 검색 도구의 사용자
QMD가 MCP server를 제공하는 이유는 agent가 QMD를 도구처럼 호출할 수 있게 하기 위해서다.
Agent LLM의 context는 검색 모델보다 넓다.
- 사용자 요청
- 현재 대화
- 사용 가능한 도구 목록
- QMD collection 정보
- 이전 검색 결과
- 다음에 어떤 도구를 호출할지에 대한 규칙
Agent는 직접 모든 문서를 읽지 않는다. 대신 이렇게 움직인다.
- 사용자의 질문을 해석한다.
- QMD query 또는 structured search를 호출한다.
- 결과가 부족하면 검색어를 바꾼다.
- 필요한 문서를 get이나 multi_get으로 가져온다.
- 근거를 정리해 main answer 단계로 넘긴다.
여기서 agent는 검색 엔진 자체가 아니다. 검색 엔진의 사용자다. 이 차이가 중요하다.
QMD의 MCP 계층은 local Markdown 지식을 agent workflow에 연결하는 접점이다. 사람이 CLI로 검색할 수도 있지만, agent가 도구로 호출하면 질문, 검색, 원문 조회, 답변 생성이 하나의 작업 흐름으로 묶인다.
9. Main Answer LLM: 마지막에 근거를 읽고 말한다
Main Answer LLM은 사용자가 실제로 읽는 답변을 만든다.
이 단계의 context는 가장 크다.
- 사용자 질문
- 검색된 상위 근거
- 원문 chunk
- 대화 맥락
- 답변 형식
- citation 또는 근거 표시 규칙
- 금지사항과 style guide
예를 들어 사용자가 묻는다.
가격 때문에 막힌 고객 미팅을 요약해줘.
앞 단계는 관련 회의록, 고객 카드, 결정 기록을 찾는다. Main LLM은 그 근거를 읽고 답한다.
가격 이슈로 지연된 미팅은 A사와 B사 건입니다.
A사는 예산 승인 지연이 핵심이고, B사는 연간 라이선스 비용 부담 때문에 도입 시점을 다음 분기로 미뤘습니다.
이 답변이 좋아지려면 main LLM 자체도 좋아야 하지만, 더 중요한 것은 근거가 좋아야 한다는 점이다. 틀린 chunk를 넣으면 좋은 모델도 그럴듯한 틀린 답을 만든다. 반대로 잘 고른 근거를 넣으면 작은 모델도 꽤 안정적으로 답할 수 있다.
QMD에서 local LLM이 들어가는 위치

QMD는 local Markdown 검색 엔진이다. QMD 자체가 전체 LLM Wiki를 대신하지는 않는다. 하지만 LLM Wiki에서 가장 중요한 retrieval layer를 맡을 수 있다.
QMD 안에서 local LLM 또는 GGUF 모델이 들어가는 대표 지점은 세 곳이다.
첫째, query expansion이다. 짧은 질문을 lex, vec, hyde query로 바꾼다.
둘째, embedding이다. 문서 chunk와 query를 vector로 바꾼다.
셋째, rerank다. 후보 chunk와 query를 함께 보고 관련성 점수를 낸다.
QMD 바깥에는 main LLM과 agent LLM이 있을 수 있다. 이 모델들은 QMD MCP tool을 호출하고, 검색 결과를 읽어 최종 답변을 만든다.
즉 QMD 구조를 정확히 말하면 이렇다.
QMD는 최종 답변 LLM이 아니라, local LLM을 검색 보조 계층으로 활용하는 retrieval engine이다.
GGUF는 역할이 아니라 포장 방식이다
GGUF는 local LLM을 실행하기 위한 모델 파일 포맷이다. GGUF 자체가 어떤 역할을 뜻하지는 않는다.
같은 GGUF라도 안에 어떤 모델이 들어 있느냐에 따라 쓰임이 달라진다.
- query expansion 모델을 담은 GGUF
- embedding 모델을 담은 GGUF
- reranker 모델을 담은 GGUF
- generation 모델을 담은 GGUF
QMD에서는 이런 모델들을 node-llama-cpp를 통해 로컬에서 실행할 수 있다. 이 구조의 장점은 문서를 외부 API로 덜 보내고도 검색 품질을 올릴 수 있다는 점이다.
다만 GGUF를 쓴다고 자동으로 privacy가 완성되는 것은 아니다. 문서가 어디에 저장되는지, 어떤 단계에서 외부 LLM API를 호출하는지, 검색 결과가 어디로 전달되는지를 따로 봐야 한다.
단계별 실패 모드
이 글의 핵심은 여기다. LLM이 여러 단계에 들어간다는 것은 실패도 여러 단계에서 생긴다는 뜻이다.
Query Expansion이 실패하면 검색어가 엉뚱한 방향으로 넓어진다. 사용자는 “예산 때문에 막힌 고객”을 찾고 싶은데 expansion이 “pricing page”나 “billing plan” 쪽으로 치우칠 수 있다.
Embedding이 실패하면 의미상 가까운 문서를 놓친다. 특히 짧은 query, 사내 약어, 제품명, 한국어와 영어가 섞인 문장에서 문제가 커진다.
HyDE가 실패하면 가상 passage가 너무 구체적인 거짓 디테일을 만들 수 있다. HyDE는 검색용으로만 써야 하고, 그 내용을 최종 답변 근거로 쓰면 안 된다.
BM25가 실패하면 정확한 키워드가 없는 문서를 놓친다. 반대로 너무 흔한 단어가 많은 문서를 과대평가할 수도 있다.
RRF가 실패하면 여러 검색 경로의 잡음이 같이 올라온다. 특히 query expansion이 너무 많은 query를 만들면 관련 없는 후보가 fusion 단계에서 살아남을 수 있다.
Reranker가 실패하면 그럴듯하지만 질문과 다른 chunk가 상위로 올라온다. Reranker는 후보 전체를 새로 찾는 것이 아니라 후보 안에서만 판단하므로, 1차 검색 후보가 나쁘면 한계가 있다.
Chunk Selection이 실패하면 main LLM이 필요한 근거를 못 본다. 이 경우 main LLM을 바꿔도 답변은 계속 약하다.
Main LLM이 실패하면 근거는 맞는데 답변이 과장되거나, 근거 밖 내용을 섞거나, citation을 잘못 붙인다.
이렇게 보면 “답변이 별로다”라는 문제를 한 단계로 고칠 수 없다. 어느 단계에서 context가 잘못 들어갔는지 봐야 한다.
설계할 때의 판단 기준
검색형 LLM 시스템을 설계할 때는 다음 질문을 순서대로 던지는 편이 좋다.
첫째, 이 단계는 생성이 필요한가, 판별이 필요한가, 표현 변환이 필요한가?
Query Expansion과 HyDE는 생성이다. Embedding은 표현 변환이다. Rerank는 판별이다. Main Answer는 생성이다. 역할이 다르면 모델 선택도 달라진다.
둘째, 이 단계가 봐야 하는 context는 무엇인가?
전체 문서가 필요한가, query 하나면 충분한가, query와 candidate 쌍이 필요한가, 대화 맥락까지 필요한가를 구분해야 한다.
셋째, 이 단계의 출력은 사람이 읽는 것인가, 다음 단계의 입력인가?
Query Expansion, HyDE, embedding, rerank 출력은 대부분 중간 산출물이다. 사람이 읽을 답변처럼 다루면 안 된다.
넷째, local로 돌릴 가치가 있는가?
민감한 문서가 많고 반복 호출이 많다면 query expansion, embedding, rerank를 local로 돌리는 가치가 크다. 반대로 최종 답변 품질이 중요하고 외부 전송이 허용된다면 main LLM은 더 큰 외부 모델을 쓸 수도 있다.
다섯째, 실패했을 때 관측 가능한가?
검색 query, top-k 후보, RRF 결과, rerank score, 최종 context를 로그로 볼 수 있어야 한다. 이 중간 상태가 없으면 “LLM이 이상하다”는 말밖에 못 한다.
LLM Wiki 관점에서의 결론
LLM Wiki는 단순히 문서를 많이 넣고 LLM에게 물어보는 구조가 아니다. 원본 문서, wiki card, schema, 검색 계층, agent workflow가 함께 돌아가야 한다.
그중 QMD는 검색 계층에 가깝다. Markdown 문서를 색인하고, BM25와 vector search를 섞고, query expansion과 rerank를 붙이고, MCP로 agent가 호출할 수 있게 만든다.
LLM은 이 구조 안에서 여러 번 쓰인다. 하지만 매번 같은 일을 하지 않는다.
- Query Expansion LLM은 질문을 검색 가능한 표현으로 바꾼다.
- Embedding 모델은 텍스트를 vector로 바꾼다.
- HyDE generator는 검색용 가상 passage를 만든다.
- Reranker는 후보 chunk를 다시 평가한다.
- Agent LLM은 QMD 같은 도구를 호출한다.
- Main Answer LLM은 선택된 근거를 읽고 답변한다.
좋은 retrieval system은 이 역할들을 한 모델에 뭉개 넣지 않는다. 작은 모델, 검색 알고리즘, local index, main LLM을 각각 맞는 자리에 둔다.
그래서 “LLM은 어디에 쓰이는가?”의 답은 하나가 아니다.
검색 전에는 질문을 바꾸는 데 쓰이고, 검색 중에는 의미 표현과 후보 평가에 쓰이고, 검색 후에는 근거를 읽어 답변하는 데 쓰인다.
이 구분을 잡으면 QMD, RAG, LLM Wiki의 구조가 훨씬 선명해진다. 그리고 문제가 생겼을 때도 “모델이 별로다”가 아니라 “query expansion이 넓다”, “embedding이 약하다”, “reranker 후보가 나쁘다”, “main LLM context가 부족하다”처럼 고칠 지점을 찾을 수 있다.