이번에는 지난번 지식그래프에 대한 전반적인 이해를 했다면, 이번에는 8단계 온톨로지 구축단계 중 핵심이라고 할 수 있는 단계4, 클래스/속성 정의, 단계5. 관계 정의, 단계6. 표현 및 구현 단계를 공연/전시 사례를 바탕으로 진행할 예정입니다.참고한 도서는 유원북스의 지식그래프(2025)입니다.
공연/전시 서비스 온톨로지 구축 예시(단계4,5,6)
단계4: 클래스 및 속성 정의
1. 클래스(Class) 및 계층 구조 정의
클래스는 온톨로지의 '주체'가 되는 틀입니다. 공연 서비스라면 우리가 다룰 데이터의 가장 큰 범주를 먼저 설정합니다.
1) 클래스 정의 (Class Definition)
단순한 카테고리가 아니라, "이 세상에 존재하는 것들의 유형"을 정의하는 것입니다.
- :Performance: 모든 공연의 공통 조상 (추상적 개념)
- :Exhibition: 모든 전시의 공통 조상
- :Venue: 공연이나 전시가 열리는 물리적/가상 공간
- :Person: 아티스트, 감독, 관객 등 사람 개체
2) 클래스 계층 구조 설계 (Hierarchy)
모든 정보를 Performance 하나에 넣으면 관리가 어렵습니다. is-a (상속) 관계를 통해 세분화합니다.
| 부모 클래스 (Superclass) | 자식 클래스 (Subclass) | 의미 (is-a) |
| :Performance | :Musical, :Concert, :Play | 뮤지컬은 공연의 일종이다. |
| :Exhibition | :ArtExhibition, :PhotoExhibition | 미술 전시는 전시의 일종이다. |
| :Person | :Actor, :Director, :Singer | 배우는 사람의 일종이다. |
Tip: 계층 구조를 잘 짜두면, 나중에 "모든 공연 정보를 가져와"라고 명령했을 때 하위 클래스인 '뮤지컬'과 '콘서트' 데이터를 자동으로 포함하여 추론할 수 있습니다.
2. 속성(Property) 정의
속성은 클래스들 사이의 '관계'나 클래스가 가진 '값'을 정의합니다.
1) 데이터 속성 (Datatype Property)
개체가 가진 구체적인 정보(값)를 나타냅니다. (개체 → 문자열, 숫자, 날짜 등)
- :hasTitle: 공연의 제목 (값: "레미제라블"^^xsd:string)
- :hasPrice: 티켓 가격 (값: 150000^^xsd:integer)
- :openingDate: 개막일 (값: "2026-05-11"^^xsd:date)
2) 객체 속성 (Object Property)
개체와 또 다른 개체를 연결하는 '링크'입니다. (개체 → 개체)
- :takesPlaceAt: 공연(Performance)이 열리는 장소(Venue)를 연결
- :hasPerformer: 공연(Performance)에 출연하는 예술가(Artist)를 연결
- :organizedBy: 전시(Exhibition)를 주최하는 기관(Organization)을 연결
3. 속성의 정의역(Domain)과 치역(Range)
이 부분이 온톨로지의 '규칙'을 만드는 핵심입니다. 아무 데이터나 연결되지 않도록 가이드라인을 정하는 것입니다.
예시: :takesPlaceAt (개최 장소) 속성
- 정의역(Domain): :Performance
- "이 속성은 오직 '공연' 클래스의 개체만 사용할 수 있다." (예약어 같은 역할)
- 치역(Range): :Venue
- "이 속성 뒤에는 반드시 '장소' 클래스의 개체가 와야 한다."
예시: :hasPrice (가격) 속성
- 정의역(Domain): :Performance
- "가격이라는 속성은 '공연'에 붙는다."
- 치역(Range): xsd:integer
- "가격 값은 반드시 '정수' 형태여야 한다." (텍스트 "비쌈" 등은 허용 안 함)
4. 종합 예시 (Scenario)
만약 "예술의전당에서 열리는 뮤지컬 '지킬앤하이드'"라는 데이터를 온톨로지로 표현한다면 다음과 같은 구조가 됩니다.
클래스 선언:
- Jekyll_and_Hyde rdf:type :Musical .
- Seoul_Arts_Center rdf:type :Venue .
- 계층 관계 활용:
- :Musical rdfs:subClassOf :Performance . (지킬앤하이드는 자동으로 '공연'이 됨)
- 속성 연결:
- Jekyll_and_Hyde :takesPlaceAt Seoul_Arts_Center . (객체 속성)
- Jekyll_and_Hyde :hasTitle "지킬 앤 하이드" . (데이터 속성)
5단계: 관계 정의
4단계가 온톨로지의 뼈대(클래스와 속성)를 만드는 과정이었다면, 이번 5단계(관계 정의)는 그 뼈대들이 어떻게 상호작용하는지 '논리적 물리 법칙'을 부여하는 단계입니다.
단순히 데이터를 연결하는 것을 넘어, 컴퓨터(추론 엔진)가 숨겨진 정보를 스스로 알아낼 수 있도록 규칙을 세밀하게 조율하는 과정입니다. RAG 아키텍처나 지식그래프 기반 검색에서 가장 강력한 위력을 발휘하는 부분이기도 합니다.
목표: 클래스 간의 관계를 나타내는 객체 속성을 상세화하고, 속성 자체의 특성과 제약 조건을 정의하여 온톨로지의 표현력과 정밀도를 높이는 것
1. 객체 속성 상세화 (Object Property Refinement)
4단계에서 정의한 굵직한 관계 외에, 도메인(공연/전시)에서 일어나는 다양한 비즈니스적 관계를 촘촘하게 추가합니다.
- isLocatedIn: (장소 → 도시) 공연장이 어느 지역에 있는지 연결합니다.
- producedBy: (공연 → 제작사) 누가 이 공연을 만들었는지 연결합니다.
2. 속성 특성 정의 (Property Characteristics)
컴퓨터가 관계의 '성질'을 이해하도록 수학적/논리적 특성을 부여합니다.
1) 속성 특성 정의
| 속성 특성 | 의미 | 공연/전시 도메인 예시 |
| 함수적 (Functional) |
"오직 하나만 존재" 주어 하나당 목적어가 최대 1개 |
hasMainDirector: 하나의 공연은 단 1명의 '총괄 감독'만 가집니다. |
| 역함수적 (Inverse Functional) |
"이 값으로 주어 역추적 가능" 고유 식별자 역할 |
hasTicketingID: 예매 번호가 'T1234'인 티켓은 세상에 단 하나뿐입니다. 이 번호로 티켓 개체를 특정할 수 있습니다. |
| 이행적 (Transitive) |
"꼬리에 꼬리를 무는 포함 관계" A→B 이고 B→C 이면 A→C |
isLocatedIn: 예술의전당이 '서울'에 있고, 서울이 '한국'에 있다면, 예술의전당은 '한국'에 있습니다. (컴퓨터가 스스로 추론) |
| 대칭적 (Symmetric) |
"너와 나의 관계는 동등함" A→B 이면 B→A |
isSimilarTo: '지킬앤하이드'가 '프랑켄슈타인'과 유사한 극이라면, 반대로 '프랑켄슈타인'도 '지킬앤하이드'와 유사합니다. |
| 비대칭적 (Asymmetric) |
"일방통행 관계" A→B 이면 B→A 일 수 없음 |
isPartOf: '1막'은 '전체 공연'의 일부입니다. 하지만 '전체 공연'이 '1막'의 일부가 될 수는 없습니다. |
| 역 속성 (Inverse Of) |
"서로 반대 방향에서 부르는 말" | hasPerformer ↔ performsIn: 공연 입장에서는 "이 배우를 캐스팅했다"이고, 배우 입장에서는 "이 공연에 출연한다"입니다. 둘 중 하나만 데이터로 입력해도 반대쪽은 자동 생성됩니다. |
3. 관계 카디널리티 제약 정의 (Cardinality Constraints)
데이터베이스의 무결성 제약 조건(예: NOT NULL)과 유사하게, 논리적 오류가 발생하지 않도록 연결되는 개체의 '수(Count)'를 엄격하게 제한합니다.
- 최소 카디널리티 (Min 1):
- 규칙: :Musical owl:minCardinality 1 :hasPerformer
- 해석: "아무리 1인극이라도 뮤지컬이라면 최소 1명 이상의 배우는 무조건 연결되어야 한다." (배우 정보가 없는 뮤지컬 데이터는 오류로 처리됨)
- 최대 카디널리티 (Max 1):
- 규칙: :Seat owl:maxCardinality 1 :isAssignedTo :Ticket
- 해석: "하나의 좌석에는 최대 1장의 티켓만 발급될 수 있다." (중복 예매 방지 논리)
- 정확 카디널리티 (Exact):
- "이 전시는 정확히 3개의 전시관으로 구성된다."
4. 복잡한 관계 표현 (Property Chains)
온톨로지 추론의 '꽃'이라고 할 수 있습니다. 이미 존재하는 여러 단계의 관계를 조합하여, 데이터베이스에 직접 입력하지 않은 '새로운 직통 관계(지름길)'를 컴퓨터가 스스로 만들어내게 합니다.
- 설정 규칙: :hasPerformer + :isBasedIn ➡ :hasPerformerBasedIn
- 상황:
- 공연(A)은 배우(B)를 가짐 (:hasPerformer)
- 배우(B)는 런던(C)을 주 무대로 활동함 (:isBasedIn)
- 추론 결과:
- 시스템은 자동으로 "이 공연(A)은 런던에 기반을 둔 배우들이 출연하는 공연(C)이다" (:hasPerformerBasedIn) 라는 새로운 지식을 생성합니다.
실무적 활용 (RAG 관점): 사용자가 LLM에게 *"런던 출신 배우들이 나오는 내한 뮤지컬 찾아줘"*라고 질문했을 때, 일반적인 검색은 '런던'과 '뮤지컬'이 동시에 적힌 텍스트만 찾습니다. 하지만 위와 같이 속성 체인이 구축된 지식그래프를 RAG에 연동하면, 명시적으로 홍보 문구에 '런던'이 없더라도 연결된 배우의 국적 데이터를 타고 들어가 정확한 답변을 도출할 수 있습니다.
단계6: 표현 및 구현
지금까지의 단계가 회의실 화이트보드에 그림을 그리며 "어떤 데이터를 어떻게 연결할까?"를 고민하는 설계 단계였다면, 이번 6단계(표현 및 구현)는 그 그림을 컴퓨터(특히 RAG나 AI 에이전트)가 읽고 쿼리할 수 있도록 실제 코드로 작성하여 데이터베이스에 적재(인스턴스화)하는 과정입니다.
데이터 분석 및 시스템 기획 실무에 빗대어 본다면, ERD(개체-관계 모델) 설계를 마치고 실제 SQL DDL로 테이블을 생성한 뒤, INSERT 문으로 초기 데이터를 밀어 넣는 작업과 완벽히 동일합니다.
목표: 앞선 단계들에서 개념적으로 설계된 온톨로지 모델(클래스, 속성, 관계)을 컴퓨터가 이해하고 처리할 수 있는 표준 형식으로 변환하고, 실제 온톨로지 파일을 생성하는 단계
주요 활동
1. 온토로지 표현 언어 선택
온톨로지를 기술하기 위한 표준 언어를 선택합ㄴ디ㅏ. 현재 웹 온톨로지 분야의 표준은 W3C에서 제정한 OWL 2입니다.
2. OWL구문 선택
OWL 2온톨로지를 파일로 저장하고 교환하기 위한 구문을 선택함
- RDF/XML: OWL의 기본 교환 형식이며, RDF 표준에 기반한 XML구문입니다. 기계처리에 적합하지만 사람이 직접 읽고 쓰기에는 다소 복잡할 수 있음
- Turle (Terse RDF Triple Language): RDF표준이 간결하게 표현하는 텍스트 기반 구문. 사람이 읽고 쓰기에 비교적 용이하게 개발됨
- OWL/XML: OWL 2구조를 직접 반영하는 XML 기반 구문
- Manchester Syntax: 프레임 기반으로 클래스 관련 정보를 모아서 보여주는 사용자 친화적인 구문입니다. 특히 Progege와 같은 온톨로지 편집 도구에서 많이 사용됨
- JSON-LD:JSON형식을 사용하여 링크드 데이터를 표현하는 방식으로, 웹 개발 환경과의 통합에 유리합니다.
3.온톨로지 편집 도구 사용
온톨로지를 시각적으로 설계하고, OWL 코드를 생성 및 편집하며, 관리하는 데 특화된 소프트웨어 도구를 사용함. 대표적 Protege

