[개발 공부] / Query Coverage, 질문 완성도를 따로 보는 레이어.md

Query Coverage, 질문 완성도를 따로 보는 레이어

조회

2026년 4월 21일 | 개발 공부


Query Coverage는 검색 결과가 질문 안의 핵심 대상과 조건을 얼마나 빠짐없이 실제로 받쳐 주는지를 보는 관점이다. 쉽게 말해 관련 문서가 어딘가에 하나 들어왔는지만 보는 게 아니라, 지금 앞에 올라온 결과들이 질문의 몇 퍼센트를 완성하고 있는가를 따로 읽는 방식이다. 나는 한동안 검색 품질을 recall이나 top-k hit로만 보는 쪽에 가까웠는데, 최근 GraphRAG 쪽 실험을 만지면서는 이 중간 층을 분리해서 보지 않으면 계속 같은 착시를 겪게 된다는 걸 꽤 또렷하게 느꼈다.

특히 엔티티가 두세 개 섞인 질문에서는 이 차이가 더 크게 드러났다. 검색기는 분명 꽤 괜찮은 후보를 가져오는데, 막상 답변은 한 조각이 비어 있는 느낌이 반복됐다. 로그를 열어보면 완전히 틀린 검색은 아니었다. 다만 질문이 요구한 축 중 하나가 빠진 채로 상위권이 정렬돼 있었고, 나는 그 상태를 너무 오래 "찾았으니 거의 된 것"처럼 착각하고 있었다. 그 뒤로는 검색 결과를 볼 때 점수보다 먼저, 이 결과가 질문을 끝까지 받쳐 주는가를 따로 확인하게 됐다.

1. recall이 괜찮은데 답변이 허전한 순간이 자꾸 생겼다

검색 시스템을 처음 붙일 때는 대개 recall이 먼저 눈에 들어온다. 정답 문서가 top-k 안에 들어왔는지, 후보군이 얼마나 넓게 확보되는지, 빠진 질문이 얼마나 줄어들었는지 같은 숫자가 가장 직접적으로 보이기 때문이다. 나도 한동안은 그 숫자가 좋아지면 검색 품질도 거의 같이 좋아진다고 생각했다.

그런데 실제 질의 로그를 보다 보면 다른 종류의 실패가 따로 있었다. 예를 들어 질문이 Customer Dashboard, Payment API, Root Cause Note를 함께 묻고 있는데, 상위 결과는 앞의 두 개만 강하게 설명하고 마지막 한 축은 빠뜨린 채 올라오는 경우다. 이런 결과는 관련성이 아예 없는 건 아니라서 점수도 그럴듯하게 나오고, 사람도 처음에는 속기 쉽다. 하지만 LLM에 상위 몇 개만 넣는 순간 이 누락이 그대로 답변의 빈칸으로 이어진다.

  • 정답 문서가 후보군 안에 들어오는 것과, 질문을 충분히 완성하는 결과가 상위권에 놓이는 것은 다른 문제다.
  • multi-entity 질문에서는 한두 축만 맞아도 점수가 꽤 높게 나와 착시가 심해진다.
  • 그래서 recall만 보면 "거의 맞았다"고 생각하지만, 실제 답변 품질은 계속 허전할 수 있다.

나는 이 차이를 자주 겪고 나서야 검색 실패를 하나의 숫자로 뭉개면 안 된다는 걸 받아들였다. recall은 여전히 중요하지만, 적어도 질문이 여러 조각으로 이루어진 순간부터는 무엇이 들어왔는가무엇이 빠졌는가를 같이 읽어야 했다.

2. Query Coverage는 질문의 빠진 조각을 드러내는 레이어였다

