온톨로지는 어떻게 "생각"하는가: 추론의 원리
지난 글에서 온톨로지를 이야기하면서 이런 말을 했습니다.
"LLM은 확률적으로 '추측'하지만, 온톨로지는 논리적으로 '증명'한다."
"소크라테스는 사람이다" + "모든 사람은 죽는다" → "소크라테스는 죽는다." 어디에도 직접 적혀 있지 않던 결론이 두 사실로부터 논리적으로 도출됩니다. 그게 온톨로지의 핵심 가치라고 했어요.
그런데 솔직히 그 부분을 좀 얼버무리고 넘어갔습니다. "추론이 핵심이다"라고만 하고, 정작 그 추론이 누가, 어떻게 일어나는지는 안 짚었거든요. 온톨로지가 안 적힌 사실을 찾아내는 "추론"이 실제로 어떤 원리로 돌아가는지, 예시 위주로 이야기해 보겠습니다.

추론을 하는 리즈너(Reasoner)
온톨로지에서 추론을 담당하는 건 리즈너(Reasoner)라는 도구입니다. 주어진 전제(사실과 규칙)만 가지고 결론을 끌어내는, 고지식할 만큼 원칙대로만 따지는 논리 기계예요. 사실 이걸 들여다보고 있으면 예전에 논리학 배우던 시절이 떠오릅니다. "모든 사람은 죽는다, 소크라테스는 사람이다, 따라서 소크라테스는 죽는다" 하던 그 삼단논법이요. 리즈너가 하는 일이 딱 그겁니다.
리즈너에게는 두 가지를 줍니다.
- TBox - 규칙과 정의. "사람은 동물이다", "모든 사람은 죽는다" 같은 세상의 틀.
- ABox - 실제 데이터. "소크라테스는 사람이다" 같은 구체적인 사실.
이 둘을 받으면 리즈너는 명시적으로 적혀 있지 않더라도 규칙상 반드시 따라오는 사실을 도출합니다. "소크라테스는 죽을 수밖에 없는 존재다" 같은 거요. 아무도 입력하지 않았는데 논리적으로 결론에 따라붙는 거죠. (엄밀히는 리즈너가 데이터를 "생성"한다기보다 "이게 참으로 따라온다"라고 밝혀내는 거예요. 이 결과를 실제 데이터로 저장해 두면 materialization이고, 저장하지 않고 질의 시점에 그때그때 계산할 수도 있습니다. 아래에서 더 다룰게요.

리즈너가 하는 일은 크게 세 가지로 나눌 수 있습니다.
1. 분류 (Classification): "이건 사실 저 종류다"
"아메리카노는 커피다"라고만 적었는데, "커피는 음료다"라는 규칙이 있으면 리즈너는 "아메리카노는 음료다"까지 자동으로 압니다. 일일이 "아메리카노도 음료임"이라고 적어줄 필요가 없어요. (정확히 말하면 "아메리카노"라는 클래스가 "커피"의 하위 클래스이고 "커피"가 "음료"의 하위 클래스라면, 어떤 개체가 아메리카노 타입일 때 그 개체는 커피이자 음료라는 것도 리즈너가 알 수 있다는 뜻이에요.)
2. 일관성 검사 (Consistency): "이거 말이 안 되는데?"
예를 들어 온톨로지에 "채식주의자는 고기를 먹는 사람과 양립할 수 없다"는 제약이 명시돼 있고, 삼겹살이 고기로 분류돼 있다고 해볼게요. 이때 "철수는 채식주의자다"와 "철수는 삼겹살을 먹는다"는 데이터가 함께 들어오면, 리즈너가 모순을 감지하고 빨간불을 켭니다. 사람이 일일이 검수하지 않아도 데이터의 모순을 잡아내는 거죠.
여기서 한 가지 짚고 갈 게 있어요. 리즈너가 "채식주의자는 원래 고기 안 먹잖아"라고 상식으로 알아서 판단하는 게 아닙니다. 위처럼 "채식주의자는 고기를 먹을 수 없다"는 제약이 온톨로지 안에 적혀 있어야 모순으로 잡혀요. 안 적어두면 리즈너는 둘이 함께 들어와도 모순으로 보지 않고 그냥 넘어갑니다. (리즈너가 의미를 아는 게 아니라 적어준 규칙만 따진다는 점, 이게 뒤에서도 계속 나올 핵심이에요.)
3. 논리적 귀결 (Entailment): "그럼 이런 것도 참이네"
위에서 본 삼단논법이 여기 해당합니다. 기존 사실 두 개로부터 논리적으로 따라오는 새 사실을 도출하는 것. 추론의 가장 강력한 부분이에요.
자, 그럼 본격적으로 들어가기 전에 큰 그림부터 한 번 잡고 가죠. 사실 "추론"이라는 말 안에는 성격이 전혀 다른 갈래가 여럿 들어 있거든요.
추론에도 세 가지 갈래가 있다: 연역·귀납·가추
논리학에서는 추론을 크게 세 종류로 나눕니다. 세 가지를 같은 상황에 놓고 보면 차이가 확 와닿아요. "비 오는 날, 구내식당에서 김치찌개가 동났다"는 한 장면을 두고 세 추론이 각각 어떻게 작동하는지 봅시다.
연역(Deduction): 규칙에서 확실한 결론으로
"모든 김치찌개에는 김치가 들어간다(규칙). 오늘 메뉴는 김치찌개다(사실). → 따라서 오늘 메뉴엔 김치가 들어간다."
전제가 참이면 결론은 100% 참입니다. 빠져나갈 구멍이 없어요. 앞에서 본 소크라테스 삼단논법, 그리고 이 글에서 다룰 리즈너의 추론(계층·역관계·체인 등)이 전부 이 연역에 속합니다. 온톨로지가 "추측이 아니라 증명한다"라고 할 때의 그 증명이 바로 연역이에요.
귀납(Induction): 관찰을 모아 일반 규칙으로
"지난 10주 동안, 비 오는 날마다 따뜻한 국물 메뉴가 평소보다 많이 나갔다(관찰들). → 비 오는 날엔 국물 메뉴 수요가 늘어난다(일반화)."
여러 사례를 모아 규칙을 뽑아내는 방식입니다. 연역과 달리 항상 맞지는 않아요. 11주 차에 깨질 수도 있죠. 어디까지나 "그럴 확률이 높다"입니다. 데이터에서 패턴을 학습하는 머신러닝, 그리고 지난 글에서 "LLM이 온톨로지 구축을 가속한다"라고 했던 것, LLM이 문서를 잔뜩 읽고 "이런 관계가 있을 법하다"라고 관계의 초안을 제안하는 것이 귀납적 성격이 강합니다. (엄밀히는 LLM의 답변이 항상 귀납만은 아니에요. 때로는 가추, 때로는 단순 패턴 완성처럼 섞여 나오죠. 다만 "사례에서 일반화한다"는 점에서 귀납 쪽에 가깝습니다.)
가추(Abduction): 결과를 보고 가장 그럴듯한 원인으로
"점심시간이 끝났는데 김치찌개가 동났다(결과). → 왜지? 손님이 많았나, 적게 준비했나... 가장 말 되는 설명은, 비가 와서 국물 메뉴로 수요가 몰린 거다(추정)."
결과를 먼저 보고 거꾸로 원인을 추리하는 방식입니다. 결론이 '확실'한 게 아니라 '제일 그럴듯한 설명'이에요. 의사가 증상을 보고 병명을 추정하거나, 셜록 홈즈가 단서로 범인을 좁히는 게 이 가추입니다. 진단이나 근본원인 분석에 쓰여요.
정리하면, 같은 장면을 두고 연역은 "규칙→결론"으로 내려오고, 귀납은 "사례들→규칙"으로 올라가고, 가추는 "결과→원인"으로 거슬러 올라갑니다. 이번 글의 주인공은 첫 번째, 연역입니다. 온톨로지 리즈너가 하는 게 바로 이거니까요. 다만 나머지 둘이 있다는 걸 알아두면, 나중에 "AI가 왜 어떤 건 확신하고(연역) 어떤 건 추측하는지(귀납·가추)"가 훨씬 선명하게 보입니다.
그럼 이제 그 연역이 구체적으로 어떤 규칙들로 일어나는지 하나씩 봅시다.
추론의 기본기: 여섯 가지 패턴
온톨로지 표현 언어(OWL)에는 리즈너가 알아서 적용해 주는 기본 추론 규칙들이 있습니다. 별도 프로그래밍 없이, 그냥 "이 관계는 이런 성질이야"라고 선언만 하면 리즈너가 알아서 사실을 불려줍니다. 자주 쓰이는 여섯 가지만 예시로 보죠.

1) 계층 타고 오르기 (subClassOf의 이행성)
가장 기본입니다. 클래스 사이에 "~의 하위 종류다"라는 관계를 걸어두면, 리즈너가 그걸 끝까지 타고 올라갑니다.
아메리카노 ⊂ 커피 ⊂ 음료
"아메리카노"라는 데이터 하나만 넣어도 리즈너는 이게 커피이자 음료라는 걸 압니다. 그래서 "음료 전부 보여줘"라는 질문에 아메리카노가 자동으로 걸려요. 카테고리가 6단계든 10단계든, 일일이 "이것도 음료, 저것도 음료"라고 적지 않아도 됩니다.
2) 속성에도 계층이 있다 (subPropertyOf)
관계(속성)도 상하 관계를 가질 수 있습니다. 예를 들어 "대표 레시피다"라는 관계를 "레시피다"의 하위 속성으로 정의하면, "이건 대표 레시피"라고만 적어도 "레시피"로 묻는 질문에 같이 잡힙니다. 좁은 의미로 적어도 넓은 의미로 검색되는 거죠.
3) 역방향은 알아서 채워준다 (inverseOf)
이게 은근히 편합니다. 두 관계가 서로 반대 방향이라고 선언해 두면, 한쪽만 적어도 반대쪽이 자동으로 생깁니다.
철수 ──(hasParent)──▶ 영희
여기서 hasParent와 hasChild가 서로 역관계라고 정의해 두면, 리즈너가 알아서 이런 사실을 추가합니다.
영희 ──(hasChild)──▶ 철수
"부모" 방향만 입력해도 "자식" 방향 질문이 다 됩니다. 데이터를 절반만 넣어도 양방향으로 다 조회되는 거죠.
4) 한 방향만 적으면 되는 대칭 관계 (SymmetricProperty)
"~와 짝이 잘 맞는다" 같은 관계는 방향이 없습니다. A가 B와 어울리면 B도 A와 어울리죠.
김치찌개 ──(어울림)──▶ 공기밥
이 관계를 대칭이라고 선언하면, 리즈너가 반대 방향도 자동으로 참으로 만듭니다.
공기밥 ──(어울림)──▶ 김치찌개
한 쌍에 한 줄만 적으면 됩니다.
5) 계단을 끝까지 올라가는 이행 관계 (TransitiveProperty)
"~에 속해 있다", "~의 부분이다" 같은 개체와 개체 사이의 관계도 계속 이어질 수 있습니다. 예를 들어 "어디에 위치한다(locatedIn)"는 관계를 보죠.
강남구 ──(locatedIn)──▶ 서울 ──(locatedIn)──▶ 대한민국
이 locatedIn 관계를 이행적이라고 선언하면, 직접 적지 않은 "강남구 locatedIn 대한민국"까지 리즈너가 도출합니다. 한 칸씩 이어진 관계를 끝까지 타고 가는 거예요.
1번 "계층 타고 오르기"와 헷갈릴 수 있는데, 둘은 적용 대상이 다릅니다. 1번 subClassOf는 클래스끼리의 계층(아메리카노라는 종류가 커피라는 종류에 속함)이고, 5번 TransitiveProperty는 locatedIn·partOf·ancestorOf처럼 개체끼리의 관계(강남구라는 장소가 서울이라는 장소에 속함)에 이행성을 부여하는 거예요. 그래서 5번 예시를 "강남구 ⊂ 서울"처럼 ⊂ 기호로 쓰면 안 됩니다. 그건 클래스 포함이라 1번 얘기가 돼버리거든요.
6) 진짜 마법, 속성 체인 (propertyChainAxiom)
여기가 개인적으로 가장 재미있는 부분입니다. 위의 것들이 "있는 관계를 불려주는" 거라면, 속성 체인은 여러 관계를 엮어서 완전히 새로운 관계를 만들어냅니다.
예를 들어 이렇게 정의할 수 있어요.
"어떤 사람의 부모의 형제는 그 사람의 삼촌이다."
철수 ──(부모)──▶ 영수 ──(형제)──▶ 민수
원래 데이터에는 "철수-부모-영수"와 "영수-형제-민수"만 있습니다. "삼촌"이라는 단어는 어디에도 없어요. 그런데 속성 체인을 정의해두면 리즈너가 이 사실을 도출합니다.
철수 ──(삼촌)──▶ 민수
두 홉(hop)을 건너야 알 수 있던 관계를 한 홉으로 압축해 주는 거죠. 실무에서 이게 왜 강력하냐면, 예를 들어 "이 재료가 어떤 상위 분류에 속하는가"를 계층을 따라 일일이 타고 올라가는 대신, "재료 → 상위분류"를 바로 잇는 지름길을 리즈너가 깔아줍니다. "농산물에 속하는 거 전부"를 물을 때 하위 항목을 하나하나 나열하지 않아도 한 번에 걸리는 식이에요.
관계만 봐도 타입을 안다 (domain / range)
하나 더. 속성에는 "이 관계의 주어는 어떤 종류여야 한다(domain)", "목적어는 어떤 종류여야 한다(range)"를 정해둘 수 있습니다.
"hasCuisine(요리 분류)의 주어는 반드시 레시피다"라고 정의해 두면, 어떤 X가 hasCuisine을 가지는 순간 리즈너는 "아, X는 레시피구나"라고 타입을 추론합니다. 타입을 직접 안 적어도 관계만 보고 알아내는 거죠.
다만 이건 양날의 검입니다. 잘못 정의하면 엉뚱한 타입까지 추론해 버려서, 의도하지 않은 데이터가 줄줄이 딸려 나옵니다. 강력한 만큼 조심해서 써야 하는 기능이에요.
기본기로 안 될 때: 규칙 기반 추론
지금까지 본 여섯 가지는 OWL이 기본으로 제공하는 "공리(axiom)"들입니다. 그런데 도메인이 복잡해지면 이걸로 표현이 안 되는 규칙이 나옵니다. 지난 글에서 들었던 예시를 다시 가져와 볼게요.
"A 약품은 B 성분을 포함한다" + "B 성분은 C 질환 환자에게 금기다" → "A 약품은 C 질환 환자에게 처방하면 안 된다."
이건 단순한 역관계나 이행 관계가 아니라, 조건이 붙은 IF-THEN 규칙입니다. 이런 건 SWRL 같은 규칙 언어로 따로 적어줍니다. (SWRL은 OWL에 규칙 언어를 결합하려는 대표적인 제안인데, 정식 W3C 권고 표준이 아니라 Member Submission 성격이에요. 그래서 제품마다 지원 범위가 다르니 실제로 쓸 땐 확인이 필요합니다.)
IF 약품(?a) ∧ 성분포함(?a, ?b) ∧ 금기성분(?b, ?c)
THEN 처방금지(?a, ?c)
리즈너는 데이터에서 이 조건에 맞는 패턴을 찾으면 결론 부분을 새 사실로 추가합니다. 사람이 "이 약은 이 환자한테 안 돼요"라고 일일이 안 적어도, 규칙 하나로 수만 건의 조합을 자동으로 도출하는 거죠.
헷갈리기 쉬운 지점 하나. 비슷하게 생긴 SHACL이라는 것도 있는데, SHACL Core의 주된 목적은 새 사실을 도출하는 추론이라기보다 검증입니다. OWL/SWRL이 "무엇이 참으로 따라오는가"라면, SHACL은 "이 데이터가 우리가 정한 품질 규칙을 지켰는가"에 가까워요. "이 레시피엔 요리 분류가 반드시 하나 있어야 하는데 비었네?" 같은 걸 잡아내는 역할이죠. (다만 SHACL Rules 같은 확장까지 가면 규칙으로 값을 만들어내는 처리도 가능해요. "SHACL은 절대 추론이 아니다"라고까진 못 하고, 기본 역할이 데이터 품질 검증 쪽이라는 정도로 이해하면 됩니다.) 추론과 검증, 둘 다 온톨로지에서 자주 같이 쓰이지만 목적이 달라요.
추론 엔진은 한 종류가 아니다
지금까지 "리즈너가 추론한다"라고 뭉뚱그렸는데, 사실 그 리즈너가 추론을 굴리는 방식 자체가 여러 갈래입니다. 목적지는 똑같아요. 숨은 사실 찾기. 그런데 거기까지 가는 엔진이 여러 종류고, 각자 잘하는 게 다릅니다. 앞에서 본 여섯 가지 패턴이 "무엇이 추론되는가"였다면, 지금부터는 "어떻게 추론하는가"의 이야기예요. 대표적인 네 가지만 봅시다.

