관점 에세이 · 2026-08-26

RDF/OWL로 다 표현할 수 있는데, 왜 SKOS와 PROV가 따로 있을까

표현할 수 있다는 것과, 표현해도 된다는 것은 다른 문제였다

ontology

PROV와 SKOS를 보다가 의문이 생겼다. 둘 다 RDF 위에서 동작하고, PROV-O는 아예 OWL 온톨로지로 정의돼 있다. 그런데 왜 굳이 따로 표준을 만들었을까. 결국 RDF/OWL로 다 표현할 수 있는 것 아닌가.

Entity, Activity, Agent 같은 클래스를 내가 직접 OWL로 정의하고, broader나 narrower 같은 관계도 내 온톨로지에 property로 얹으면 그만 아닌가 싶었다. RDF는 트리플이고 OWL은 그 위에 얹는 어휘일 뿐이니, 새 어휘가 필요하면 내가 만들면 되는 것 같았다.

이 가정에는 숨은 전제가 있었다. "표현할 수 있는 관계는 표현력을 다 써서 정의해도 안전하다"는 전제다. SKOS와 PROV-O를 자세히 보니 이 전제부터 틀렸다.


SKOS는 subClassOf를 쓸 수 있는 구조가 아니었다

SKOS(Simple Knowledge Organization System)는 시소러스나 분류체계, 주제명표목표 같은 걸 RDF로 표현하는 어휘다. 핵심 관계는 skos:broader와 skos:narrower다. "포유류"가 "동물"보다 broader라거나, "파리"가 "일드프랑스"보다 narrower라는 식이다.

처음엔 "그냥 subClassOf를 안 쓰기로 한 것"이라고 생각했다. 다시 보니 안 쓴 게 아니라 애초에 쓸 수 없는 구조였다. SKOS에서 "포유류"나 "파리" 같은 개별 개념은 skos:Concept라는 클래스의 인스턴스로 선언된다. OWL 관점에서는 클래스가 아니라 개별자(individual)다. rdfs:subClassOf는 클래스와 클래스 사이의 관계라서, 인스턴스인 두 개념 사이에 그대로 쓸 수 없다.

subClassOf를 쓰려면 "포유류"와 "동물"을 skos:Concept의 인스턴스가 아니라 각자 OWL 클래스로 다시 선언해야 한다. 이건 같은 것에 다른 이름표를 붙이는 정도의 일이 아니다. 하나의 자원을 클래스이면서 동시에 인스턴스로 다루는 걸 펀닝(punning)이라고 부르는데, OWL 1에서는 아예 금지돼 있었다. 클래스와 개별자는 서로 겹치지 않아야 한다는 제약이 있었기 때문이다. OWL 2에서 펀닝이 허용되긴 하지만, 그렇게 쓰면 온톨로지는 OWL Full 영역으로 밀려난다. RL도 DL도 아닌, 프로파일 계층 바깥이다.

그러니까 SKOS가 개념을 인스턴스로 설계한 순간, subClassOf는 선택지에서 빠졌다. 그리고 이 설계는 결과적으로 SKOS를 잘 정돈된 추론 영역 안에 붙잡아뒀다. PROV-O가 표현은 다 갖추고도 RL 프로파일 밖으로 안 나간 것과 같은 종류의 절제다.

설령 개념을 클래스로 설계했다고 해도 문제가 남는다. 실제 분류체계의 broader 관계는 늘 같은 종류가 아니기 때문이다. "파리 broader 일드프랑스"는 부분-전체에 가깝고, "포유류 broader 동물"은 상하위 개념에 가깝다. 같은 broader라는 이름 아래 서로 다른 관계가 섞여 있다.

이 지점을 실제로 따라가 보면 이렇다. 어느 신체 부위 분류체계에 이런 관계가 있다고 하자.

손가락 broader 손
손 broader 팔

만약 concept가 클래스였고 broader가 subClassOf처럼 전이적으로 정의돼 있었다면, RDFS reasoner는 규칙 하나로 전이적 폐포를 계산했을 것이다.

x subClassOf A
A subClassOf B
----------------
x subClassOf B

여기 대입하면 "손가락 subClassOf 팔"이 나온다. 손가락은 손의 부분이고 손은 팔의 부분이니, 이 결론은 맞다. 문제는 관계가 "부분-전체"와 "상하위 개념"이 섞인 사슬로 이어질 때다. "테니스공 broader 스포츠용품, 스포츠용품 broader 상품"이라는 사슬에서, 테니스공은 스포츠용품의 일종(상하위)이고 스포츠용품은 상품의 일종(상하위)이라 이 사슬도 맞다. 하지만 실제 분류체계 데이터에는 이 두 종류가 예고 없이 섞여 들어오고, 편집자가 매번 어느 종류인지 구분해서 입력하지 않는다. SKOS는 그 구분을 강제하지 않은 채로 방대한 기존 시소러스 데이터를 RDF로 옮겨야 했다. 그런 데이터 위에서 전이성까지 자동으로 켜두면 검증되지 않은 사슬에서 검증되지 않은 결론이 계속 새로 생긴다. broader/narrower를 비전이적으로 남긴 SKOS의 선택은, 개념을 인스턴스로 둔 첫 번째 절제와 같은 방향을 가리킨다. RDF/OWL이 표현을 못 해서가 아니라, 표현력을 다 쓰면 데이터에 없던 결론까지 자동으로 따라 나오거나 추론 자체가 정돈된 영역을 벗어나기 때문에, 일부러 부분집합에 머문 것이다.


PROV-O는 OWL이면서 스스로 RL 안에 머문다

