기술

온톨로지 결정 하나를 고쳤는데, 지식그래프 판정 지점 넷 중 셋은 옛 뜻으로 돌고 있었습니다

2026.10.0610분 읽기

사내 문서 지식그래프 검색 도구를 운영하고 있습니다. 문서 폴더를 사업 단위로 묶어 두고, 누가 어떤 사업에 참여했는지, 발주처가 몇 곳인지, 문서가 몇 건인지를 그래프와 '사업 대장'(정식 사업으로 등록된 목록)으로 답합니다.

어느 날 대장에 오르지 않은 문서 1,302건을 조회 범위에 넣었습니다. 입찰공고, 견적, 지난 제안서 같은 것들입니다. 조회 범위가 67개 사업에서 199개 폴더로 커졌습니다. 그 직전에 고객사 대표가 두 가지를 못 박아 둔 상태였습니다. '폴더는 사업이 아니다', '모든 공고가 사업이 아니다'.

저는 그 결정을 코드에 적었습니다. 정확히는 한 자리에만 적었습니다.


범위는 커졌는데 이름이 따라오지 않았습니다

이 시스템은 배포 전후로 148문항짜리 회귀 측정 세트를 돌립니다. 범위를 넓힌 직후 7회차 측정에서 11건이 내려갔고, 그중 6건이 같은 뿌리에서 나왔습니다.

집계 축은 '199개 사업의 문서 4,399건'이라고 답했습니다. 직전 회차는 3,191건이었습니다. 회의록도 '199개 사업의 회의록 226건'이었습니다. 숫자 자체는 범위가 커진 결과라 틀린 것이 아닙니다. 틀린 것은 이름입니다. 199는 폴더 수인데 사업이라고 부르고 있었고, 그건 방금 내린 결정과 정면으로 어긋나는 말입니다.

사람 축의 답은 더 크게 어긋났습니다. 특정 인물에게 어떤 사업을 했는지 물으면 '참여한 사업 71건'이라고 답했는데, 열어 보니 70개 폴더였고 그중 대장에 오른 것은 46건, 나머지 24개는 대장 밖 폴더였습니다. 직전 회차의 46건이 대장 기준 값이었습니다. 두 개 이상의 사업에 참여한 사람도 111명에서 216명으로 뛰었습니다. 늘어난 사람 대부분은 공고나 남의 제안서에 이름이 한 번 스친 사람입니다. 여기서는 이름만 틀린 것이 아니라 셈 자체가 어긋났습니다.

결정 한 문장이 코드의 판정 지점 넷 중 한 곳에만 적용된 구조를 그린 도식


에러 없이 그럴듯한 숫자가 넷이었습니다

같은 시기에 다른 집계에서도 문제 하나가 더 나왔습니다. 전체 사업 중 한 건은 시스템 사업이라 발주처가 우리 회사 자신입니다. 발주처가 몇 곳인지 물으면 집계 도구는 실제보다 한 곳 많게 답했습니다. 그 한 곳이 우리 회사 자신이었습니다. 목록을 주는 API 는 이미 이 시스템 사업을 빼고 있었습니다. 세는 도구만 안 뺐습니다. 같은 판정이 두 자리에 각각 구현돼 있었고, 그 순간부터 갈릴 준비가 돼 있던 셈입니다.

직전 6회차에도 같은 수가 나왔지만, 숫자가 그럴듯해 정답으로 채점했습니다.

판정 지점

내놓은 답

실제

어긋난 종류

집계 문구

199개 사업의 문서 4,399건

199개 폴더

이름

사람 축

참여한 사업 71건

대장 46건 + 대장 밖 24개 폴더

이름과 셈

사업 지목

대장 밖 폴더 하나의 참여자 33명

소속 26명·사업 8건

답 자체

세는 도구

발주처 수가 한 곳 많다

우리 회사를 뺀 수

셈


실제로 틀린 답은 하나였습니다

넷 중 셋은 이름이나 셈이 어긋난 것이고, 하나는 답이 아예 틀렸습니다. 특정 협력사 사람들이 어떤 사업에 들어갔는지 묻는 질문입니다. 6회차에는 소속 18명, 사업 8건으로 답했습니다. 범위를 넓힌 뒤에는 그 회사 이름이 폴더명에 든 대장 밖 폴더 하나를 짚어 그 폴더의 참여자 33명을 냈습니다. 33명 중 실제 그 회사 소속은 7명이고 나머지는 발주처와 다른 수행사 사람들입니다.