1) 기술 논리(Description Logic, DL) 방식: "모순이 나나 끝까지 따져본다"
아마 "DL"이라는 말을 어디선가 들어보셨을 거예요(Description Logic, 기술 논리). 사실 OWL이라는 언어 자체가 이 기술 논리 위에 세워져 있습니다. 가장 정통이자 표현력이 강한 방식이에요.
이 계열 리즈너는 귀류법과 비슷하게 동작합니다. "이게 거짓이라고 가정해 보자 → 어, 그러면 규칙들이랑 충돌해서 모순이 생기네 → 그러니까 참이다" 하는 식으로 끝까지 따져보는 거죠. 이걸 타블로(tableau) 방식이라고 부릅니다. 복잡하게 얽힌 정의도 다 다룰 수 있지만, 그만큼 계산이 무겁습니다. Pellet, FaCT++ 같은 리즈너가 여기 속하고, HermiT도 이 계열인데 더 정확히는 타블로를 개량한 하이퍼타블로(hypertableau) 방식을 씁니다.
2) 규칙 기반(Rule-based) 방식: "IF-THEN을 계속 적용한다"
앞에서 본 IF-THEN 규칙을 데이터에 반복적으로 적용하면서 새 사실을 불려 나가는 방식입니다. 발상이 단순하고, 무엇보다 대용량 데이터에 강해요. 표현력은 DL보다 제한적이지만 빠르고 결과가 예측 가능해서, 실무에서 가장 흔하게 쓰는 축입니다.
이 방식과 짝을 이루는 게 OWL 2 RL 프로파일이에요. 이름의 RL이 아예 Rule Language에서 왔는데, "규칙 엔진으로 구현하기 쉽도록" 표현력을 잘라낸 버전이거든요. 표준 안에 "A subClassOf B이고 B subClassOf C이면 A subClassOf C" 같은 IF-THEN 규칙이 정의돼 있고, 리즈너는 이걸 더 이상 새 사실이 안 나올 때까지 반복 적용합니다. Neptune, GraphDB, RDFox 같은 그래프·규칙 엔진에서 바로 돌릴 수 있어서, 대량 데이터 추론이 필요할 때 현실적으로 가장 먼저 손이 가는 선택이에요.
3) 질의 재작성(Query Rewriting) 방식: "추론을 질문 쪽에 심는다"
이건 발상이 재미있어요. 데이터에 추론된 사실을 미리 채워 넣는 대신, 질문 자체를 추론까지 포함하도록 다시 쓴 다음 원본 데이터에 던집니다. "음료 줘"라는 질문을 리즈너가 내부적으로 "음료이거나, 커피이거나, 아메리카노인 것 줘"처럼 자동 확장해서 처리하는 식이죠. 데이터가 어마어마하게 크고 자주 바뀌어서 미리 추론해 박아두기가 부담스러울 때 유리합니다.
4) 결과 기반(Consequence-based) 방식: "거대한 분류 체계 전용"
분류 계산(무엇이 무엇의 하위인지)에 특화돼서, 말도 안 되게 큰 온톨로지도 빠르게 처리하는 방식입니다. 지난 글에서 언급한 의료 표준 온톨로지 SNOMED CT가 수십만 개념 규모인데, 이런 걸 다루는 ELK 같은 리즈너가 이 계열이에요.
눈치채셨을 수도 있는데, 이 방식들은 OWL의 "프로파일"과 짝을 이룹니다. OWL에는 표현력을 일부러 제한한 버전들이 있어요. 풀 사양(OWL DL)은 위의 1번 방식으로 뭐든 다 추론하지만 무겁고, RL·EL·QL 같은 프로파일은 표현력 일부를 포기하는 대신 각각 규칙 기반·결과 기반·질의 재작성 방식으로 빠르게 돕니다. 어느 게 정답이라기보다, 내 데이터가 얼마나 크고 / 얼마나 복잡하고 / 얼마나 자주 바뀌느냐를 보고 고르는 거예요.
언제 추론할까: 미리 vs 그때그때
여기서 실무적으로 중요한 갈림길이 하나 있습니다. 이 추론을 언제 돌릴 거냐는 문제예요. 크게 두 방식입니다.

