같은 데이터를 두고도 “조인을 설계하는” 방식과 “관계를 걸어가는” 방식은 실무자가 체감하는 속도와 접근성이 완전히 다릅니다. RDB와 온톨로지 차이를 확인하기 위해, 이 글은 법인카드 한도를 조회하는 흔한 사내 질문 하나를 RDB 조인 방식과 Palantir Foundry 온톨로지 탐색 방식으로 각각 풀어보면서, 온톨로지 탐색이 실제로 무엇을 바꾸는지 구체적으로 비교합니다.
문제 정의: 한 문장 질문, 네 개 테이블
사내 채팅으로 이런 질문이 들어왔다고 가정합니다.
“김민준 사원이 속한 팀의 팀장이 이번 달에 쓸 수 있는 법인카드 한도, 얼마나 남았어?”
일상적인 문장이지만 답을 찾으려면 최소 네 개 테이블을 오가야 합니다.
| 조각 | 필요한 정보 | 테이블 |
|---|---|---|
| 김민준 | 사원 정보, 소속 팀 ID | EMPLOYEE |
| 속한 팀 | 팀 정보, 팀장 ID | TEAM |
| 팀장 | 팀장의 사원 정보(EMPLOYEE를 다시 참조) |
EMPLOYEE(셀프 조인) |
| 법인카드 한도 | 팀장 명의 카드, 이번 달 한도·사용액 | CARD, CARD_LIMIT |
네 조각의 정보를 “관계”로 이어 붙여야 비로소 답이 나오는 질문이라는 점에서, 이 질문은 RDB와 온톨로지의 차이를 보여주는 데 적합한 사례입니다.
RDB 조인 방식: 사람이 경로를 설계한다
출발점 — 5개 테이블 스키마
EMPLOYEE (user_id PK, user_nm, team_id FK)
TEAM (team_id PK, team_nm, leader_id FK → EMPLOYEE)
CARD (card_id PK, holder_id FK → EMPLOYEE, card_type)
CARD_LIMIT (card_id FK, month, limit_amt, used_amt)
관계는 FK 컬럼명에만 존재합니다. “속한다”, “팀장이다”, “카드를 보유한다” 같은 업무적 의미는 스키마 어디에도 문자로 적혀 있지 않고, 개발자가 FK를 보고 유추해야 합니다.
실제로 작성되는 쿼리
SELECT c.card_id,
cl.limit_amt - cl.used_amt AS 잔여한도
FROM employee e
JOIN team t ON e.team_id = t.team_id
JOIN employee mgr ON t.leader_id = mgr.user_id -- 셀프 조인
JOIN card c ON c.holder_id = mgr.user_id
JOIN card_limit cl ON cl.card_id = c.card_id
WHERE e.user_nm = '김민준'
AND cl.month = '2026-08';
한 문장짜리 질문이 4개 JOIN(그중 하나는 셀프 조인)을 가진 쿼리로 번역됩니다. 이 쿼리를 작성하려면 스키마를 아는 사람이 필요하고, “팀장 말고 팀 전체 한도라면?” 같은 질문이 하나만 바뀌어도 조인 경로를 다시 설계해야 합니다.
RDB 방식이 부딪히는 벽
| 문제 | 내용 |
|---|---|
| 스키마 사전 지식 의존 | 테이블명·컬럼명·FK 관계를 모르면 시작조차 불가 — 지식이 특정 인력에게 종속 |
| 질문이 바뀌면 쿼리도 재작성 | “팀장 말고 팀원 전체라면?” — 매번 조인 경로 재설계 |
| 현업 사용자의 직접 접근 불가 | SQL을 모르는 요청자는 IT에 요청 후 대기 |
| 의미의 단절 | ‘법인카드 한도’는 사람의 언어, card_id는 시스템의 언어 — 번역 비용이 계속 발생 |
온톨로지 방식: 질문 그대로 걸어간다
같은 데이터를 온톨로지로 모델링하면
테이블은 Object Type으로, FK는 이름 있는 Link Type으로 바뀌면서 관계에 업무적 의미가 명시됩니다.
- 직원(Employee Object) —[소속팀이다]→ 팀(Team Object)
- 팀(Team Object) —[팀장이다]→ 직원(Employee Object)
- 직원(Employee Object) —[카드를 보유한다]→ 법인카드(Card Object)
- 법인카드 Object의 Property: 이번 달 한도, 사용액, 그리고 파생 Property인 잔여한도(한도 − 사용액)가 객체 안에 한 번만 정의됩니다.
FK 컬럼명 뒤에 숨어 있던 관계가 “소속팀이다·팀장이다·카드를 보유한다”라는 업무 언어로 승격되는 것이 핵심입니다.
조회: 질문의 어순 그대로 탐색
김민준 → 소속팀 → 팀장 → 보유 카드 → 잔여한도
질문 “김민준이 → 속한 팀의 → 팀장이 → 쓸 수 있는 법인카드 한도가 → 얼마나 남았어?”의 어순이 곧 객체 탐색 경로(Traverse)입니다. 조인 경로를 새로 설계하는 대신, 이미 정의된 관계 위를 그대로 걸어가면 됩니다.
이 탐색은 Foundry 안에서 세 가지 방식으로 재사용됩니다.
| 진입 경로 | 특징 |
|---|---|
| Object Explorer | 현업이 클릭만으로 직원→팀→팀장→카드 순서로 탐색, SQL 불필요 |
| Workshop 앱 | 법인카드 현황 대시보드에 동일한 탐색 로직을 위젯으로 재사용 |
| AIP / Agent | 자연어 질문을 온톨로지 경로로 자동 변환해 즉답 |
한눈에 비교
| 비교 항목 | RDB 조인 방식 | 온톨로지 탐색 방식 |
|---|---|---|
| 필요한 사전 지식 | 테이블·컬럼·FK 구조 암기 | 업무 용어(직원·팀·카드)만 알면 됨 |
| 질문 → 답 변환 | 사람이 조인 경로를 설계해 SQL 작성 | 질문의 어순 = 객체 탐색 경로 |
| ‘팀장’ 관계 처리 | 셀프 조인 + 별칭(alias)으로 우회 표현 | ‘팀장이다’ Link Type으로 명시적 정의 |
| ‘잔여한도’ 계산 | 쿼리마다 limit_amt – used_amt 반복 | 파생 Property로 1회 정의, 전사 재사용 |
| 질문 변경 대응 | 쿼리 전면 재작성 | 탐색 경로만 변경(모델 재사용) |
| 주 사용자 | 개발자·DBA | 현업 + 개발자 + AI Agent |
실무 적용 시 고려사항
- 온톨로지는 데이터를 바꾸는 작업이 아니다. 원본 테이블과 파이프라인은 그대로 두고, 그 위에 “질문할 수 있는 언어”를 한 겹 씌우는 작업이다. Ontology Manager에서 Object Type·Link Type을 설계하는 절차는 Ontology Manager 실전 가이드에서 다룬다.
- Link Type 이름이 곧 문서다. manager_id라는 FK 컬럼명 대신 “팀장이다”라는 Link Type 이름을 쓰면, 그 자체가 스키마 문서 역할을 한다. 이름을 대충 지으면 이 이점이 사라진다.
- 파생 Property는 한 번만, 신중하게 정의한다. ‘잔여한도’ 같은 계산식을 Object Type 안에 정의해두면 이후 모든 화면·리포트·AI Agent가 같은 계산 결과를 공유한다. 반대로 계산식이 잘못 정의되면 그 오류도 똑같이 전사에 퍼진다.
- 셀프 조인이 사라지는 게 아니라, 이름을 얻는다. RDB에서 골치 아팠던 셀프 조인(팀장=직원)이 온톨로지에서 없어지는 것은 아니다. 다만 “팀장이다”라는 이름 있는 관계로 명시되면서 매번 별칭(alias)을 헷갈릴 필요가 없어진다.
마무리
RDB 조인과 온톨로지 탐색은 같은 데이터에 대한 두 가지 접근 방식입니다. RDB는 질문을 스키마에 맞게 사람이 번역해야 하고, 온톨로지는 질문의 구조 자체가 이미 탐색 경로가 되도록 관계에 이름을 붙여둡니다. “김민준이 속한 팀의 팀장이 쓸 수 있는 법인카드 한도가 얼마나 남았어?” — 온톨로지에서는 이 문장이 곧 쿼리입니다.