내가 이해한 query coverage는 거창한 새 알고리즘이라기보다, 검색 결과를 읽는 단위를 한 단계 더 세분화한 것이다. 질문에서 핵심 엔티티나 조건을 먼저 뽑고, 각 결과가 그중 몇 개를 실제로 지지하는지 본다. 그러면 같은 top result라도 느낌이 완전히 달라진다. 단순 유사도 점수만 볼 때는 잘 나온 것처럼 보이던 결과가, coverage 기준으로 보면 partial hit인지 full hit인지 바로 갈라지기 때문이다.

이 감각이 유용했던 이유는 검색 결과를 사람이 다시 해석하는 시간을 많이 줄여줬기 때문이다. 예전에는 상위 문서를 열어 보고 머릿속으로 "이건 두 개는 맞는데 하나가 빠졌네"를 매번 판단해야 했다. coverage를 노출하면 그 판단이 출력 자체에 나타난다. 검색기는 여전히 점수를 계산하지만, 나는 그 위에 질문 완성도라는 보조 좌표를 하나 더 얹어 보는 셈이다.

query_entities: [Customer Dashboard, Payment API, Root Cause Note]
hit_entities: [Customer Dashboard, Payment API]
missing_entities: [Root Cause Note]
coverage_ratio: 0.67

이 네 줄이 생기고 나면 결과를 읽는 방식이 달라진다. 예전에는 높은 점수 결과를 중심으로 왜 괜찮아 보이는지 설명했다면, 지금은 coverage가 낮은 결과를 보면서 왜 아직 불완전한지부터 설명하게 된다. 나는 이 전환이 꽤 중요했다. 검색을 더 잘 맞히는 일 못지않게, 어디가 비었는지 더 빨리 아는 일이 다음 조정을 훨씬 쉽게 만들기 때문이다.

3. recall, coverage, reranking은 같은 층의 기술이 아니었다

이 개념을 정리하면서 제일 도움이 됐던 건 세 단계를 아예 다른 질문으로 나눠 보는 것이었다. retriever는 관련 후보를 데려오는 층이고, query coverage는 그 후보가 질문을 얼마나 채우는지 읽는 층이며, reranking은 그 완성도를 포함해 누가 앞줄에 설지 다시 정하는 층이다. 셋이 섞이면 문제 원인이 흐려지고, 셋이 분리되면 조정 방향도 훨씬 빨라진다.

내가 던지는 질문 주로 보는 신호
Retriever 관련 문서를 후보군 안에 넣었는가 top-k hit, recall, candidate diversity
Query Coverage 질문의 핵심 조각을 얼마나 빠짐없이 받쳤는가 hit entities, missing entities, coverage ratio
Reranker 질문을 더 완성하는 결과를 앞쪽에 세웠는가 top-1 변화, rank shift, 상위권 안정성

이렇게 놓고 나니 예전에 헷갈리던 장면들이 정리됐다. 후보군 안에는 정답이 있었는데도 상위권이 허전했다면, retriever 하나의 실패로만 볼 일이 아니었다. coverage를 읽지 않았거나, coverage를 읽고도 reranking에 반영하지 못한 문제일 수도 있었다. 나는 이 구분이 생긴 뒤로 검색 파이프라인을 훨씬 덜 막연하게 보게 됐다.

4. multi-entity 질문에서는 coverage가 사실상 문맥 예산의 기준이 됐다

LLM 기반 검색에서 문맥 창은 늘 한정돼 있다. top-20을 다 찾았다고 해도 실제로는 앞의 몇 개만 넣게 되고, 그 몇 개가 답변의 방향을 거의 결정한다. 그래서 상위 문서가 질문의 여러 조각을 한 번에 얼마나 받치는지가 생각보다 중요하다. coverage가 낮은 결과를 앞에 두면, 나머지 빈칸을 메우려고 더 많은 문서를 밀어 넣어야 하고 결국 잡음도 같이 늘어난다.