전방 추론 (Forward chaining / Materialization)
데이터가 들어오는 시점에 미리 추론을 다 돌려서, 도출된 사실을 실제 트리플로 저장해 둡니다. "삼촌" 관계를 미리 다 계산해서 박아두는 거죠. 나중에 질문이 들어오면 이미 계산돼 있으니 조회가 빠릅니다. 대신 저장 공간을 많이 먹고, 원본 데이터가 바뀌면 다시 계산해야 해요.
후방 추론 (Backward chaining)
평소엔 도출된 사실을 저장하지 않다가, 질문이 들어오는 순간 그 자리에서 추론합니다. 저장 공간은 아끼지만, 질문할 때마다 계산하니 응답이 느려질 수 있어요.
현장에서 느낀 것 하나. 상용 그래프 데이터베이스 중에는 질의 시점에 추론을 해주지 않는 제품이 꽤 있습니다. 그러면 선택지는 사실상 하나예요. 데이터를 적재하는 빌드 단계에서 리즈너를 한 번 돌려서, 도출된 사실(역관계·대칭 관계·계층 롤업 등)을 미리 다 만들어 그래프에 박아 넣는 겁니다. 그래야 실제 질의는 추론 없이도 빠르게 답하거든요. "추론은 빌드 때 미리, 조회는 가볍게"가 현실적인 타협점인 경우가 많았습니다.
그런데 무거운 리즈너, 현실에서 어디에 쓸까
여기서 솔직한 이야기를 하나 하고 싶어요. 앞에서 "타블로(DL) 방식은 표현력이 강하지만 무겁다"라고 했는데, 이 "무겁다"가 생각보다 심각합니다. 표현력이 강한 추론은 최악의 경우 계산량이 지수적으로 늘어나요. 데이터가 조금만 커져도 시간과 메모리가 감당이 안 되는 수준으로 튑니다. 실제로 대량 데이터에 HermiT 같은 리즈너를 돌리려고 하면, 끝나기를 기다리다 포기하게 되는 경우가 흔해요.
그럼 이런 무거운 리즈너는 아무도 안 쓰느냐? 그건 아닙니다. 쓰는 자리가 다를 뿐이에요. 이걸 구분 못 하면 엉뚱한 데 갖다 쓰고 "왜 안 돌아가지?" 하게 됩니다.
이럴 때 쓴다: 온톨로지를 "설계하고 검증"하는 단계
HermiT·Pellet 같은 리즈너는 대량 데이터 처리기가 아니라, 온톨로지 스키마(TBox)를 점검하는 도구로 쓰입니다. 온톨로지 편집기(Protégé 같은)에 기본으로 들어 있어서, 설계자가 버튼 하나로 "내가 짠 공리에 모순은 없나?", "이 클래스 계층이 의도대로 분류되나?"를 확인해요. 스키마는 규모가 작고(수천 개 개념 수준) 자주 바뀌지도 않으니, 여기선 무거운 리즈너도 몇 초에서 몇 분이면 끝납니다. 표현력이 강한 만큼 복잡한 정의의 정합성까지 꼼꼼히 잡아주니, 이 자리에선 제값을 해요.
이럴 때는 안 쓴다: 대량 데이터에 실시간 추론
반대로 실제 인스턴스 데이터(ABox)가 수백만 건인데 거기에 풀 DL 리즈너를 돌리는 건 아무도 안 합니다. 안 돌아가니까요. 이 자리는 앞에서 본 대로 가벼운 규칙 기반(OWL RL) + 빌드타임 materialization, 또는 질의 시점 경로 탐색으로 갑니다.
그래서 현장의 실제 패턴은 역할을 나누는 거예요. 설계 단계에서는 스키마를 무거운 리즈너로 한 번 힘들게 검증하고(모순·분류 확인), 운영 단계에서는 검증이 끝난 그 스키마 위에서 대량 데이터를 가벼운 방식으로 처리합니다. "정합성 검증은 무거운 리즈너, 대량 처리는 가벼운 엔진"으로 나눠 쓰는 거죠.
덧붙이면, 사실 현업 온톨로지의 상당수는 애초에 HermiT가 필요할 만큼 복잡한 표현력을 쓰지 않습니다. 그런 무거운 추론이 꼭 필요하다면, 그건 문제를 푸는 데 정말 필요해서라기보다 온톨로지를 과하게 설계한 신호일 때도 많아요. 지난 글에서도 짚었듯, 완벽한 지식 체계를 만들려다 비대해져서 실패하는 게 흔한 함정이거든요. 풀려는 문제에 딱 필요한 만큼만. 이게 표현력을 고를 때의 기본기예요.
안 적힌 건 "거짓"이 아니라 "모름": 열린 세계 vs 닫힌 세계
엑셀이나 데이터베이스를 쓰던 분이 온톨로지를 처음 만지면, 거의 다 여기서 한 번 걸려 넘어집니다. 짚고 갈게요.
데이터베이스는 닫힌 세계 가정(CWA, Closed World Assumption) 위에서 돕니다. 한마디로 "내 데이터에 없으면 = 없는 것, 거짓"이에요. 항공 예약 시스템에서 승객 명단에 철수가 없으면? "철수는 이 비행기 안 탐"으로 단정합니다. 명단이 곧 세상의 전부니까요.
그런데 온톨로지(OWL)의 기본값은 정반대인 열린 세계 가정(OWA, Open World Assumption)입니다. "내 데이터에 없으면 = 거짓이 아니라, 그냥 모름."
예를 들어 "철수가 땅콩 알레르기다"라는 기록이 없다고 해볼게요.
- 닫힌 세계(DB식): "기록이 없으니 철수는 땅콩 알레르기가 아니다." (단정)
- 열린 세계(온톨로지식): "철수가 땅콩 알레르기인지 아닌지 모른다." (보류)
왜 굳이 이렇게 설계했을까요? 세상의 지식은 늘 불완전하기 때문이에요. 안 적혀 있다고 거짓이라 단정하면 위험합니다. 특히 알레르기 같은 안전 문제에서 "기록 없음 = 안전함"으로 처리했다간 큰일 나죠. 그래서 온톨로지는 함부로 단정하지 않고 "모른다"로 남겨둡니다.

