“우리 데이터를 구조화하자”는 말에는 서로 다른 세 가지가 섞여 있습니다. 용어를 정리하자는 것일 수도, 계층을 만들자는 것일 수도, 기계가 추론할 수 있게 만들자는 것일 수도 있습니다. 각각 필요한 노력과 얻는 것이 완전히 다릅니다.
이 글은 그 층위를 나누고, 교육 도메인을 예로 어디까지 갈지 판단하는 기준을 정리합니다.
1. 온톨로지란 무엇인가
가장 많이 인용되는 정의는 Gruber의 것입니다.
온톨로지는 개념화(conceptualization)에 대한 명시적 명세(explicit specification)다.
풀어 쓰면 이렇습니다. 어떤 도메인을 다루는 사람들의 머릿속에는 암묵적인 합의가 있습니다. “선수과목”이 무엇인지, “이수”와 “수강”이 어떻게 다른지 대충 압니다. 온톨로지는 그 암묵적 합의를 기계가 읽을 수 있게 적어 놓은 것입니다.
핵심은 명시적이라는 부분입니다. 사람이 읽고 이해하는 문서가 아니라, 기계가 검증하고 추론할 수 있는 형식이어야 합니다.
표현력의 층위
“구조화”라는 말이 가리킬 수 있는 단계들입니다. 아래로 갈수록 표현력이 커지고 구축 비용도 커집니다.
| 단계 | 담는 것 | 예시 | 할 수 있는 일 |
|---|---|---|---|
| 용어 목록 | 단어들 | 과목, 학점, 전공 | 검색어 통일 |
| 분류체계(Taxonomy) | 상하위 관계 | 전공 > 전공필수 | 상위 개념으로 묶어 조회 |
| 시소러스(Thesaurus) | + 동의어, 관련어 | “자료구조” ≈ “Data Structure” | 질의 확장 |
| 온톨로지 | + 관계 종류, 제약, 공리 | 선수과목(자료구조, 프로그래밍기초)선수과목은 이행적 |
추론, 정합성 검증 |
대부분의 실무 요구는 시소러스 단계에서 이미 해결됩니다. 온톨로지까지 가야 하는 경우는 관계를 타고 추론해야 할 때입니다.
선수과목 관계가 이행적(transitive)이라고 선언해 두면
선수과목(자료구조, 프로그래밍기초)
선수과목(알고리즘, 자료구조)
──────────────────────────────── 자동 추론
선수과목(알고리즘, 프로그래밍기초) ← 아무도 적지 않았지만 참
이런 추론이 필요 없다면 온톨로지 비용을 치를 이유가 없습니다.
2. 표준 스택 — 어디까지 쓸 것인가
RDF — 모든 것은 트리플이다
RDF(Resource Description Framework)는 지식을 주어-술어-목적어 세 칸으로 표현합니다.
@prefix ex: <http://example.org/edu#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
ex:CS201 ex:과목명 "자료구조" .
ex:CS201 ex:학점 3 .
ex:CS201 ex:선수과목 ex:CS101 .
ex:CS201 ex:개설학과 ex:컴퓨터공학과 .
트리플이 모이면 그래프가 됩니다.
ex:컴퓨터공학과
▲
│ 개설학과
│
ex:CS101 ◄────ex:CS201────► "자료구조"
선수과목 과목명
모든 것에 URI를 붙인다는 게 RDF의 핵심입니다. ex:CS201 은 문자열이 아니라 전역 식별자이므로, 다른 데이터셋의 같은 URI와 자동으로 연결됩니다.
RDFS — 최소한의 스키마
클래스와 속성, 그리고 상하위 관계를 선언합니다.
ex:전공필수과목 rdfs:subClassOf ex:과목 .
ex:선수과목 rdfs:domain ex:과목 ;
rdfs:range ex:과목 .
rdfs:domain 과 rdfs:range 는 제약이 아니라 추론 규칙입니다. 이게 RDFS에서 가장 헷갈리는 지점입니다.
ex:GE100 ex:선수과목 ex:GE050 .
ex:GE100 이 과목이라고 아무도 선언하지 않았어도, domain 선언 때문에 추론 엔진은 “아, 그러면 GE100은 과목이겠구나” 하고 타입을 추가합니다. 오류를 내는 게 아니라 사실을 늘립니다.
이것이 개방 세계 가정(Open World Assumption) 입니다. 적혀 있지 않은 것은 거짓이 아니라 미지입니다. RDB의 NOT NULL 처럼 동작할 거라 기대하면 반드시 배신당합니다.
OWL — 추론을 위한 표현력
관계의 성질과 논리적 제약을 선언합니다.
ex:선수과목 a owl:TransitiveProperty . # 이행적
ex:동일과목 a owl:SymmetricProperty . # 대칭적
ex:개설학과 a owl:FunctionalProperty . # 값이 하나뿐
ex:전공필수과목 a owl:Class ;
rdfs:subClassOf [
a owl:Restriction ;
owl:onProperty ex:이수구분 ;
owl:hasValue ex:필수
] .
OWL은 강력하지만 비싸고 위험합니다. 표현력이 올라갈수록 추론 비용이 급격히 늘고, 실수했을 때 엉뚱한 사실이 대량으로 생성됩니다. 실무에서는 owl:TransitiveProperty, owl:inverseOf, owl:sameAs 정도만 써도 대부분의 효용을 얻습니다.
SKOS — 개념 체계에는 이쪽이 맞습니다
교육 도메인에서 가장 실용적인 선택입니다. 분류 체계, 주제어, 역량 체계처럼 “개념들의 느슨한 계층” 을 표현합니다.
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
ex:프로그래밍역량 a skos:Concept ;
skos:prefLabel "프로그래밍 역량"@ko ;
skos:altLabel "코딩 역량"@ko, "Programming Competency"@en ;
skos:broader ex:컴퓨팅사고력 ;
skos:narrower ex:알고리즘설계, ex:디버깅 ;
skos:related ex:문제해결역량 ;
skos:definition "요구사항을 코드로 구현하는 능력"@ko .
SKOS가 좋은 이유가 있습니다.
skos:broader는 OWL 서브클래스가 아닙니다. “더 넓은 개념”일 뿐이라 논리적으로 엄격하지 않습니다. 현실의 분류 체계는 대개 엄밀하지 않으므로 이게 오히려 맞습니다prefLabel/altLabel로 동의어를 자연스럽게 담습니다. 검색 질의 확장에 바로 씁니다- 다국어가 기본입니다.
@ko,@en태그
“역량 체계를 온톨로지로 만들자”는 요구는 십중팔구 SKOS로 충분합니다. OWL 클래스 계층으로 만들면 “프로그래밍 역량의 인스턴스가 무엇인가” 같은 답하기 곤란한 질문에 부딪힙니다.
정리
용어 통일만 → SKOS
계층 + 동의어 → SKOS
개체 간 관계 질의 → RDF + RDFS
관계를 타고 추론 → OWL (최소한만)
데이터 정합성 검증 → SHACL ← 뒤에서 자세히
3. 교육 도메인 모델링
무엇을 개체로 볼 것인가
가장 먼저 하는 일은 클래스 후보를 뽑고 그중 진짜 클래스를 고르는 것입니다.
과목 학생 교원 학과 교육과정
성취기준 역량 학위 강의 수강이력
여기서 흔히 틀리는 지점이 있습니다. “수강”을 어떻게 다룰 것인가입니다.
# 시도 1 — 단순 관계
ex:학생001 ex:수강 ex:CS201 .
이러면 “언제 수강했는지, 성적이 뭔지”를 붙일 곳이 없습니다. 트리플은 세 칸뿐이니까요.
# 시도 2 — 관계를 개체로 승격 (reification)
ex:수강001 a ex:수강이력 ;
ex:수강자 ex:학생001 ;
ex:대상과목 ex:CS201 ;
ex:학기 "2024-1" ;
ex:성적 "A" ;
ex:취득학점 3 .
속성을 가져야 하는 관계는 개체로 올려야 합니다. 이건 RDF 모델링에서 가장 자주 나오는 패턴이고, 초반에 판단하지 못하면 나중에 전면 수정이 됩니다.
판단 기준은 단순합니다. “이 관계에 시점·상태·근거를 붙이고 싶은가?” 그렇다면 개체입니다.
교육과정 - 역량 - 성취기준 연결
교육 도메인의 핵심 가치는 여기를 연결했을 때 나옵니다.
ex:CS201 a ex:과목 ;
ex:과목명 "자료구조" ;
ex:달성역량 ex:알고리즘설계, ex:문제해결역량 ;
ex:성취기준 ex:AC-CS201-01, ex:AC-CS201-02 .
ex:AC-CS201-01 a ex:성취기준 ;
ex:기술 "선형 자료구조를 구현하고 시간복잡도를 분석할 수 있다" ;
ex:연계역량 ex:알고리즘설계 ;
ex:블룸단계 ex:분석 .
ex:알고리즘설계 a skos:Concept ;
skos:broader ex:프로그래밍역량 .
이렇게 엮여 있으면 이런 질문에 질의로 답할 수 있습니다.
# "문제해결역량을 기르려면 어떤 과목을 들어야 하나"
PREFIX ex: <http://example.org/edu#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?과목 ?과목명 WHERE {
?과목 ex:달성역량 ?역량 ;
ex:과목명 ?과목명 .
?역량 skos:broader* ex:문제해결역량 .
}
skos:broader* 의 * 가 경로 질의입니다. 하위 역량이 몇 단계로 중첩돼 있든 전부 타고 올라갑니다. 관계형 DB에서 재귀 CTE로 짜야 할 것이 한 줄입니다. 그래프 모델을 쓰는 실질적 이득이 여기서 나옵니다.
메타데이터 표준 재사용
바퀴를 다시 발명하지 않는 게 중요합니다. 이미 있는 어휘를 쓰면 외부 데이터와 연결되고, 설계 시간도 아낍니다.
| 표준 | 용도 |
|---|---|
| Dublin Core | 자원의 기본 메타데이터 (제목, 작성자, 날짜, 언어) |
| schema.org | 웹 공개용. Course, EducationalOccupationalCredential 등 교육 타입 보유. 검색엔진이 읽습니다 |
| LOM / IEEE 1484.12 | 학습 객체 메타데이터. 교육 분야 전용 |
| SKOS | 개념 체계 |
| PROV-O | 출처·이력 (누가 언제 이 데이터를 만들었나) |
@prefix dct: <http://purl.org/dc/terms/> .
@prefix schema: <https://schema.org/> .
ex:CS201 a ex:과목, schema:Course ;
dct:title "자료구조" ;
dct:language "ko" ;
dct:modified "2024-03-01"^^xsd:date ;
schema:courseCode "CS201" .
자체 어휘(ex:)와 표준 어휘를 섞어 쓰는 게 정상입니다. 표준에 있는 것은 표준을 쓰고, 도메인 고유 개념만 직접 정의합니다.
4. 정합성 — 추론이 아니라 SHACL로
이 절이 실무에서 제일 중요합니다.
왜 OWL로는 검증이 안 되는가
“모든 과목은 학점이 있어야 한다”를 강제하고 싶습니다. OWL로 이렇게 써 봅니다.
ex:과목 rdfs:subClassOf [
a owl:Restriction ;
owl:onProperty ex:학점 ;
owl:minCardinality 1
] .
그리고 학점이 없는 과목을 넣습니다.
ex:CS999 a ex:과목 . # 학점 없음
오류가 나지 않습니다. 추론 엔진은 이렇게 해석합니다.
“CS999는 과목이다. 모든 과목은 학점이 하나 이상 있다. 따라서 CS999에도 학점이 있을 것이다. 다만 그 값을 아직 모를 뿐이다.”
개방 세계 가정이기 때문입니다. OWL은 제약 언어가 아니라 추론 언어입니다. 데이터 검증에 쓰면 안 됩니다.
SHACL — 폐쇄 세계 검증
SHACL(Shapes Constraint Language)은 정반대입니다. 적혀 있지 않으면 없는 것으로 보고 위반을 보고합니다.
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ex:과목Shape a sh:NodeShape ;
sh:targetClass ex:과목 ;
sh:property [
sh:path ex:과목명 ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
sh:message "과목명은 반드시 하나여야 합니다"
] ;
sh:property [
sh:path ex:학점 ;
sh:datatype xsd:integer ;
sh:minInclusive 1 ;
sh:maxInclusive 6 ;
sh:minCount 1 ;
sh:message "학점은 1~6 사이의 정수여야 합니다"
] ;
sh:property [
sh:path ex:선수과목 ;
sh:class ex:과목 ;
sh:message "선수과목은 과목이어야 합니다"
] .
이제 ex:CS999 를 검증하면 “학점은 1~6 사이의 정수여야 합니다” 라는 위반 보고서가 나옵니다.
역할 분담
OWL → 추론: 적힌 것에서 새로운 사실을 끌어냄
SHACL → 검증: 적힌 것이 규칙에 맞는지 확인
둘 다 필요하고, 섞어 쓰면 안 됩니다. 파이프라인은 대개 이렇게 구성합니다.
원본 데이터 → RDF 변환 → SHACL 검증 → (통과) → 추론 → 트리플스토어 적재
↓ (실패)
위반 보고서 → 데이터 수정
순환 참조 같은 것도 SHACL이나 SPARQL로 잡습니다.
# 선수과목 순환 탐지
PREFIX ex: <http://example.org/edu#>
SELECT ?과목 WHERE {
?과목 ex:선수과목+ ?과목 .
}
ex:선수과목+ 는 한 번 이상 타고 갔더니 자기 자신으로 돌아온 경우를 찾습니다. 데이터 적재 전에 이 질의를 돌리면 순환을 미리 막을 수 있습니다.
5. 저장소 선택
| 종류 | 예 | 특징 |
|---|---|---|
| 트리플스토어 | Apache Jena TDB, GraphDB, Blazegraph, Amazon Neptune | RDF 네이티브. SPARQL, 추론, SHACL 기본 지원 |
| 속성 그래프 DB | Neo4j, Amazon Neptune | 노드·엣지에 속성. Cypher 질의. 개발자 친화적 |
| 관계형 DB | MySQL, PostgreSQL | 트리플 테이블로 흉내 가능. 재귀 CTE로 경로 질의 |
표준과 추론이 필요하면 트리플스토어, 개발 속도가 우선이면 속성 그래프가 일반적인 갈림길입니다.
한 가지 현실적인 조언은, 처음부터 트리플스토어를 도입하지 않아도 된다는 것입니다. 개념 모델(클래스, 관계, 제약)을 제대로 정의해 두면 저장소는 나중에 바꿀 수 있습니다. 모델링이 자산이고 저장소는 구현입니다.
6. 확장성과 재사용성
네임스페이스와 URI 설계
URI는 한 번 정하면 바꾸기 어렵습니다. “쿨한 URI는 변하지 않는다” 는 원칙이 있습니다.
나쁨: http://our-univ.ac.kr/2024/ontology/v2/과목/CS201
↑ 연도, 버전, 조직명이 들어가면 전부 변경 요인
좋음: http://our-univ.ac.kr/id/course/CS201
↑ 식별에 필요한 것만
- 버전을 URI에 넣지 않습니다. 버전은 별도 속성으로
- 조직 개편에 흔들리지 않는 경로를 씁니다
- 온톨로지(스키마) URI와 데이터(인스턴스) URI를 분리합니다.
/ontology/Coursevs/id/course/CS201
버전 관리
온톨로지는 계속 바뀝니다. 바뀔 때 하위 호환이 깨지는지를 구분해야 합니다.
| 변경 | 호환성 |
|---|---|
| 클래스·속성 추가 | 안전 |
| 라벨·설명 수정 | 안전 |
속성의 range 확대 |
안전 |
| 속성 이름 변경 | 깨짐. 기존 데이터 전부 영향 |
| 클래스 삭제 | 깨짐 |
| 카디널리티 강화 | 깨짐. 기존 데이터가 위반 상태가 됨 |
삭제 대신 폐기 표시(owl:deprecated) 를 하고 대체 항목을 가리키게 하는 게 안전합니다.
ex:구과목명 a owl:DeprecatedProperty ;
rdfs:comment "2024-03 폐기. ex:과목명 을 사용하세요." ;
rdfs:seeAlso ex:과목명 .
개념과 인스턴스를 섞지 않기
흔한 실수입니다.
# 나쁨 — 역량을 클래스로
ex:프로그래밍역량 a owl:Class .
ex:학생001 a ex:프로그래밍역량 . # 학생이 역량의 인스턴스?
# 좋음 — 역량을 개념으로, 보유를 관계로
ex:프로그래밍역량 a skos:Concept .
ex:학생001 ex:보유역량 ex:프로그래밍역량 .
“이것의 인스턴스가 무엇인가” 를 물어보면 대개 판별됩니다. 답하기 곤란하면 클래스가 아니라 개념입니다.
7. 어디까지 갈 것인가 — 판단 기준
온톨로지 구축은 비용이 큽니다. 얻는 것이 비용을 넘는지 먼저 따져야 합니다.
| 이 질문에 “예”라면 | 필요한 것 |
|---|---|
| 용어가 부서마다 달라 소통이 안 된다 | SKOS 용어집 |
| 계층 상위로 묶어서 조회하고 싶다 | SKOS + broader |
| “A를 들으려면 결국 뭘 먼저 들어야 하나” 같은 경로 질문이 있다 | 그래프 + 경로 질의 |
| 데이터 입력 오류를 자동으로 잡고 싶다 | SHACL |
| 명시되지 않은 사실을 끌어내야 한다 | OWL 추론 |
| 외부 기관 데이터와 연결해야 한다 | 표준 어휘 + URI |
아무것도 해당하지 않으면 온톨로지를 만들지 않는 게 맞습니다. 잘 정규화된 관계형 스키마로 충분합니다.
정리
| 질문 | 답 |
|---|---|
| 온톨로지란 | 암묵적 합의를 기계가 읽을 수 있게 명시한 것. 핵심은 “명시적” |
| 분류체계와 뭐가 다른가 | 관계의 종류·성질·제약이 있어 추론이 가능하다 |
| 교육 도메인에 뭘 쓰나 | 역량·주제 체계는 SKOS로 충분한 경우가 대부분. OWL은 최소한만 |
| 속성 있는 관계는 | 개체로 승격. “시점·상태·근거를 붙이고 싶은가”가 기준 |
| OWL로 데이터 검증이 되나 | 안 된다. 개방 세계 가정이라 빠진 값을 “미지”로 본다. 검증은 SHACL |
| URI는 어떻게 짓나 | 버전·연도·조직명을 넣지 않는다. 스키마와 인스턴스 URI를 분리 |
| 언제 만들지 말아야 하나 | 경로 질의·추론·외부 연결 요구가 없다면. 관계형으로 충분하다 |
참고 문헌
- Gruber, A Translation Approach to Portable Ontology Specifications (1993): https://tomgruber.org/writing/ontolingua-kaj-1993
- W3C RDF 1.1 Primer: https://www.w3.org/TR/rdf11-primer/
- W3C SKOS Primer: https://www.w3.org/TR/skos-primer/
- W3C SHACL: https://www.w3.org/TR/shacl/
- W3C OWL 2 Primer: https://www.w3.org/TR/owl2-primer/
- schema.org — Course: https://schema.org/Course