4. URI 명명규칙 및 네임스페이스 정의
일관성 있고 의미 있는 URI 명명 규칙을 수립하고, 온톨로지의 출처와 버전을 나타내는 네임스페이스를 정의하는 것이 중요함
예) http://myperformingarts.com/ontology/performance#
5. 개체 생성
정의된 클래스와 속성을 바탕으로 실제 세계의 구체적인 개체를 온톨로지에 추가함
예) 뮤지컬 Cats를 :Musical 클래스의 개체로 생성하여 관련 속성값들을 연결함
1)Turtle 구문 예시
| 예시(turle구문) @ prefix : <http://myperformingarts.com/ontology/performance#t> @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> @prefix owl: <http://www.w3.org/2002/07/owl#> @ prefix xsd: <http://www.w3.ora/2001/XMLSchematt> @prefix rdfs: <http://www.w3.ora/2000/01/rdf-schema#> :Performance rdf:type owl:Class :Musical rdf:type owl:Class rdfs:subClassOf:Performance. :Venue rdf:type owl:Class. :Artist rdf:type ow:Class. :hasTitle rdf:type owl:DatatypeProperty; rdfs:domain:Performance; rdfs:range xsd:string.: takesPlaceAt rdf:type owl:ObjectProperty; rdfs:domain :Performance; rdfs:range:Venue. :hasPerformer rdf:type owl:ObjectProperty; rdfs:domain:Performance: rdfs:range:Artist. #Instance Creation Example :Cats_Musical rdf:type :Musical; :hasTitle "Cats"^^xsd:string; :takesP|aceAt:NationalTheatre; :hasPerformer :JaneDoe. :NationalTheatre rdf:type :Venue rdfs:label"National Theatre": :JaneDoe rdf:type :Artist:; rdfs:label "Jane Doe". |
2. 예시(Turtle 구문)의 쉬운 해석
Turtle(Terse RDF Triple Language)은 지식그래프를 구성하는 주어-동사-목적어(Triple) 구조를 사람이 읽기 쉽게 줄여 쓴 마크업 언어입니다. 개발 환경의 YAML이나 JSON처럼 직관적입니다.
① 머리말 (Prefix 설정: 단축키 지정)
@prefix : <http://myperformingarts.com/ontology/performance#>
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
...
- 해석: 매번 길고 복잡한 웹 주소(URI)를 쓰기 힘드니 단축키를 만듭니다. 예를 들어 앞으로 rdf:라고 쓰면 뒤에 있는 긴 주소로 컴퓨터가 알아서 인식합니다. 콜론(:)만 있는 것은 '현재 우리 프로젝트의 기본 주소'를 의미합니다.
② 클래스 선언 (뼈대 만들기)
:Performance rdf:type owl:Class .
:Musical rdf:type owl:Class ;
rdfs:subClassOf :Performance .
- 해석: '공연(Performance)'이라는 클래스를 만듭니다. 그리고 '뮤지컬(Musical)'이라는 클래스도 만드는데, 이는 공연의 하위 클래스(상속, subClassOf)라고 지정합니다.
③ 속성 정의 (관계 규칙 만들기)
:hasTitle rdf:type owl:DatatypeProperty ;
rdfs:domain :Performance ;
rdfs:range xsd:string .
:takesPlaceAt rdf:type owl:ObjectProperty ;
rdfs:domain :Performance ;
rdfs:range :Venue .
- 해석:
- hasTitle(제목): 공연(Performance)에 붙는 속성이며, 그 값은 반드시 문자열(string)이어야 합니다.
- takesPlaceAt(개최장소): 공연(Performance)에 붙는 속성이며, 그 값은 단순 문자가 아니라 장소(Venue)라는 또 다른 객체와 연결되어야 합니다.
④ 개체 생성 (실제 데이터 입력 - Instance Creation)
:Cats_Musical rdf:type :Musical ;
:hasTitle "Cats"^^xsd:string ;
:takesPlaceAt :NationalTheatre ;
:hasPerformer :JaneDoe .
- 해석: 드디어 실제 데이터를 넣습니다. Cats_Musical이라는 데이터를 만들고, 이것의 타입은 '뮤지컬'이라고 선언합니다. 제목은 문자열로 "Cats", 장소는 국립극장(NationalTheatre 객체 연결), 출연자는 제인 도(JaneDoe 객체 연결)로 세팅합니다. (세미콜론 ;은 주어인 Cats_Musical이 계속 이어진다는 의미입니다.)
3. Manchester Syntax 버전으로 변환
Manchester Syntax는 Protégé(프로테제) 같은 온톨로지 에디터에서 주로 사용하는 문법입니다. Turtle이 주어 중심의 '문장'형태라면, Manchester는 객체지향 프로그래밍의 '프레임(Frame)'이나 '클래스 구조체'를 보는 것처럼 덩어리로 묶어서 표현하여 구조를 한눈에 파악하기 매우 좋습니다.
위 Turtle 코드를 Manchester Syntax로 완벽히 동일하게 구현하면 다음과 같습니다.
Prefix: : <http://myperformingarts.com/ontology/performance#>
Prefix: xsd: <http://www.w3.org/2001/XMLSchema#>
Prefix: rdfs: <http://www.w3.org/2000/01/rdf-schema#>
Prefix: owl: <http://www.w3.org/2002/07/owl#>
# 1. 클래스(Class) 정의
Class: :Performance
Class: :Musical
SubClassOf: :Performance
Class: :Venue
Class: :Artist
# 2. 데이터 속성(Data Property) 정의
DataProperty: :hasTitle
Domain: :Performance
Range: xsd:string
# 3. 객체 속성(Object Property) 정의
ObjectProperty: :takesPlaceAt
Domain: :Performance
Range: :Venue
ObjectProperty: :hasPerformer
Domain: :Performance
Range: :Artist
# 4. 개체(Instance / Individual) 생성
Individual: :NationalTheatre
Types: :Venue
Annotations: rdfs:label "National Theatre"
Individual: :JaneDoe
Types: :Artist
Annotations: rdfs:label "Jane Doe"
Individual: :Cats_Musical
Types: :Musical
Facts:
:hasTitle "Cats"^^xsd:string,
:takesPlaceAt :NationalTheatre,
:hasPerformer :JaneDoe
💡 실무 적용 포인트 (개발 관점): 지식그래프 기반의 '생성형 AI 통합 검색 서비스'나 RAG 파이프라인을 구축하실 때, 이 6단계의 결과물(Turtle이나 JSON-LD 파일)이 바로 Graph Database(예: Neo4j, GraphDB 등)에 적재되는 핵심 데이터 덤프 파일이 됩니다. LLM 기반 에이전트들은 사용자의 자연어 질문("제인 도가 나오는 뮤지컬 국립극장 예매해줘")을 받아, 이 온톨로지 구조를 바탕으로 정확한 SPARQL 쿼리나 Cypher 쿼리를 생성하여 답변을 찾아오게 됩니다.
3. Neo4j에서 사용하기 위한 변형
온톨로지 설계(개념 모델)를 Neo4j 스키마(물리 모델)로 변환하는 것은 매우 자연스럽게 이루어집니다. 앞서 설명해 드린 4, 5, 6단계의 온톨로지 모델이 Neo4j 스키마와 Cypher(Neo4j 쿼리 언어)로 어떻게 번역되는지 직관적으로 비교해 드리겠습니다.
1) 온톨로지 ➡️ Neo4j 매핑 공식
| 온톨로지 (RDF/OWL) | Neo4j (Property Graph) | 예시 적용 |
| 클래스 (Class) | 노드 라벨 (Node Label) | :Performance, :Venue, :Artist |
| 계층 구조 (subClassOf) | 다중 라벨 (Multiple Labels) | (:Performance:Musical) (공연이면서 뮤지컬인 노드) |
| 데이터 속성 (Datatype Property) | 노드 속성 (Node Property) | title: "Cats", openingDate: "2026-05-11" |
| 객체 속성 (Object Property) | 관계 (Relationship / Edge) | [:TAKES_PLACE_AT], [:HAS_PERFORMER] |
| 카디널리티 제약 조건 | 제약 조건 (Constraint) | REQUIRE p.title IS NOT NULL |
2) Neo4j 스키마 설계도 (개체-관계 모델)
Neo4j에서는 관계를 화살표(()-[r]->()) 형태의 스키마로 표현합니다. 앞서 설계한 공연/전시 온톨로지를 Neo4j 스키마 형태로 그리면 다음과 같습니다.
- (:Performance:Musical) -[ :TAKES_PLACE_AT ]-> (:Venue)
- (:Performance:Musical) -[ :HAS_PERFORMER ]-> (:Artist)
- (:Performance:Musical) -[ :PRODUCED_BY ]-> (:ProductionCompany)
- (:Venue) -[ :IS_LOCATED_IN ]-> (:City)
3) 실제 Neo4j 적용 (Cypher 코드 예시)
앞서 6단계에서 작성했던 "제인 도가 출연하는 국립극장 뮤지컬 캣츠" 데이터를 Neo4j 스키마에 맞게 적재하는 Cypher 쿼리입니다.
① 스키마 제약조건 생성 (단계 4, 5의 규칙 적용)
Neo4j에서는 제약조건을 통해 데이터의 정합성을 맞춥니다.
// 공연 ID는 고유해야 함 (역함수적 속성 반영)
CREATE CONSTRAINT performance_id_unique FOR (p:Performance) REQUIRE p.id IS UNIQUE;
// 공연 제목은 반드시 있어야 함 (최소 카디널리티 제약)
CREATE CONSTRAINT performance_title_exists FOR (p:Performance) REQUIRE p.title IS NOT NULL;
② 인스턴스(데이터) 및 관계 생성 (단계 6의 구현)
RDF/OWL의 복잡한 구조가 Neo4j에서는 직관적인 노드와 관계로 생성됩니다.
// 1. 노드(개체) 생성 및 데이터 속성 부여
CREATE (cats:Performance:Musical {
id: "M_001",
title: "Cats",
price: 150000,
openingDate: date("2026-05-11")
})
CREATE (nt:Venue {
id: "V_001",
name: "National Theatre"
})
CREATE (jane:Artist {
id: "A_001",
name: "Jane Doe"
})
// 2. 객체 속성(관계) 연결
CREATE (cats)-[:TAKES_PLACE_AT]->(nt)
CREATE (cats)-[:HAS_PERFORMER]->(jane)
4) RAG 시스템에서 Neo4j 스키마 활용 예시
온톨로지에서 '복잡한 관계 표현 (Property Chain)'이나 '이행적 속성'으로 정의했던 개념들은 Neo4j에서 그래프 순회(Graph Traversal) 쿼리로 매우 강력하게 작동합니다.
상황: "제인 도가 출연하는 뮤지컬의 장소 이름을 알려줘"
RAG의 LLM 에이전트는 사용자의 질문을 분석하여 다음과 같은 직관적인 Cypher 쿼리를 생성합니다.
MATCH (m:Musical)-[:HAS_PERFORMER]->(a:Artist {name: "Jane Doe"}),
(m)-[:TAKES_PLACE_AT]->(v:Venue)
RETURN m.title AS MusicalTitle, v.name AS VenueName
요약하자면:
W3C의 온톨로지(OWL/Turtle)는 "지식을 학술적이고 논리적으로 빈틈없이 정의하는 표준 규격서"라면, Neo4j는 그 규격서를 바탕으로 "RAG나 AI 서비스가 초고속으로 데이터를 검색하고 관계를 추적할 수 있도록 최적화된 실무 데이터베이스"라고 이해하시면 좋습니다. 실무에서는 Protege로 온톨로지 구조를 기획하고, 실제 서비스 구현 시 Neo4j에 그래프 형태로 부어서 사용하는 패턴(Knowledge Graph 구축)을 가장 많이 사용합니다.
'독서&지식' 카테고리의 다른 글
| 목숨 걸고 온톨로지 전문가 되기 1탄(지식그래프)_1 (0) | 2026.05.11 |
|---|---|
| 랭체인 에이전트 및 도구, Pydantic 스키마로 구조화된 입력받기, ReAct (0) | 2026.04.03 |
| 랭체인 프롬프트, 모델, 출력파서, 랭체인 허브 (1) | 2026.04.02 |
| 국회 예산안 및 결산안 심사 과정 (0) | 2026.03.31 |
| 법률 관련 사이트 및 API 정보 (0) | 2026.01.28 |