들어가며: Ontology는 조직을 움직이는 소프트웨어다
Ontology를 잘 설계하는 일은 "데이터를 잘 모델링하는 일"과 다릅니다. Palantir Foundry의 설계 문서는 그 차이를 한 문장으로 못 박습니다.
The Ontology is the software that powers your organization.
Ontology가 조직을 움직이는 소프트웨어라는 뜻입니다. 그래서 문서는 "Ontology를 프로덕션 코드와 같은 주의로 다루되, 완벽보다 비즈니스 가치를 우선하라"는 태도를 권합니다. 이 글은 Foundry의 Ontology 설계 문서 세 편(모범 사례, 구조적 가이드, 안티패턴)을 따라가며, 좋은 Ontology를 만드는 원칙과 흔한 함정을 한국어로 정리한 설계 노트입니다. 핵심 메시지는 일관됩니다. 소스 시스템의 스키마를 베끼지 말고 현실 세계의 개념을 모델링하라.
일곱 가지 설계 가이드라인
문서는 직관적이고 유지보수 가능한 Ontology를 위한 일곱 가지 실천 지침을 제시합니다.
- 현실을 모델링하라, 시스템이 아니라(Model Reality, Not Systems): object type은 소스 시스템이나 부서별 표현이 아니라 현실의 실체를 나타내야 합니다. 여러 소스의 컬럼을 한 object type에 욱여넣는 대신
Patient,WorkOrder,Vessel처럼 별개의 개념으로 모델링합니다. - 의도적으로 큐레이션하라(Curate Intentionally): 모든 property에는 분명한 비즈니스적· 기술적 가치가 있어야 합니다. CSV 컬럼을 1:1로 전부 매핑하지 말고 도메인에 기여하는 필드만 남깁니다.
- 팀을 가로질러 협업하라(Collaborate Across Teams): 사일로화된 팀은 중복의 주된 원인입니다. Sales·Support·Billing이 각자 고객 object type을 만들면 하나의 정본
Customer로 통합합니다. - object type을 좁게 유지하라(Keep Object Types Focused): 각 object type은 하나의 뚜렷한 실체를 나타내야 합니다.
Order에 고객·상품 정보를 컬럼으로 박지 말고Order·Customer·Product로 분리합니다. - 올바른 도구를 골라라(Choose the Right Tool): 인간/에이전트의 결정에는 action type을, 자동 변환에는 파이프라인을 씁니다. 자동 데이터 보정은 파이프라인에, 승인 결정은 action에.
- 추상화에는 interface를 써라(Use Interfaces for Abstraction): 공통 특성을 가진 실체는 넓고 희소한 object type 대신 interface로 추상화합니다.
Arena가Building을 상속하는 대신Building과SchedulableResourceinterface를 둘 다 구현하게 합니다. - 결정을 문서화하라(Document Your Decisions): object type·property·link를 Ontology Manager에서 문서화합니다. 미래의 유지보수자와 추론하는 AI 에이전트 모두를 위해서입니다.
네 가지 핵심 설계 원칙
이 지침들은 네 가지 핵심 원칙으로 압축되며, 우선순위 순으로 제시됩니다.
원칙 1 — 도메인 주도 설계(Domain-Driven Design): 소스 데이터가 아니라 현실 세계를 모델링하라. object는 의미 있는 현실 개념을 나타내야 하고 소스 스키마 변경에 견고해야 합니다. 문서의 대표 예시는 이렇습니다. order_id, customer_name, customer_email, product_sku, quantity 컬럼을 가진 CSV는 다섯 개 property를 가진 하나의 OrderData 타입이 아니라, 서로 링크된 세 object type Order·Customer·Product가 되어야 합니다. 정체성과 관찰을 분리하고(실체 vs 그에 대한 측정값), person.linkedChildPersonObjects보다 person.children처럼 사람을 위한 이름을 쓰며, 의미 없는 기술 유틸리티 타입은 hidden으로 표시해 기본 뷰를 깨끗이 유지합니다.