이 점에서 query coverage는 단순 설명용 지표를 넘어서 문맥 예산을 어디에 써야 하는지를 가르는 기준처럼 느껴졌다. partial hit를 많이 모아 놓는 것보다, full hit에 가까운 결과를 앞에 세우는 편이 실제 답변 안정성에 더 직접적이었다. 나는 예전에는 top-k를 키우는 쪽으로 먼저 반응했는데, 요즘은 질문을 더 완성하는 결과가 앞으로 오도록 정렬 기준을 손보는 쪽이 더 먼저 떠오른다.

  • coverage가 낮은 상위 결과는 문맥 창을 빨리 소모하지만 질문의 빈칸은 그대로 남긴다.
  • coverage가 높은 결과는 적은 문서 수로도 답변 뼈대를 더 안정적으로 세워 준다.
  • 그래서 multi-entity 질문일수록 recall 확대보다 coverage 기반 재정렬이 더 큰 차이를 만들 수 있다.

나는 이 감각이 생긴 뒤로 검색 로그를 볼 때 "몇 개를 찾았나"보다 "앞줄이 질문을 얼마나 다 말하고 있나"를 더 먼저 본다. 비슷한 retrieval 점수에서도 답변 품질이 꽤 다르게 나오는 이유가 여기서 설명되는 경우가 많았다.

5. 그래서 coverage는 보조 지표가 아니라 rank를 다시 읽는 출발점이 됐다

실제로 손에 잡히는 변화는 여기서 나왔다. coverage를 explain 용도로만 출력할 때는 도움이 되긴 해도 마지막 해석이 여전히 사람 머릿속에 남아 있었다. 하지만 full coverage 결과를 조금 더 우대하거나, missing entity가 많은 결과를 한 단계 아래로 미루는 식으로 ranking에 반영하면 변화 방향이 더 선명해졌다. 같은 검색 시스템인데도, 질문을 덜 비우는 결과가 위로 올라오기 시작한 것이다.

나는 이 지점에서 query coverage를 단순한 보고서 숫자보다 rank를 다시 읽는 출발점으로 보게 됐다. coverage가 없다면 partial hit와 full hit가 같은 관련성 점수 안에서 섞여 버린다. coverage가 있으면 적어도 왜 어떤 문서를 앞세우는지가 설명 가능해진다. 검색 시스템이 설명 가능해진다는 건 보기 좋은 로그가 생긴다는 뜻이 아니라, 다음 실험에서 무엇을 바꿔야 할지가 더 빨리 보인다는 뜻에 가깝다.

이건 결국 retrieval을 하나의 큰 점수판으로 보지 않는 연습이기도 했다. 후보를 데려오는 층, 질문을 얼마나 채우는지 읽는 층, 그리고 그 완성도를 앞줄에 반영하는 층을 나누고 나니 문제를 더 작게 고칠 수 있었다. 내 기준에서는 이게 최근에 얻은 가장 실용적인 공부였다.

6. 짧게 남겨두고 싶은 내 식의 정리

지금의 나는 query coverage를 단순히 "질문 엔티티를 몇 개 맞췄는가"로만 보지 않는다. 그보다 검색 결과가 질문을 어디까지 완성했는가를 보여 주는 관점으로 남아 있다. recall이 후보군의 존재를 말해 준다면, coverage는 상위 결과의 충실도를 말해 준다. 둘은 비슷해 보여도 실제 답변 품질을 흔드는 방식이 꽤 다르다.

아마 한동안은 검색 로그를 볼 때 이 좌표를 계속 같이 보게 될 것 같다. 관련 문서가 들어왔다는 사실만으로는 안심하기 어려운 질문들이 분명히 있고, 특히 엔티티가 여러 개 섞이는 순간부터는 그 차이가 훨씬 크게 드러난다. 나는 이제 검색이 잘됐는지 물으면, 점수표를 보기 전에 먼저 묻는다. 이 결과가 질문을 끝까지 받쳐 주는가.

댓글

홈으로 돌아가기

검색 결과

"" 검색 결과입니다.