지식그래프 데이터 품질, 모니터링 안 하면 3가지가 조용히 깨집니다
지식그래프를 구축하고 운영하기 시작하면, 처음에는 괜찮습니다. 노드도 잘 들어가고, 관계도 연결되고, 검색 결과도 나오거든요. 그런데 문서를 계속 임포트하고 엔티티가 쌓이다 보면, 어느 순간 검색 결과가 이상해지기 시작합니다.
"분명 있는 엔티티인데 검색에 안 잡힌다", "검색 결과에 관련 없는 노드가 섞여 나온다" — 이런 증상이 하나씩 나타나는데, 문제는 이게 한 번에 터지는 게 아니라 슬금슬금 조용히 진행된다는 거였습니다.
터지고 나서야 찾고, 매번 Cypher로 수동 확인했다
첫 번째로 발견한 건 고아 노드였습니다. 관계가 하나도 없는 노드가 그래프에 수십 개 쌓여 있었거든요. 문서 재임포트 과정에서 관계는 삭제됐는데 노드만 남은 경우였습니다. 이 노드들이 벡터 검색에 섞여 나오면서, 질문과 관련 없는 결과가 끼어들기 시작했어요.
두 번째는 벡터 정합성 문제였습니다. Neo4j에 노드는 있는데 Qdrant에 임베딩이 없는 엔티티가 있었거든요. 노드를 추가하고 임베딩 생성이 실패했는데, 에러가 조용히 넘어간 케이스였습니다. 이 엔티티는 그래프 탐색에서는 나오는데 벡터 검색에서는 아예 안 잡혀서, 검색 경로에 따라 답변이 달라지는 증상이 나타났어요.
세 번째는 중복 엔티티였습니다. 같은 대상인데 이름이 다르게 들어간 거예요. "결제서비스"와 "결제시스템"이 별도 노드로 존재하면서 각각 다른 관계를 갖고 있었습니다. 질문에 따라 한쪽만 잡혀서 답변이 불완전해지는 문제였어요.
세 가지 모두 터지고 나서야 알았고, 그때마다 Cypher 쿼리를 직접 짜서 확인하고 수동으로 고쳤습니다. 이걸 매번 반복하다 보니, 대시보드로 상시 감시해야겠다는 결론에 도달한 거였어요.
문제를 정리해보니, 관점이 5가지로 나뉘더라
대시보드를 설계하면서 "뭘 감시해야 하지?"를 정리해봤더니, 5가지 관점으로 분류가 됐습니다. 실제로 터져서 알게 된 3가지, 그리고 아직 안 터졌지만 경험상 미리 넣어둔 2가지입니다.
관점 | 출발점 | 한 줄 요약 |
|---|---|---|
그래프구조 | 🔴 실제 터짐 | 고아 노드, 자기참조 등 그래프 자체가 깨진 것 |
벡터정합성 | 🔴 실제 터짐 | 노드는 있는데 임베딩이 없거나, 반대인 경우 |
일관성 | 🔴 실제 터짐 | 같은 대상이 다른 이름으로 중복 존재 |
스키마정합성 | 🟡 미리 설계 | 스키마에 없는 타입이 그래프에 남아있는 경우 |
완전성 | 🟡 미리 설계 | 임포트가 누락되거나, 속성이 비어있는 경우 |
핵심은 터진 것만 감시하면 안 된다는 거였습니다. 터지기 전에 감지하려면 "이건 아직 문제 없지만 언제든 터질 수 있는 영역"도 같이 봐야 하거든요.