원칙 2 — 반복하지 말라(Don't Repeat Yourself), 3의 법칙(Rule of Three). 문서의 표현은 "같은 것을 세 번 만들었다면 리팩터링하라"입니다. 한 번의 중복은 우연으로 용인되고, 두 번은 경고이며, 세 번이면 리팩터링 신호입니다. SalesCustomer·SupportCustomer·BillingCustomer는 하나의 Customer로 통합하거나, 형태가 진짜로 다르다면 공유 CustomerBase interface로 묶습니다.

원칙 3 — 확장에는 열려 있고 수정에는 닫혀 있게(Open for Extension, Closed for Modification): 핵심 모델을 보호하고 빌더가 확장하게 하라. 프로덕션에 올라간 object type이나 interface의 핵심은 안정적이어야 하며, 다른 이들은 핵심을 수정하는 대신 새 링크 타입·새 interface 구현·새 property로 확장합니다. Equipment에 인증 추적을 더하려면 property 네 개를 추가하는 대신, 새 Equipment Certification 링크 타입과 새 Certifiable interface를 만듭니다.

원칙 4 — 깊은 상속보다 합성(Composition Over Deep Hierarchies): 다중 상속을 interface로, 플러그인처럼. interface를 통한 다중 상속으로, 단일 상속 체인 대신 여러 초점화된 추상화에서 능력을 합성합니다. Asset → PhysicalAsset → Building → SchedulableBuilding → Arena 같은 깊은 체인 대신, Arena가 Building과 SchedulableResource를 독립적으로 구현하게 합니다. Inspectable·Schedulable·Billable처럼 능력 중심 interface를 설계하고, 워크플로가 interface를 겨냥하게 해 여러 타입에서 수정 없이 동작하게 합니다.

실용주의와 트레이드오프
문서는 이 원칙들이 법이 아니라 지침임을 분명히 합니다. 마감, 레거시 시스템, 부분적 플랫폼 지원, 팀의 숙련도 같은 현실 제약 때문에 이상적 설계가 늘 곧장 가능한 것은 아닙니다. 좋은 설계로 이끌되 장애물이 되지 말고, 지금은 합리적인 것을 만들되 개선 경로를 분명히 두라고 권합니다. 트레이드오프는 명시적으로 이름 붙이고 무엇을 언제 포기하는지 설명합니다(예: "비정규화는 현재 규모에선 동작하지만 1만 object에선 재검토가 필요할 수 있다"). 빅뱅 리팩터링 보다 점진적 개선을 선호하되, 나중에 고치기 어려운 핵심 불변식 — 네이밍 품질, 의미적 명료성, 보안 설계 — 은 끝까지 지키고, 대신 구현 세부에서 타협합니다.
구조적 가이드: 정규화, 파생 속성, 성능
구조적 가이드 문서는 "각 사실을 한 번만 저장하고, 편의를 위해 파생 속성(derived property)을 쓰라"는 원칙에서 출발합니다. 비정규화로 값을 복사하면 소스가 바뀔 때 모든 사본을 갱신해야 하므로, 정규화로 일관성을 지키고 파생 속성으로 편리한 접근을 얻습니다. 예를 들어 managerName을 여러 Employee object에 복사하는 대신, Manager object에 이름을 한 번 저장하고 파생 속성으로 접근합니다.
미리 계산할지 동적으로 파생할지는 입력의 안정성에 달려 있습니다. 입력이 안정적인 값은 파이프라인 변환으로 미리 계산하고(런타임 오버헤드 0), 링크된 object나 action에 의존하는 값은 파생 속성으로 둡니다. 다만 중요한 트레이드오프가 있습니다. action으로 인한 변경에 의존하는 값이라면, 그 값에 영향을 줄 수 있는 모든 action이 그 값도 함께 갱신해야 합니다. 하나라도 누락되면 불일치가 발견될 때까지 값이 틀린 채로 남습니다.
성능 기준선도 구체적입니다. 질의당 약 1만 object 미만의 저~중간 규모에서는 파생 속성을 자유롭게 쓰고, 약 1만 object를 넘어 지연이 보이면 문서화된 근거와 함께 선택적 비정규화를 고려합니다. 5,000명 규모의 인력에는 파생 directReportCount가 안전하지만, 50만 건 트랜잭션에는 집계 카운트를 미리 계산하는 편이 나을 수 있습니다.
구조적 가이드: struct와 reducer, interface, link type
의미적으로 관련된 필드는 별개 property로 평탄화하지 말고 struct로 묶습니다. 주소를 addressStreet·addressCity로 흩지 말고 street·city·state·postal code·geopoint를 담은 하나의 struct로 모델링합니다. struct에는 인터페이스·질의에서 단순 property처럼 동작하도록 main field를 지정하고, 여러 값을 가진 struct property에는 가장 관련성 높은 값을 surface하는 reducer를 씁니다(예: 여러 전화번호 중 대표 번호). LLM이 만든 출력은 신뢰도·근거·출처 같은 메타데이터와 함께 struct로 담는 것이 권장됩니다.
interface는 재사용 가능한 추상화를 만드는 도구입니다. 공유 property·link·action을 담은 interface를 정의하면 여러 object type이 이를 구현하고, interface를 겨냥한 워크플로는 구현하는 모든 타입을 자동으로 지원합니다. interface는 능력 중심(Inspectable, Schedulable)이나 분류 중심(MilitaryAsset, MedicalDevice)으로 설계합니다. 플랫폼 지원이 아직 부족해 일부 워크플로를 타입별로 임시 중복해야 하더라도, interface를 미리 세워두면(scaffold) 지원이 확대될 때 통합 경로가 분명해집니다.
link type은 의미 있는 관계를 나타내야 합니다. dataset이 외래 키를 공유한다는 이유만으로 존재하는 링크는 노이즈입니다. 모든 link type은 "이 환자가 어느 시설을 방문했나?" 같은 분명한 도메인 질문에 답해야 합니다. 관계가 자체 메타데이터(날짜·역할·상태·배분율)를 가진다면 직접 링크 대신 object-backed link type을 씁니다. Employee와 Venture를 직접 잇는 대신 Employee → VentureStaffing → Venture로 모델링하면, VentureStaffing이 role·startDate· allocationPercentage를 담습니다. 문서의 통찰처럼 "모든 연결 object가 모든 맥락에서 보일 필요는 없습니다." 어떤 워크플로는 조인 메타데이터를, 어떤 워크플로는 직접 연결만 원합니다.
구조적 가이드: 네이밍 규칙
이름은 나중에 고치기 가장 어려운 것 중 하나라, 문서는 구체적 규칙을 제시합니다.
- object type: 도메인 전문가가 알아보는 단수·구체 명사. 좋음
Patient·WorkOrder·FlightSegment, 나쁨Data·Item·Record. - property: 타입 정보나 구현 세부를 인코딩하지 않은 간결·자명한 이름. 좋음
age·status·lastInspectionDate, 나쁨dtLastInspMod·nVAL01·fieldX. - link type: 양방향으로 자연스럽게 읽히게. Employee→Department 링크는 직원 쪽에서
department, 부서 쪽에서employees로 읽혀야 하며relatedItems·link1은 피합니다. - 날짜: 한 가지 규칙을 일관되게(
createdDate·updatedDate·effectiveDate),createdDate와dateOfCreation을 섞지 않습니다. - 모호한 용어: 맥락을 한정합니다. 좋음
monetaryValue·quantityOnHand·riskScore, 나쁨value·quantity·score.
핵심은 빌드를 시작하기 전에 날짜·상태·식별자·link type의 규칙에 합의하라는 것입니다. Ontology가 사용된 뒤의 교정은 어렵고 파괴적이기 때문입니다.
구조적 가이드: 보안 설계
보안은 데이터 인프라가 아니라 도메인 용어로, 최소 권한(least privilege) 원칙을 따라 의미적으로 설계합니다. 행 수준 보안(어떤 object를 볼 수 있나)과 열 수준 보안(보이는 object의 어떤 property를 볼 수 있나)을 결합하면 둘의 교집합인 셀 수준 통제가 됩니다. 예를 들어 행 수준으로 주니어 직원에게서 VIP 환자를 숨기고, 열 수준으로 진료팀이 아닌 사람에게서 임상 노트를 숨기면, 선임 진료팀은 모든 환자·모든 property를 보고 주니어는 비VIP 환자의 공개 property만 봅니다.
보안을 이유로 object type을 복제하지 않습니다. PublicPatient와 RestrictedPatient로 쪼개는 대신, 하나의 object type에 잘 설계된 보안 정책을 거는 편이 낫습니다. 복제된 스키마는 시간이 지나며 어긋나기 때문입니다. 기본은 최소 접근으로 시작해 필요에 따라 신중히 넓히고, 보안 경계를 도메인 경계와 정렬합니다(지역 관리자의 뷰는 앱 코드의 필터링이 아니라 "region" 관계에 대한 행 수준 보안으로). 새 링크·타입·property를 추가할 때는 그것이 의도된 보호를 보존하는지 검토 합니다. 예컨대 PublicPatient에서 RestrictedMentalHealthRecords로의 직접 링크는 열 수준 제한을 우회할 수 있어 반드시 검토에서 걸러야 합니다.
여덟 가지 안티패턴
안티패턴 문서는 "처음엔 합리적으로 보이지만 Ontology가 커지며 큰 문제를 만드는" 여덟 가지 함정을 정리합니다. 앞의 원칙들과 거울처럼 대응합니다.
- System Silos(시스템 사일로): 같은 현실 실체를 소스 시스템 출처에 따라 별도 object type으로 만드는 것.
HR System Employee·Badge System Employee·Project Management Employee대신, 세 소스를 병합한 통합 backing dataset(충돌 시 우선순위 규칙 포함) 위의 하나의Employee로. - The Kitchen Sink(부엌 싱크대): 비즈니스 관련성이 없는 기술/외부 시스템 컬럼까지 property로 넣는 것.
Customer는customer_id·customer_name·email만 두고_crm_extracted_at·_crm_sequence·last_etl_update_timestamp같은 기술 메타데이터는 backing dataset에 남깁니다. - Department Silos(부서 사일로): 부서마다 공유 실체의 자기 버전을 만들어 비즈니스 현실이 아니라 조직도를 반영하는 것.
Sales/Support/Billing Customer대신 하나의Customer에salesStatus·supportTier·billingAccountId와 부서별 링크를 둡니다. - The God Object(신 객체): 하나의 object type이 여러 실체를 표현해 다른 property 값에 따라 의미가 달라지고 대부분 null인 것. 트럭·기계·소프트웨어 라이선스·부동산을 한
Asset에 150개 이상의 대부분 null인 property로 담는 대신,Equipment·Vehicle·Software License·Property로 분리하고 공유 특성은Depreciable Assetinterface로. - The Golden Hammer(황금 망치): action type·파이프라인·function 중 하나에 모든 문제를 떠넘기는 것. 예약 처리는 배치 파이프라인, 연속 저지연 데이터는 스트리밍, 사람이 시작하는 결정은 action, 이벤트 반응은 automation, 복잡한 실시간 로직은 function으로 도구를 매칭합니다.
- Action Sprawl(액션 난립): "Set [Property]"·"Update [Property]"처럼 단일 property만 바꾸는 좁은 action을 잔뜩 만드는 것. "이름/성/이메일/전화/부서/매니저 업데이트…" 20여 개 대신, "Update Employee Contact Information"·"Transfer Employee to New Department"처럼 비즈니스 연산 단위로 관련 변경을 묶습니다.
- The Time Machine(타임머신): 실체의 이력 버전을 별도 object나 object type으로 모델링하는 것.
Contract v1/v2/v3나Contract 2023/2024/2025대신, 현재 상태를 가진 하나의Contract를amendmentDate·previousValue·newValue를 담은Contract Amendments에 링크하거나 시계열 property를 씁니다. - The Misnomer(잘못된 이름): object type·property·link에 모호하거나 오해를 부르는 이름을 쓰는 것.
Item→Product/Sales Order Line Item,value→monetaryValue/quantityOnHand,type→productCategory,Item → Related Item→Product → Purchasing Customers처럼 자기 설명적 이름으로 바꿉니다.
마치며
Ontology 설계의 뼈대를 다시 정리하면 다음과 같습니다.
- 출발점은 하나다 — 소스 시스템이 아니라 현실 세계를 모델링하라. 일곱 지침과 네 원칙 (도메인 주도, DRY/3의 법칙, 개방-폐쇄, 합성 우선)이 모두 여기서 나온다.
- 사실은 한 번만 저장하고 편의는 파생 속성으로. 약 1만 object를 넘기면 성능을 보며 문서화된 비정규화를 고려한다.
- 관련 필드는 struct(main field·reducer)로, 공통 능력은 interface로, 메타데이터를 가진 관계는 object-backed link type으로.
- 네이밍과 보안은 빌드 전에 합의·설계한다. 나중에 고치기 가장 어렵기 때문이다. 보안은 도메인 용어로, 최소 권한으로, 행+열 수준을 결합해 설계한다.
- 여덟 안티패턴(System/Department Silos·Kitchen Sink·God Object·Golden Hammer·Action Sprawl· Time Machine·Misnomer)은 네 원칙의 위반 사례이며, 해법은 늘 "현실의 실체로 분리하고, 도구를 맞게 쓰고, 자기 설명적으로 이름 붙이는 것"이다.
이 원칙들을 관통하는 태도는 문서가 처음에 던진 비유 그대로입니다. Ontology를 프로덕션 코드처럼 다루되 완벽이 아니라 비즈니스 가치를 우선하라는 것 — 좋은 설계로 꾸준히 이끌되, 그 자체가 일을 가로막는 장애물이 되지는 말라는 균형입니다.
이 글에서 다루지 못한 세부 주제
설계 문서가 다른 페이지로 연결한 다음 항목은 깊이 다루지 못했습니다. property 기본 타입과 link 카디널리티의 구체, Ontology Manager의 실제 편집·문서화 UI, action type의 부수 효과·검증 규칙 구성, function의 작성 방식, 그리고 ontology scenario·writeback 같은 운영 실행 세부입니다.