Palantir Foundry에 대한 설명을 듣고나니 제 IBM Box Ontology의 부족함이 눈에 들어오기 시작했습니다. 이 시스템을 만들면서 저는 계속해서 이 시스템을 정말 온톨로지라고 부를 수 있을지에 대한 의문에 시달렸습니다. 하지만 파운드리를 보고나니 생각이 정리되기 시작했습니다.
결론부터 정리해보면 이렇습니다.
제가 지난 두 편에서 만들었다고 적었던 온톨로지는, Palantir 가 말하는 세 레이어 중 가장 첫 번째 (Semantic)만 구현한 시스템이었습니다. 두 번째 (Kinetic) 와 세 번째 (Dynamic) 가 사실상 비어 있고, 그래서 합의의 표현까지는 도달했지만 살아 움직이는 시스템으로는 아직 가지 못한 상태입니다.
많은 사람들이 온톨로지를 GraphDB를 있어보이게 잘 포장한 키워드로만 이해합니다. 저 또한 같은 관점으로 이 시스템을 구축하기 시작했고, 만들고나니 문제가 보이기 시작했습니다. 이번 글이 온톨로지를 이해하는데 여러분에게 많은 도움을 줄 것이라 기대합니다.
1. 명사만 있고 동사가 없다
Palantir 시리즈 2편에서 이런 이야기를 했습니다.
명사 (semantic) + 동사 (kinetic) + 가정 (dynamic) 으로 구성된 조직의 디지털 표현이 온톨로지이고, 셋 중 하나라도 빠지면 그건 그냥 데이터 모델이지 온톨로지가 아닙니다.
제 시스템의 세 레이어를 채워보면 이렇습니다.
| 레이어 | Palantir 가 다루는 것 | 제 KB Ontology 의 상태 |
|---|---|---|
| Semantic (명사) | Object / Link / Property | Document, Organization, Topic, Product, Team. 잘 만들어져 있음 |
| Kinetic (동사) | 사용자 Action, Event, Workflow, write-back | 사실상 없음 |
| Dynamic (가정) | 시뮬레이션, what-if, 시나리오 | 없음 |
02_ontology_design.md 에 ActionItem, Decision, Risk 같은 좋은 후보가 이미 클래스 하이어라키에 있는데, 정작 extract/schemas.py 의 ExtractedActionItem 은 LLM 이 회의록 본문에서 읽어낸 것일 뿐, 시스템 위에서 누군가가 수행한 행위로서의 Action 이 아닙니다. 동사가 그래프에 있긴 한데, 그건 과거 시제의 동사 일 뿐 현재 일어나고 있는 동사 가 아닙니다.
다시말해 제가 만든 그래프는 만든 시점의 캡처일뿐입니다. 조직과 지식은 계속 변하고 흐릅니다. 그래프에 이것이 반영되었을때 온톨로지가 됩니다.
2. Write-back 의 부재 - 시스템이 한 방향으로만 흐른다
Palantir 시리즈 4편부터 7편까지 끈질기게 등장한 단어가 write-back 이었습니다. 분석가의 결론, 운영자의 결정, 모델이 잡지 못한 외부 요인에 대한 사람의 판단. 이런 신호가 다시 온톨로지로 흘러 들어가야 시스템이 점진적으로 똑똑해진다는 이야기였습니다. 하지만 제 시스템에는 이런 루프가 구현되어있지 않습니다.
mermaid 로드 중…
마지막 화살표가 끊겨 있습니다. 사용자가 검색 결과를 보다가 "이 문서는 한화손해보험이 아니라 한화생명 자료다" 라고 오류를 알아챘을 때, 그 신호를 그래프로 흘려보낼 길이 없습니다. 사용자가 직접 organizations.yml 을 편집하고 파이프라인을 다시 돌려야 합니다.
1편에서 저는 글로서리 큐레이션 루프를 사람-기계 협력 루프 라고 적었습니다. 협력은 맞는데, 그 협력의 인터페이스가 YAML 텍스트 편집기와 git commit 메시지 인 상태입니다. 한화 분할이라는 그 중요한 도메인 결정이 시스템 안에 Action 으로 남지 못하고, git log 로 흘러가버렸습니다. 한 달 뒤 누군가 왜 한화가 두 그룹으로 쪼개져 있죠 라고 물으면, 답은 그래프가 아니라 PR 디스크립션을 뒤져야 나옵니다.
write-back 이 없으면 두 가지가 끊깁니다.
- 시스템이 점진적으로 똑똑해지는 경로가 없다. 사용자가 발견한 오류, 누락, 새 별칭이 다음 사이클에 자동 반영되지 않습니다.
- 운영 결정이 시스템 안에 머무르지 않는다. "이 제안서를 우리 회사의 정식 reference case 로 쓴다" 같은 합의가 시스템 외부 (Slack, 회의록) 에 머뭅니다.
3. 모델이 온톨로지에 붙어 있지 않다
Palantir 4편에서 강조한 한 줄, 모델은 객체의 동적 속성으로 자리잡는다. 현재 제 시스템에서 모델 산출물이라 부를 수 있는 건 딱 하나, Document.summary 뿐입니다. 그것도 사실상 정적입니다 - 한 번 생성되고 끝납니다.
그래프 위에 있어야 자연스러울 후보가 많은데도 다 비어 있습니다.
- Organization 의 최근 90일 활성도 점수 (관련 문서 빈도 추세)
- Proposal 의 유사 과거 수주 케이스 Top-3
- Topic 의 모멘텀 (등장 빈도의 1차 미분)
- Document 의 민감도 자동 추정
이게 동적 속성으로 그래프에 자리잡고 있어야, 검색이든 챗이든 어플리케이션이든 자동으로 그 신호를 보게 됩니다. 지금은 챗이 던질 때만 그래프가 응답하는 수동적 자료보관소에 가깝습니다. 의사가 환자 객체를 열면 2년 생존 확률 이 거기 들어 있다는 그 의료 예시 (4편) 와는 반대의 그림입니다.
4. 객체에 상태 가 없다
설계 문서에는 Proposal.status: draft / submitted / won / lost 라는 enum 이 있습니다. 그런데 이건 문서 메타데이터 일 뿐 시스템 안의 상태 머신 이 아닙니다. Palantir 의 Proposal 객체였다면 다음과 같은 것들이 따라왔을 겁니다.
- 상태 전이가
:Action {actor, timestamp, reason}으로 그래프에 기록된다 - 상태에 따라 권한이 달라진다 (
won상태는 reference case 풀에 자동 편입) - 상태 변화가 다른 객체에 이벤트로 전파된다 (
won이 되면 그 RFP 의 다른 후보 Proposal 의 상태가 자동으로lost로)
MeetingMinutes 와 ActionItem 도 마찬가지입니다. 회의록에서 추출된 액션 아이템은 그래프에 한 번 적히고 그걸로 끝납니다. 그 액션이 실제로 완료되었는지, 누가 후속 미팅에서 그걸 어떻게 처리했는지가 시스템 안에서 추적되지 않습니다. 그래프가 회의록의 사본일 뿐 후속 추적의 도구가 되지 못합니다.
5. 검색 시스템이지 어플리케이션 이 아니다
이게 가장 본질적인 차이일 수 있습니다. 지금까지의 1, 2, 3, 4번 결함은 모두 이 부분에서 나옵니다.
- 현재 제 시스템: 사용자가 자연어로 묻고 문서 또는 행 을 돌려받음. 끝.
- Palantir 가 말하는 시스템: 사용자가 객체에서 출발해 분석하고, 결정하고, 그 결정이 시스템에 기록됨.
/chat, /hybrid, /search 세 엔드포인트는 모두 read-only 인터페이스입니다. Quiver 나 Workshop 처럼 한 화면에서 객체에 액션을 걸 수 있는 자리가 없습니다. 그래서 1편과 2편에서 그렇게 공들여 검색 정확도를 끌어올려도, 시스템은 결국 읽는 시스템 에 머뭅니다. 사용자의 일을 대신 처리 하는 단계로는 못 갑니다.
6. 그래서 무엇부터 손볼 것인가
당장 해법으로 떠오른건 Kafka 이벤트 백본 입니다.
위에서 정리한 결함 중 (1) Action 일급화 부재, (2) write-back 없음, (3) 모델이 그래프에 안 붙음, (4) 상태 머신 없음, (5) 어플리케이션 부재 다섯 가지가 사실 한 가지 사실로 환원됩니다. 시스템 안에 이벤트라는 개념이 없다는 겁니다. 폴더 스캔 → 추출 → Neo4j 적재의 단방향 파이프 뒤에 read-only API 가 붙어 있을 뿐이고, 사용자가 무엇을 했는지, 모델이 무엇을 계산했는지, 누가 언제 어떤 결정을 내렸는지가 애초에 데이터 구조에 들어갈 자리가 없습니다.
Kafka 토픽은 immutable append-only 로그이고, 모든 소비자는 그 로그의 projection 입니다. Neo4j 가 진리의 원천 (SSOT) 을 자처할 필요가 없어지고 현재 상태의 materialized view 가 됩니다. 먼저 이 관점으로 부족한 부분을 채워보려합니다.
다음글은 Confluent 와의 결합에 관한 글이 될 것 같습니다.