PROV-O는 다르다. Entity, Activity, Agent가 실제 OWL 클래스로 정의돼 있고, wasGeneratedBy, used, wasAssociatedWith 같은 관계도 OWL property로 선언돼 있다. SKOS와 달리 표현을 약하게 만들지 않았다.

대신 다른 선택을 했다. PROV-O 명세는 스스로 "다섯 개 공리를 제외하면 OWL 2 RL 프로파일을 따른다"고 밝힌다. 클래스와 관계를 정의할 표현력은 다 썼지만, 그 정의들이 만들어내는 추론의 난이도는 거의 전부 RL 수준에 묶어뒀다는 뜻이다. Full DL이 지원하는 복합 클래스 정의나 cardinality 제약을 거의 안 쓴다.

이유는 SKOS와 다르다. SKOS는 잘못된 추론을 막으려고 표현을 줄였다. PROV-O는 틀린 추론이 나올 위험보다는, 대규모 provenance 기록을 실시간으로 쌓고 조회해야 하는 운영 환경에서 추론 비용이 감당 안 되는 게 더 큰 문제였다. 표현은 다 갖추되, 그 표현이 요구하는 계산은 예측 가능한 수준으로 눌러둔 것이다.

실제로 흔히 나오는 provenance 기록은 이런 모양이다.

Report1 wasGeneratedBy Activity1
Activity1 used Dataset1
Activity1 wasAssociatedWith Agent1

이 세 트리플에서 "Report1을 누가, 무엇으로 만들었나"를 묻는 건 그래프를 한두 hop 따라가는 조회다. cardinality 제약이나 복합 클래스 정의 없이도 답이 나온다. PROV-O가 Full DL의 표현력을 아예 안 쓴 건 아니지만, 실제로 쓰이는 관계 대부분이 이런 단순한 hop 조회로 충분하다는 걸 알고 있었기 때문에, 다섯 개 예외를 빼고는 RL 수준에 스스로 묶어둔 것이다.


표준이 아니라 내 온톨로지라면

SKOS와 PROV-O는 이미 정해진 표준이니 그 설계를 보고 배우면 그만이다. 문제는 내가 새 관계를 하나 정의할 때다. "이 조항은 이 조건을 requires한다"거나 "이 문서는 저 문서를 supersedes한다" 같은 관계를 만들 때, 그 관계를 rdfs:subClassOf에 가깝게 강하게 정의할지, skos:broader처럼 약하게 둘지를 매번 판단해야 한다. SKOS와 PROV-O를 보기 전에는 이 판단 기준 자체가 없었다. "일단 표현할 수 있으면 정의부터 하고 본다"는 게 기본값이었다.


두 표준이 같은 결론에 도착했다

SKOS는 관계 자체를 약하게 만들었고, PROV-O는 관계는 정의대로 두되 추론 프로파일을 제한했다. 방법은 다르지만 이유는 같은 자리에서 나온다. RDF/OWL의 표현력을 끝까지 다 쓰면, 어딘가에서 틀린 결론이 자동으로 따라 나오거나 계산이 감당 안 되는 지점이 나온다는 것이다.

"표현할 수 있다"와 "그 표현을 끝까지 써도 된다"는 다른 질문이었다. RDF/OWL이 부족해서 SKOS와 PROV가 따로 생긴 게 아니라, RDF/OWL이 표현할 수 있는 것 중에서 어디까지 실제로 쓸지를 각자 다른 이유로 골라낸 결과가 SKOS와 PROV였다.

처음 질문으로 돌아가면, "RDF/OWL로 다 표현할 수 있는데 왜 따로 표준이 있을까"는 절반만 맞는 질문이었다. 표현할 수 있다는 전제는 맞다. 문제는 그다음이었다. 표현할 수 있는 걸 전부 쓰면 무슨 일이 생기는지를 안 물어본 채로, 표현 가능성만 보고 "그러니 필요 없다"고 결론 내리려 했다. SKOS와 PROV-O는 그 다음 질문까지 이미 답해둔 표준이었다.

그러면 그 선택의 기준이 뭔지가 다음 질문이 된다. SKOS는 전이성을 버렸고 PROV-O는 추론 프로파일을 제한했는데, 둘 다 결국 OWL 안에 있는 두 계약, 규칙으로 풀리는 추론과 논리식으로 풀리는 추론 중 하나를 고른 것이었다. 이 두 계약이 정확히 어떻게 다른지가 다음 편의 주제다.


OWL 2의 프로파일 이름

PROV-O가 머물렀다는 "OWL 2 RL"과, 다음 편에서 다룰 "OWL 2 DL"은 줄임말이다. OWL 2는 표현력과 추론 비용을 다르게 맞바꾼 프로파일 네 개로 나뉘는데, 이름에 그 성격이 그대로 들어 있다.

  • DL: Description Logic. 클래스를 논리식으로 정의하고, 그 정의가 참인지 계산하는 쪽.

  • RL: Rule Language. 규칙 엔진으로 구현하도록 설계된 쪽. PROV-O가 스스로 묶어둔 프로파일이다.

  • EL: Existential Language. 클래스 계층이 아주 큰 도메인(생명과학 온톨로지 등)에 맞춘 프로파일.

  • QL: Query Language. SQL 같은 관계형 DB 질의로 답할 수 있도록 설계된 프로파일.

이 시리즈에서 실제로 다루는 건 RL과 DL 두 개다. EL과 QL은 각자 다른 트레이드오프(대규모 계층, DB 연동)를 노린 프로파일이라 여기서는 이름만 적어둔다.