원인은 라우팅이었습니다. 질문이 특정 사업을 지목했다고 판정되면 소속 축을 타지 않는 설계였습니다. 6회차에는 그 폴더가 범위에 없어서 자연히 소속 축이 답했습니다. 범위가 열리자 폴더 이름이 회사 이름과 겹쳐 사업 지목으로 판정됐습니다.

바로 전날에는 반대 방향의 오류를 겪었습니다. 사업명에 발주처 이름이 들어 있어, 사업 참여자 57명을 물은 질문이 발주처 소속 인원을 묻는 질문으로 잘못 분류됐고 답은 1명으로 줄었습니다. 같은 경계의 반대편입니다. 한쪽을 조이면 다른 쪽이 헐거워집니다.

같은 그래프 위에서 판정이 갈린 앞선 사례도 한 번 정리해 둔 적이 있습니다.


고치기 전에 회귀의 출처부터 갈랐습니다

참여 조회 쪽 회귀 둘은 제 배포 직후 재측정에서 발견됐습니다. 그대로 믿으면 제가 방금 만진 코드를 파게 됩니다. 148문항 전후 비교표를 열어 보니 그 둘은 이번 배포로 바뀐 목록에 없었습니다. 대장 밖 폴더를 범위에 넣은 커밋 뒤로 생긴 회귀였습니다.

여러 세션이 같은 저장소를 만지는 환경에서는 이 구분이 없으면 엉뚱한 자리를 고치고 고쳤는데 그대로라는 결과를 얻습니다. 재측정에서 내려간 항목은 내 변경 때문인지 그 사이 다른 커밋 때문인지부터 가른 뒤에 손을 댑니다.

재측정에서 내려간 항목의 원인을 내 변경과 그 사이 다른 커밋으로 가르는 판단 흐름도


빼는 것과 뒤로 미는 것은 다릅니다

세 가지 수정안을 놓고 각각의 손해를 셌습니다.

안

내용

손해

A

참여 조회 후보를 대장 안으로 한정한다

대장 밖에만 이름이 있는 사람이 네 명 중 한 명(26%)이라, 그 사람들 질문이 0건으로 물러서면서 통째로 문서 검색으로 샌다

B

대장 밖 폴더를 후보에서 빼지 않고 뒤로 민다

순위가 내려간 자리를 소속 축이 가로챈다

C

B 에 '강등 규칙'과 갈라 말하기를 더한다

폴더명 규칙에 기대는 부분이 남는다

A 안을 접은 이유는 측정 결과 때문이었습니다. 대장 밖 폴더를 콕 집어 묻는 문항 7개가 전부 정답이었고, 그 사람들을 0건으로 만들면 그 7개에도 답하지 못하게 됩니다. 안 세는 것과 못 찾는 것은 다릅니다.

B 안을 적용하자 다른 문제가 드러났습니다. 어떤 해외 사업에 누가 참여했는지 묻는 질문을 소속 축이 가로채, 다른 수행사 이름을 집어 1명이라고 답했습니다. 정답은 2명입니다. 미리 써 둔 가드 테스트가 이걸 잡았습니다. 관문을 넓혀 버리고 싶었지만, 그러면 전날 고친 반대편이 다시 헐거워집니다.

그래서 C 안을 선택했습니다. 대장에 오른 사업을 지목한 것만 확실한 지목으로 보고, 대장 밖 폴더 이름과 겹친 것은 한 번 더 따집니다. 일치한 글자가 회사 이름만으로도 모두 설명되면 특정 사업을 지목한 것으로 보지 않습니다. 이것이 '강등 규칙'입니다. 이 시스템은 폴더명에 날짜, 발주처, 사업명을 붙여 쓰기 때문에 회사 이름이 폴더명에 섞여 있고, 그래서 성립하는 규칙입니다. 폴더명 체계가 다르면 안 통합니다.

