2편에서는 초기 Blue 인덱스의 문제와 이를 고쳐 Green 인덱스를 만든 과정을 다뤘다. 이번 글은 측정 이야기다. Green이 실제로 나아졌는지 평가하고, 그 결과로 운영 인덱스를 정한 과정을 정리한다.
1편에서 모델별 평가 결과도 3편에서 다루겠다고 적었다. 다만 API 키로 답변까지 생성하던 당시 구조는 지금 쓰지 않아서, 이번 글에서는 검색 성능 측정만 다룬다.
1. 평가셋을 두 벌로 나눈 이유
검색 평가셋은 실무에서 나올 법한 질문 38개로 구성했고, 그중 초기 21문항에는 사람이 직접 정답 문서 라벨을 붙였다. 지표는 recall, hit, MRR 세 가지를 썼다.
- recall@k: 질문별 전체 정답 문서 중 상위 k개 안에서 회수한 비율이다. 정답 문서가 5개이고 그중 4개를 찾았다면 0.8점이다.
- hit@k: 정답 문서가 하나라도 상위 k개 안에 있는지만 본다. 같은 사례에서 정답을 1개만 찾아도 1점이다. 그래서 hit@10이 같아도 recall@10은 다를 수 있다.
- MRR: 첫 정답 문서가 나온 순위를 반영한다. 정답이 1위면 1점, 5위면 0.2점이라 순위가 몇 칸만 밀려도 점수가 크게 바뀐다.
문제는 직접 라벨을 붙인 문항이 21개뿐이었다는 점이다. 정답 라벨을 만들려면 사람이 원문을 읽고 어떤 문서까지 정답으로 인정할지 판단해야 한다. 그래서 평가셋을 빨리 늘리기 어려웠고, 검색 방식을 바꿔도 일부 문항의 결과만 달라져 실제 품질이 좋아졌는지 판단하기 어려운 경우가 있었다.
대표적인 사례가 BM25 형태소 분석기였다. 한국어 문장을 형태소 단위로 나눠 색인하도록 바꾸자 BM25 자체 지표는 눈에 띄게 올랐다. 숫자만 보면 당연히 운영에 반영할 개선처럼 보였다. 하지만 라벨이 있는 21문항에서는 상위 검색 결과가 거의 달라지지 않았다. BM25 점수는 올랐지만, 실제 정답 검색 품질이 좋아졌는지는 확인할 수 없었다.
그래서 149문항 규모의 평가셋을 따로 만들어 다시 테스트했다. 149문항 중 102문항에서 상위 결과가 바뀌었지만, 최종 지표는 소수 넷째 자리까지 같았다(2승 2패). 형태소 분석은 결과를 크게 흔들었을 뿐, 정답을 찾는 품질에는 효과가 없었다. 이 코퍼스는 식별자와 영문 용어가 중심이고, 한글 질의도 이미 도메인 용어로 잡히기 때문으로 보인다. 21문항에서 본 BM25 자체 지표만 믿었다면, 효과 없는 변경을 개선으로 판단하고 반영할 뻔했다.
이 경험 이후 평가셋을 두 종류로 나눠 쓴다.
- 골든 셋: 직접 정답 라벨을 붙인 소규모 셋. 지금 검색 결과가 실제로 정확한지 판단한다.
- 회귀 셋: 149문항. 검색 방식을 바꿨을 때 기존보다 크게 나빠지지 않았는지만 감지한다.
하나의 평가셋으로 모든 결론을 내리기보다, 규모와 신뢰도에 맞게 역할을 나눴다.
2. Blue와 Green 비교
2편에서 청킹과 결과 융합 방식을 개선했으니 Green의 지표가 전반적으로 오를 거라고 예상했다. 결과는 달랐다.
| 지표 | Blue | Green | 결과 |
|---|---|---|---|
| recall@5 | 0.730 | 0.722 | 사실상 동률 |
| recall@10 | 0.833 | 0.833 | 완전 동률 |
| MRR@10 | 0.851 | 0.721 | Green 0.130p 하락 |
| p50 지연 | 1,665ms | 574ms | Green 약 3배 단축 |
| p95 지연 | 2,972ms | 642ms | Green 약 4.6배 단축 |
Green은 응답이 3배 넘게 빨라졌고 recall도 Blue와 거의 같았다. 그러나 MRR@10은 0.130p 낮았다.
당시에는 이 차이를 문항 수가 적어서 생긴 흔들림으로 봤다. 21문항에서는 한 문항의 성공 여부가 비율 지표에 약 4.8%p 영향을 주니, 몇 문항의 순위 변화로 생긴 노이즈라고 생각했다. 이 해석은 틀렸다.
3. 시행착오
Blue와 Green의 결과가 달라진 문항을 하나씩 보다가 이상한 사례를 찾았다. DIP가 무엇이며 DataAdapter와 어떤 관계인지 묻는 질문이었는데, Green이 1·2위에 올린 문서는 커뮤니티의 DataAdapter 상세 설명글과 공식 매뉴얼이었다. 질문과 직접 관련된 문서인데, 정답지에 없다는 이유로 오답 처리되고 있었다.
기존 정답지의 문서 ID는 과거 Blue의 검색 결과를 참고해 사람이 쓴 것이었다. Blue 결과로 만든 골든 셋으로 Blue와 Green을 비교하고 있으니, 평가 구조 자체가 Green에 불리하다고 판단했다. 그래서 "누락된 정답을 보완하면 Green의 점수가 크게 오를 것이다"라는 가설을 세우고 테스트했다.
정답지를 다시 정비했다. 매뉴얼이나 스키마 문서를 제목으로만 적어 둔 항목은 실제 문서 ID로 바꿨고, 채점 가능한 문항을 21개에서 25개로 늘렸다. 정답 범위가 너무 좁았던 12문항도 함께 고쳤다.
다만 이 과정이 정답지의 편향을 완전히 없앤 것은 아니다. 최초 정답지는 Blue 결과를 참고했고, 교정할 때는 Green의 오답 사례를 본 뒤 누락된 정답을 보완했다. 두 인덱스의 후보 문서를 합친 뒤 이름과 순위를 가리고 다시 판정하는 방식이 더 안전하지만, 이번에는 거기까지 가지 못했다.
그런데 교정 결과는 예상과 정반대였다. MRR 격차는 -0.130에서 -0.159로 더 벌어졌다. 동률이던 recall@10도 교정 후에는 Green이 0.097 낮았다. 정답지를 고치면 Green의 불이익이 풀릴 거라 생각했지만, 오히려 Blue의 우위가 더 분명해졌다.
이유는 새로 추가된 정답 문서에서 찾았다. 교정으로 새로 정답이 된 문서는 28건이었고, 모두 공식 매뉴얼이나 DB 스키마 문서였다. Blue는 이 중 23건을 상위 10위 안에 올렸고, Green은 13건이었다. 기존 정답지가 Green에 불리했던 게 아니었다. 커뮤니티 글 ID 중심으로 정답을 인정하던 방식이 오히려 공식 문서 검색에 강한 Blue의 성능을 제대로 반영하지 못하고 있었다.
소스 유형별로 나누면 차이가 더 분명하다. 아래 표는 문항별 recall@10을 먼저 계산한 뒤 평균한 macro 기준이다. 한 문항에 여러 소스의 정답이 있을 수 있어 소스별 문항 수의 합은 25보다 크다.
| 소스 | 문항 | Blue | Green | 차이 |
|---|---|---|---|---|
| 커뮤니티 글 | 21 | 0.833 | 0.833 | 0.000 |
| 공식 매뉴얼 | 8 | 0.906 | 0.344 | -0.563 |
| DB 스키마 | 4 | 0.750 | 0.750 | 0.000 |
처음에는 Green이 커뮤니티 글 같은 비정형 지식 검색에 강할 거라고 생각했다. 실제로는 커뮤니티 글과 DB 스키마에서 Blue와 대등했고, 공식 매뉴얼에서만 크게 뒤처졌다. 적어도 순위와 회수율 지표에서는 Green이 실제로 졌다.
그러면 질문이 남는다.
순위 지표에서 분명히 진 Green을 왜 운영 인덱스로 골랐나?
4. 지표가 낮은 Green을 고른 이유
자동 평가만 보면 Blue를 유지하는 게 자연스럽다. 하지만 운영 인덱스를 정하려면 지표의 높낮이뿐 아니라, 그 지표가 실제 사용 방식을 얼마나 반영하는지도 봐야 했다.
근거 1. 순위는 밀렸지만 정답은 상위 결과 안에 남아 있다
MRR은 첫 정답의 순위에 민감하다. 정답이 1위에서 4위로 밀리면 1점에서 0.25점으로 떨어진다. 그런데 이 서버의 실제 사용자인 코딩 에이전트는 첫 결과만 읽지 않는다. 상위 N개의 근거를 함께 읽고 답을 만든다. 그래서 첫 정답의 순위와 별개로, 정답이 상위 결과 안에 들어왔는지를 따로 쟀다.
hit@1에서 Blue만 성공한 문항은 6개, Green만 성공한 문항은 없었다. 정확 McNemar 양측 검정은 p=0.031이었다. MRR@10은 문항별 순위 점수 차이에 10,000회 paired bootstrap을 적용했다.
| 지표 | Blue | Green | 차이 | 유의성 |
|---|---|---|---|---|
| hit@1 | 0.800 | 0.560 | -0.240 | McNemar p=0.031 |
| hit@5 | 0.920 | 0.880 | -0.040 | 유의하지 않음 |
| hit@10 | 0.960 | 0.960 | 0.000 | 차이 없음 |
| MRR@10 | 0.844 | 0.686 | -0.159 | paired bootstrap p=0.002 |
최상위 결과의 성공을 보는 hit@1과 첫 정답의 순위를 보는 MRR@10에서는 Green이 유의하게 낮았다. 반면 정답이 상위 5개나 10개 안에 하나라도 있는지를 보는 hit@5, hit@10에서는 차이가 거의 없었다.
교정 전 21문항에서는 이 특성이 더 분명했다. hit@5와 hit@10의 성공 여부가 두 인덱스에서 한 문항도 다르지 않았다. Blue에서 정답이 1위였는데 Green에서 밀린 문항이 6개 있었지만, 그중 5개는 Green에서도 5위 안에 남아 있었다. Green이 정답을 아예 놓친 경우보다, 상위 결과 안에서 정답의 순서가 뒤로 밀린 경우가 많았다.
그래서 상위 결과 여러 건을 함께 읽는 코딩 에이전트에서는 MRR 차이가 그대로 답변 품질 차이로 이어진다고 단정하기 어려웠다.
근거 2. 결과 묶음을 직접 비교하면 Green이 더 많이 선택됐다
두 번째 근거는 블라인드 평가다. 알고리즘 이름과 순위를 가리고 상위 결과 묶음을 평가했더니 Green 14승, Blue 12승, 무승부 12회였다. 이미지 캡션 오염도 Blue 7건에서 Green 2건으로 줄었다. 하지만 승패 차이가 2건뿐이고 무승부가 12회라, 이것만으로 Green이 낫다고 결론 내리기는 어려웠다.
확인할 문제가 하나 더 있었다. 심판이 내용이 아니라 앞이나 뒤에 놓인 결과를 반복해서 골랐다면 블라인드 평가도 믿기 어렵다. 이를 확인하려고 기존 심판과 계열이 다른 LLM 심판을 더했다. 38문항마다 Blue와 Green의 배치 순서를 뒤집어 두 번씩 평가하게 했다. 순서를 바꿔도 같은 인덱스를 고른 경우만 유효한 승리로 인정하고, 내용과 상관없이 계속 앞이나 뒤를 고른 경우는 위치 추종으로 분류했다. 이 실험을 세 번 반복했다.
| 회차 | Green 승 | Blue 승 | 위치 추종 | 무승부·불일치 |
|---|---|---|---|---|
| 1회 | 18 | 6 | 9 | 5 |
| 2회 | 18 | 9 | 7 | 4 |
| 3회 | 18 | 6 | 10 | 4 |
세 번 모두 Green이 더 많이 선택됐다. Green의 승수는 매회 18건으로 같았고, Blue만 6~9건 사이에서 흔들렸다. 동시에 전체 판정의 평균 22.8%는 내용이 아니라 결과가 놓인 위치를 따라갔다. 순서를 통제하지 않았다면 약 네 문항 중 한 문항에서 위치 편향을 품질 판단으로 잘못 읽을 수 있었다.
자동 지표에서는 Green이 낮았지만, 위치 편향을 통제한 블라인드 평가에서는 Green이 Blue보다 2~3배 더 많이 선택됐다. 두 평가가 다른 결과를 낸 이유는 재는 대상이 달라서라고 판단했다. 자동 지표는 정답 문서가 얼마나 앞에 나오는지를 쟀고, 블라인드 평가는 상위 결과 묶음이 질문에 답하는 데 얼마나 유용하고 노이즈가 얼마나 적은지를 비교했다.
근거 3. 운영 성능과 노이즈도 Green이 유리했다
세 번째 근거는 운영 성능이다. Green으로 바꾸면서 p95 응답 시간이 2,972ms에서 642ms로 줄었다. 이미지 캡션 오염도 7건에서 2건으로 줄었다. 대신 Green은 메모리를 더 써서 Cloud Run 메모리를 2GB로 올려야 했다.
정리하면 이렇다.
- Green은 첫 정답의 순위에서 Blue보다 낮았다.
- 공식 매뉴얼 정답 회수에서도 Blue에 뒤처졌다.
- 그러나 상위 5개·10개 안에 정답이 하나라도 들어오는 비율은 거의 같았다.
- 결과 묶음을 직접 비교한 블라인드 평가에서는 Green이 일관되게 더 많이 선택됐다.
- 응답 속도가 크게 좋아졌고 이미지 캡션 오염도 줄었다.
- 대신 메모리가 더 필요했다.
이를 종합해 Green으로 바꿨다. Green이 모든 지표에서 앞서서 고른 것이 아니다. Green이 진 지표가 무엇을 재고 있고, 그 차이가 코딩 에이전트의 실제 사용 방식에서도 중요한지를 따져 본 뒤 내린 결정이다.
지금 운영 환경에서는 KB_ACTIVE_INDEX=green으로 Green만 켜 두었다. 장애나 예상치 못한 품질 저하에 대비해 Blue로 바로 되돌릴 스위치는 남겨 뒀다.
마무리
이번 작업에서 가장 중요했던 것은 점수가 높은 인덱스를 고르는 일이 아니었다. 실제 사용 환경에서 필요한 품질이 무엇인지 정의하고, 그 품질을 제대로 재고 있는지 지표와 평가자까지 다시 검토하는 일이었다.
마지막 4편에서는 Cloud Run 청구서에서 시작된 비용 문제와 개선 과정, 증분 업데이트와 데이터 영속화 자동화를 다룬다.