이게 바로 초보자가 "왜 이 당연한 걸 추론 안 해주지?" 하고 한참 헤매는 지점이에요. "이 사람은 채식주의자라고 명시 안 했으니 아닌 거 아냐?"라고 기대하지만, 열린 세계의 리즈너는 단정하지 않고 "모릅니다"라고만 답하거든요.
비슷한 함정이 하나 더 있습니다. 이름이 다르다고 다른 존재라고 단정하지도 않아요. 데이터베이스에서는 보통 철수_ID_1과 민수_ID_2처럼 ID가 다르면 다른 사람이라고 봅니다. 그런데 OWL은 그렇게 단정하지 않아요. 철수와 김철수가 서로 다른 이름(URI)이라도, "이 둘은 다른 사람이다"라고 명시하지 않았다면 리즈너는 둘이 같은 사람일 가능성을 열어둡니다. 정말 다르다고 말하고 싶으면 differentFrom 같은 걸로 "이 둘은 서로 다른 개체다"라고 적어줘야 해요. ("기록에 없으면 모름"과 한 짝인 셈이죠. 둘 다 "함부로 단정하지 않는다"는 같은 철학에서 나옵니다.)
그럼 "이 목록이 전부다"라고 확실히 닫고 싶을 땐? 그땐 명시적으로 닫아줘야 합니다. "이 환자의 알레르기는 이 셋이 전부다"라고 선언하거나, 검증 도구(앞서 나온 SHACL)로 "이 칸은 비어 있으면 안 된다"를 강제하는 식으로요. 열린 세계가 기본이되, 필요한 곳만 골라서 닫는 겁니다.
참고로 여기서 비단조 추론(non-monotonic reasoning) 같은 가지가 더 뻗어 나갑니다. 보통의 논리 추론은 사실이 추가될수록 결론도 쌓이기만 하는데(단조), 비단조 추론은 새 사실이 들어오면 기존 결론이 뒤집힐 수도 있어요. "정보가 없으니 일단 영업한다고 가정" → 나중에 "휴무" 사실이 들어오면 그 결론을 철회하는 식이죠. 깊이 들어가면 한 편이 따로 나오는 주제라 여기선 언급만 해둘게요.
공짜가 아니다: 현실적인 주의점
추론이 강력하다고 다 추론으로 풀면 안 됩니다. 몇 가지 함정이 있어요.
첫째, 추론은 비싸다.
방금 본 것처럼 표현력이 강할수록 계산이 무거워집니다. 그래서 "무조건 강력한 추론"이 아니라 풀려는 문제에 딱 필요한 만큼의 표현력(적절한 프로파일)을 고르는 게 핵심이에요. 모든 추론을 다 지원하려다 영영 답이 안 나오는 것보다, 필요한 추론만 빠르게 도는 게 낫습니다.
둘째, 공리 하나가 전체를 오염시킨다.
추론은 사실을 자동으로 불려주기 때문에, 잘못된 규칙 하나를 넣으면 그게 연쇄적으로 퍼져서 엉뚱한 사실이 잔뜩 생깁니다. 강력한 만큼 위험해요. 그래서 추론 결과를 무작정 믿기보다, 이 사실이 왜 도출됐는지 추적 가능하게 만들어두는 게 중요합니다. (어떤 규칙이 어떤 추론을 만들었는지 기록해 두면 나중에 "이게 왜 여기 있지?"를 되짚을 수 있습니다.)
셋째, 전부 추론으로 풀 필요는 없다.
어떤 사실은 그냥 명시적으로 적어두는 게 더 명확하고 빠릅니다. "추론으로 도출 가능하니까 안 적어도 돼"가 항상 정답은 아니에요. 무엇을 추론에 맡기고 무엇을 직접 적을지 가르는 것 자체가 설계의 영역입니다.
마무리: "아마 안 들어갈걸요" vs "근거를 댈 수 있습니다"
다시 처음으로 돌아가 볼게요.
"이 메뉴에 땅콩 들어가나요?"라는 한 질문을 두고, LLM과 리즈너는 전혀 다르게 대답합니다.
- LLM: "음... 메뉴 이름을 보니 아마 안 들어갈 것 같은데요?" (이름에서 통계적으로 추측)
- 리즈너: "들어갑니다. 이 메뉴는 재료로 땅콩소스를 쓰고, 그 땅콩소스 자재가 땅콩을 포함하기 때문입니다." (논리적 증명 + 근거 경로)
둘 다 같은 답을 낼 수도 있어요. 하지만 결정적인 차이는, 리즈너는 왜 그 결론이 나왔는지 한 단계씩 되짚어 보여줄 수 있다는 점입니다. 더구나 알레르겐처럼 틀리면 사람이 다치는 문제에서, "아마"는 답이 될 수 없죠. 지난 글에서 말한 "블랙박스 문제"를 푸는 열쇠가 바로 이거예요. 임원이 "근거가 뭐야?"라고 물었을 때, "인공신경망 가중치 계산 결과입니다"가 아니라 논리 체인을 펼쳐 보일 수 있는 거죠.
물론 현실에서는 LLM과 온톨로지를 대립시키기보다 둘을 합쳐 쓰는 방향으로 갑니다. LLM이 자연어를 이해하고, 온톨로지가 그 이해를 사실로 붙잡아주는 식으로요.
추론이라는 게 결국 "안 적힌 걸 규칙으로 찾아내는 것"이라는 점만 손에 쥐고 있으면, 나머지는 그 규칙의 종류일 뿐입니다.
'Tech & Development > AI' 카테고리의 다른 글
| 온톨로지(Ontology) - AI 시대에 왜 다시 주목받는가 (1) | 2026.05.08 |
|---|---|
| Claude Managed Agents 출시 - 직접 살펴본 첫인상 (0) | 2026.04.12 |
| Claude Code 완벽 가이드 (5) - 자동화와 자율 에이전트 (0) | 2026.04.10 |
| Claude Code 완벽 가이드 (4) - Skills와 Plugins, 패키지의 시대 (0) | 2026.04.09 |
| Claude Code 완벽 가이드 (3) - 숨겨진 키워드와 Ultraplan, 그리고 미공개 기능들 (0) | 2026.04.08 |
댓글
이 글 공유하기
다른 글
-
온톨로지(Ontology) - AI 시대에 왜 다시 주목받는가
온톨로지(Ontology) - AI 시대에 왜 다시 주목받는가
2026.05.08 -
Claude Managed Agents 출시 - 직접 살펴본 첫인상
Claude Managed Agents 출시 - 직접 살펴본 첫인상
2026.04.12 -
Claude Code 완벽 가이드 (5) - 자동화와 자율 에이전트
Claude Code 완벽 가이드 (5) - 자동화와 자율 에이전트
2026.04.10 -
Claude Code 완벽 가이드 (4) - Skills와 Plugins, 패키지의 시대
Claude Code 완벽 가이드 (4) - Skills와 Plugins, 패키지의 시대
2026.04.09