관점 1 — 그래프구조: 그래프 자체가 깨져 있는지
가장 기본적인 관점입니다. 그래프의 구조 자체에 문제가 있는지를 봅니다.
대표적인 게 고아 노드 — 관계가 하나도 없는 노드입니다. 문서 재임포트나 온톨로지 변경 과정에서 관계만 삭제되고 노드가 남는 경우에 생기거든요. 벡터 검색에서 이 노드가 잡히면 맥락 없는 결과가 섞여 나옵니다.
자기참조 관계도 감시 대상입니다. A→A처럼 자기 자신을 가리키는 관계는 LLM 추출 과정에서 간혹 생기는데, 그래프 탐색에서 루프를 만들 수 있어요.
대시보드에서 보는 지표는 이런 것들입니다: 관계 없는 노드 수, 자기참조 관계 수, 전체 노드 대비 고아 노드 비율. 이 숫자가 0이 아니면 확인이 필요한 거예요.
관점 2 — 벡터정합성: Neo4j와 Qdrant가 어긋나지 않았는지
지식그래프 시스템은 Neo4j(그래프)와 Qdrant(벡터)를 같이 쓰는 구조거든요. 노드를 추가하면 임베딩도 같이 생성되어야 하는데, 이 둘이 어긋나는 경우가 있습니다.
Neo4j에는 있는데 Qdrant에 없는 경우 — 노드 생성 후 임베딩 생성이 실패했을 때. 그래프 탐색에서는 나오는데 벡터 검색에서는 안 잡히는 증상이 나타납니다.
반대로 Qdrant에는 있는데 Neo4j에 없는 경우 — 노드를 삭제했는데 벡터를 안 지운 경우. 벡터 검색에서 잡히는데 실제 그래프 정보가 없어서 답변이 불완전해져요.
지표는 단순합니다: 임베딩 없는 노드 수, 노드 없는 벡터 수, Neo4j-Qdrant 간 ID 불일치 건수. 비유하자면 명부(Neo4j)와 사진첩(Qdrant)이 같은 사람을 빠짐없이 포함하고 있는지 대조하는 거예요.
관점 3 — 일관성: 같은 대상이 다른 이름으로 존재하지 않는지
"결제서비스"와 "결제시스템"이 별도 노드로 들어가 있으면, 관계도 분산되고 검색도 한쪽만 잡힙니다. LLM이 문서에서 엔티티를 추출할 때 표현이 조금씩 다르게 들어오는 게 원인이거든요.
이건 이전에 Levenshtein 거리 + LLM 의미 비교로 유사 타입을 감지하는 로직을 만들었었는데, 대시보드에서는 이걸 상시 모니터링으로 올리는 겁니다. 유사도가 높은 노드 쌍의 수, 동일 타입 내 이름 변형 건수를 추적해서, 일정 기준을 넘으면 알림이 가게 하는 거예요.
4. 스키마정합성: 스키마와 실제 데이터가 맞는지
이건 아직 터진 적은 없는데, 온톨로지 거버넌스를 운영하면서 "이건 언제든 터질 수 있겠다"고 느꼈던 영역입니다.
온톨로지를 업데이트하면 승격된 타입만 그래프에 남아야 하는데, pending 상태 타입의 엔티티가 잔존할 수 있거든요. 또 스키마에서 삭제한 관계 타입이 실제 그래프에 남아있는 경우도 가능합니다. 재임포트 과정에서 정리가 깔끔하게 안 되면 생기는 문제예요.
지표는: 스키마에 없는 노드 타입 수, 스키마에 없는 관계 타입 수, pending 상태 타입을 사용하는 엔티티 수. 이 숫자가 0이 아니면 거버넌스 프로세스 어딘가에서 누수가 생긴 거예요.
관점 5 — 완전성: 들어와야 할 데이터가 빠져 있지 않은지
마지막 관점도 아직 문제가 터진 적은 없습니다. 하지만 문서를 계속 임포트하다 보면, 특정 도메인 문서가 빠지거나 엔티티에서 속성이 누락되는 경우가 반드시 생기거든요.
엔티티가 있는데 속성(설명, 도메인 태그 등)이 비어있으면, 검색에서 잡히더라도 답변에 필요한 맥락 정보가 부족해집니다. 또 특정 도메인의 문서 임포트가 통째로 누락되면, 해당 영역 질문에 아예 답을 못 하는 사각지대가 생겨요.
지표는: 속성 미입력 노드 비율, 도메인별 문서 임포트 건수(특정 도메인이 0이면 경고), 관계가 하나도 없는 엔티티 중 최근 임포트된 것의 수. 완전성은 "있어야 할 게 없는 것"을 찾는 관점이라, 기준선을 잡아두고 변동을 추적하는 방식이 맞더라고요.

마무리
지식그래프를 운영하면서 가장 까다로웠던 건, 데이터가 조용히 망가진다는 거였습니다. 고아 노드가 검색에 섞이고, 임베딩이 빠진 엔티티가 누락되고, 중복 노드가 답변을 불완전하게 만드는데 — 터지기 전까지 모릅니다.
그래서 감시 관점을 5가지로 정리했고, 그중 3가지는 실제로 문제를 겪은 뒤에 알게 된 것, 2가지는 경험상 미리 넣어둔 것입니다. 그래프구조, 벡터정합성, 일관성, 스키마정합성, 완전성 — 이 5가지를 대시보드에서 상시 추적하면, 적어도 "터지고 나서야 Cypher로 찾는" 상황은 줄일 수 있습니다.
지식그래프를 운영하고 있다면, 품질 모니터링을 구축 초기부터 같이 설계해두는 걸 추천합니다.