그리고 네 집계 축이 모두 대장 기준 값과 대장 밖 폴더 수를 구분해 답하게 했습니다. 사람 축, 소속 축, 태그 축, 참여 사업 수 축이 이제 모두 대장 기준 값과 대장 밖 폴더 수를 나란히 적습니다. 사람은 빼지 않았습니다. 사람 축이 세는 대상은 사람입니다. 무엇을 세는 축인지에 따라 같은 결정이 다르게 적용됩니다. 사업을 세는 축이었다면 뺐을 겁니다.


세는 자리에서만 뺍니다

시스템 사업은 세는 도구에서만 제외했습니다. 목록 API 와 같은 조건입니다. 검색 범위에서는 빼지 않았습니다. 그 그릇에는 사내 문서가 실제로 들어 있고, 빼면 그 문서들이 검색에서 사라집니다.

테스트 쪽에서 함정이 하나 있었습니다. 참여 조회가 대장을 읽게 되면서, 기존 테스트가 DB 세션 없이 호출해 실패했습니다. 세션이 없으면 대장 행을 빈 목록으로 두자는 생각이 먼저 들었는데, 그렇게 하면 전부 대장 밖으로 세어지면서 테스트가 조용히 통과합니다. 검사 조건을 완화하는 대신 테스트 데이터에 대장 행을 넣었습니다.


배포 전에 같은 실데이터로 148문항을 다시 돌렸습니다

고친 판을 따로 올려 148문항을 같은 실데이터로 돌렸습니다. 바뀐 것은 13건이고 전부 같은 방향이었습니다. 소속 질문의 사업 8건이 6회차 실측과 정확히 같았는데, 그때는 대장 밖이 범위에 없어 자연히 8이 나온 값입니다. 뜻하지 않게 좋은 대조군이 됐습니다.

문항

고치기 전

고친 뒤

이 사람이 참여한 사업

71건

대장 46건 + 대장 밖 24개 폴더

그 협력사 사람들의 사업

참여자 33명

소속 26명·사업 8건 + 대장 밖 자료 6곳

발주처 수

한 곳 많음

우리 회사를 뺀 수

테스트는 796개가 통과했고 그중 6개가 이번에 새로 넣은 것입니다.

참여 사업 수 응답이 뭉뚱그린 71건에서 대장 기준과 대장 밖으로 갈라진 답으로 바뀐 비교 그림


결정을 적을 때 같이 적어 두는 것

이번에 넷을 다 찾아낸 것은 목록이 아니라 148문항 회귀 측정입니다. 측정 세트가 없었다면 참여 사업 수 축은 고쳤으니 됐다는 데서 끝났을 겁니다. 목록은 처음 결정할 때 쓰는 도구이고, 놓친 자리를 잡는 것은 측정입니다. 둘 다 있어야 합니다.

그래서 결정을 기록할 때 아래를 같이 적기로 했습니다.

이 결정이 닿아야 하는 코드 자리를 세어서 목록으로 적는다. 문장 하나로 끝내지 않는다

같은 판정이 두 곳에 구현돼 있으면 한 곳으로 모으거나, 못 모으면 두 곳을 같이 재는 테스트를 둔다

숫자를 채점할 때 구성 요소를 열어 본다. 센 수 중 하나가 우리 회사인지는 열어야만 보인다

데이터의 단위가 바뀌면 그 단위를 부르는 말도 같이 바꾼다. 숫자는 자동으로 따라오지만 이름은 안 따라온다

후보에서 빼기 전에 손해를 센다. 안 세는 것과 못 찾는 것은 다르다

같은 경계의 양쪽 사례를 한 테스트 세트에 나란히 둔다. 한쪽을 고친 규칙이 다른 쪽을 깨뜨린다

한 결정이 관련된 모든 지점에 반영되지 않아 생긴 문제는 데이터 쪽에서도 같은 모양으로 나옵니다.

판정 지점 넷을 다 고쳤다는 것이 판정이 다 옳다는 뜻은 아닙니다. 채점 기준을 정정할 문항이 둘 남아 있고, 한 문항은 축이 전부 빈손이라 우연히 물러서는 상태입니다. 명시적으로 물러서게 할지는 아직 정하지 않았습니다. 다만 이제는 어느 자리가 남았는지를 목록으로 알고 있습니다.

#온톨로지#지식그래프#RAG운영#회귀측정#판정지점