
SHACL 완전 정복 — RDF 데이터의 수호자, 지식 그래프의 품질 보증인
W3C가 만든 RDF 데이터 검증 표준 SHACL. 왜 이런 게 필요했고, 어떻게 동작하며, 2026년 AI 시대에 왜 더 중요해졌을까? 풍부한 사례와 인터랙티브 시뮬레이터로 완전 정복한다.

W3C가 만든 RDF 데이터 검증 표준 SHACL. 왜 이런 게 필요했고, 어떻게 동작하며, 2026년 AI 시대에 왜 더 중요해졌을까? 풍부한 사례와 인터랙티브 시뮬레이터로 완전 정복한다.
공장에서 제품이 출하되기 전, 반드시 품질 검사(QC)를 거친다. 나사 하나가 빠져도 불량이다. 그런데 데이터 세계에는 어떤가? 수천만 개의 데이터가 지식 그래프에 쏟아져 들어오는데, 이 데이터가 올바른 형식인지, 필수 항목이 빠지지 않았는지, 값의 범위가 적절한지 검사하는 시스템이 — 놀랍게도 오랫동안 없었다.

예를 들어 보자. 회사의 고객 데이터베이스에 이런 데이터가 들어왔다:
관계형 데이터베이스(MySQL, PostgreSQL)라면 NOT NULL 제약, CHECK 제약, 정규식 패턴 등으로 이런 불량 데이터를 입구에서 차단한다. 그런데 RDF 지식 그래프에서는? RDF는 태생적으로 "열린 세계 가정(Open World Assumption)"을 따른다. 정보가 없으면 "모른다"이지 "틀리다"가 아니다. 스키마를 강제하지 않는다. 유연하다. 하지만 바로 그 유연함이 데이터 품질의 블랙홀이 된다.
"RDF는 자유로운 영혼이다. 하지만 자유에는 책임이 따른다. SHACL은 그 책임을 코드로 구현한 것이다."
SHACL(Shapes Constraint Language) 이 바로 이 문제를 풀기 위해 W3C가 만든 표준이다. RDF 데이터의 '품질 검사관' — 데이터 그래프가 정해진 규칙(모양, Shape)을 따르는지 검증하는 언어다.
이 글에서는 SHACL이 왜 만들어졌는지(역사), 어떻게 동작하는지(핵심 개념), 실제로 어떻게 쓰이는지(사례), 그리고 2026년 AI 시대에 왜 더 중요해졌는지(미래)를 차근차근 풀어본다.

2001년, 팀 버너스-리는 Scientific American에 시맨틱 웹의 비전을 발표했다. 기계가 웹의 데이터를 이해하고, 자동으로 추론하고, 지능적으로 연결하는 세상. 이 비전의 기반 기술이 바로 RDF(Resource Description Framework) 다.
RDF는 모든 것을 주어-술어-목적어(Subject-Predicate-Object) 의 트리플로 표현한다:
아름답게 구조화된 데이터다. 그런데 문제가 있다. 밥의 나이가 -5다. RDF는 이걸 전혀 문제 삼지 않는다. RDF의 관점에서 "밥의 나이가 -5"는 문법적으로 완벽한 트리플이기 때문이다.
"잠깐, OWL(Web Ontology Language)이 있잖아? 클래스와 속성에 제약을 걸 수 있지 않나?"
맞다, OWL은 추론(reasoning) 을 위한 언어다. OWL로 "사람의 나이는 0 이상의 정수"라고 정의할 수 있다. 하지만 OWL이 "나이가 -5"인 데이터를 만나면 어떻게 할까?
즉, OWL은 "세상을 설명"하고, SHACL은 "데이터를 검사"한다. 목적 자체가 다른 것이다.
SHACL 이전에도 RDF 검증을 시도한 기술들이 있었다:
| 기술 | 시기 | 접근법 | 한계 |
|---|---|---|---|
| SPIN | 2011 | SPARQL 기반 제약 규칙 | SPARQL 전문 지식 필요, 표준화 안 됨 |
| Resource Shapes | 2014 | OSLC 진영의 형상 기술 | 특정 생태계에 국한 |
| DSP | 2008 | Dublin Core 기반 프로파일 | 범용성 부족, 복잡한 제약 미지원 |
| ShEx | 2014 | 정규 표현식 스타일의 형상 언어 | W3C 표준화 실패, SHACL과 경쟁 |
| SHACL | 2017 | W3C 표준, RDF 기반 제약 + SPARQL 확장 | W3C Recommendation 달성 |
2014년 9월 26일, W3C는 RDF Data Shapes Working Group을 공식 출범시켰다. 미션은 명확했다: "RDF 인스턴스 데이터의 구조적 제약을 기술하고 검증하는 W3C 권고안을 만들어라."
Holger Knublauch(TopQuadrant)와 Dimitris Kontokostas(당시 라이프치히 대학, 현 Google) 등이 편집자로 참여했다. SPIN의 경험, Resource Shapes의 아이디어, ShEx의 이론적 토대가 모두 녹아들었다.
약 3년간의 작업 끝에, 2017년 7월 20일 — SHACL은 W3C Recommendation이 되었다. 시맨틱 웹 역사상 가장 실용적인 표준 중 하나가 탄생한 순간이다.
SHACL의 세계관은 단순하다. 두 개의 그래프가 있다:
핵심 규칙: 검증 과정에서 데이터 그래프와 셰이프 그래프는 절대 변경되지 않는다(immutable). SHACL 프로세서는 순수하게 "읽기 전용"으로 동작한다.
SHACL의 제약 조건은 셰이프(Shape) 라는 단위로 묶인다. 셰이프는 두 종류다:
| 구분 | NodeShape | PropertyShape |
|---|---|---|
| 대상 | 노드 자체(포커스 노드) | 노드의 특정 속성 값 |
| 식별자 | sh:path 없음 | sh:path 있음(필수) |
| 비유 | "이 사람은 반드시 학생이어야 한다" | "이 사람의 이메일은 반드시 있어야 한다" |
| 예시 | sh:class ex:Person | sh:path ex:email; sh:minCount 1 |
쉽게 말하면, NodeShape은 "너는 누구냐" 를 검사하고, PropertyShape은 "네 속성은 올바르냐" 를 검사한다.
셰이프가 검사 규칙이라면, 타겟(Target) 은 그 규칙을 적용할 대상을 지정한다. 5가지 방식이 있다:
SHACL이 제공하는 내장 제약 컴포넌트를 분류별로 정리하면 이렇다:
데이터의 타입을 검사한다.
값의 개수를 검사한다. SQL의 NOT NULL이나 UNIQUE와 비슷하다.
| 제약 | 의미 | 실생활 비유 |
|---|---|---|
sh:minCount 1 | 최소 1개 존재 | "이름은 반드시 입력하세요" |
sh:maxCount 1 | 최대 1개 | "주민번호는 하나만 가능합니다" |
sh:minCount 0 + sh:maxCount 3 | 0~3개 | "취미는 최대 3개까지 선택" |
숫자나 날짜의 범위를 검사한다.
sh:property [
sh:path ex:age ;
sh:minInclusive 0 ;
sh:maxInclusive 150 ;
sh:message "나이는 0~150 사이여야 합니다" ;
] ;
4가지 연산자: sh:minInclusive(이상), sh:minExclusive(초과), sh:maxInclusive(이하), sh:maxExclusive(미만).
텍스트의 패턴과 길이를 검사한다.
추가로 sh:languageIn ("ko" "en" "ja")는 다국어 라벨의 언어 태그를 검증하고, sh:uniqueLang true는 같은 언어로 된 라벨이 중복되지 않도록 보장한다.
두 속성 간의 관계를 검사한다.
| 제약 | 의미 | 예시 |
|---|---|---|
sh:equals | 두 속성의 값이 동일 | email == contactEmail |
sh:disjoint | 두 속성의 값이 겹치지 않음 | 회사 전화 ≠ 개인 전화 |
sh:lessThan | 첫 속성 값 < 둘째 속성 값 | 입사일 < 퇴사일 |
sh:lessThanOrEquals | 첫 속성 값 ≤ 둘째 속성 값 | 시작 시간 ≤ 종료 시간 |
프로그래밍의 논리 연산자와 같다.
실용적인 예시:
# "직원이거나 계약직이어야 한다 (둘 중 하나)"
sh:or (
[ sh:class ex:Employee ]
[ sh:class ex:Contractor ]
) ;
# "블랙리스트에 올라있으면 안 된다"
sh:not [
a sh:NodeShape ;
sh:class ex:Blacklisted ;
] ;
셰이프 안에 셰이프를 중첩한다. 러시아 인형(마트료시카)처럼.
# 주소는 반드시 PostalAddress 셰이프를 따라야 한다
sh:property [
sh:path ex:address ;
sh:node ex:PostalAddressShape ;
] ;
# PostalAddress 셰이프
ex:PostalAddressShape a sh:NodeShape ;
sh:property [
sh:path ex:street ;
sh:minCount 1 ;
sh:datatype xsd:string ;
] ;
sh:property [
sh:path ex:city ;
sh:minCount 1 ;
] .
sh:closed true: 정의되지 않은 속성 사용 금지 (JSON Schema의 additionalProperties: false와 동일)sh:hasValue "active": 특정 값이 반드시 존재해야 함sh:in ("active" "inactive" "pending"): 허용된 값 목록(enum)아래 시뮬레이터에서 직접 제약을 켜고 끄며, 어떤 데이터가 통과하고 실패하는지 확인해 보자:
SHACL의 가장 실용적인 특징은 검증 리포트(Validation Report) 의 상세함이다. 단순히 "통과/실패"만 알려주는 게 아니라, 어디서, 왜, 무엇이 틀렸는지 정확히 알려준다.
W3C 스펙에 실린 대표 예시를 그대로 분석해 보자:
# ── 셰이프 그래프 ──
ex:PersonShape
a sh:NodeShape ;
sh:targetClass ex:Person ; # 모든 Person 인스턴스 대상
sh:property [
sh:path ex:ssn ;
sh:maxCount 1 ; # SSN은 최대 1개
sh:datatype xsd:string ; # 문자열 타입
sh:pattern "^\\d{3}-\\d{2}-\\d{4}$" ; # XXX-XX-XXXX 형식
] ;
sh:property [
sh:path ex:worksFor ;
sh:class ex:Company ; # Company 인스턴스여야 함
sh:nodeKind sh:IRI ; # IRI여야 함(리터럴 불가)
] ;
sh:closed true ; # 정의되지 않은 속성 금지
sh:ignoredProperties ( rdf:type ) . # rdf:type은 예외
# ── 데이터 그래프 ──
ex:Alice a ex:Person ;
ex:ssn "987-65-432A" . # ❌ 패턴 위반 (A는 숫자가 아님)
ex:Bob a ex:Person ;
ex:ssn "123-45-6789" ;
ex:ssn "124-35-6789" . # ❌ maxCount 위반 (SSN이 2개)
ex:Calvin a ex:Person ;
ex:birthDate "1971-07-07"^^xsd:date ; # ❌ closed 위반 (birthDate 미정의)
ex:worksFor ex:UntypedCompany . # ❌ class 위반 (Company가 아님)
결과:
모든 제약이 같은 무게를 갖지는 않는다. SHACL은 3단계 심각도를 제공한다:
sh:property [
sh:path ex:phone ;
sh:minCount 1 ;
sh:severity sh:Warning ; # 전화번호 없어도 치명적이지 않음
sh:message "전화번호를 입력하면 연락이 더 빠릅니다"@ko ;
] ;
SHACL은 RDF 그래프를 탐색하기 위해 7가지 경로(Path) 유형을 지원한다. 이것이 SHACL을 단순한 검증 도구 이상으로 만드는 핵심이다.
| 경로 유형 | 문법 | 의미 | 비유 |
|---|---|---|---|
| Predicate | sh:path ex:email | 직접 속성 | 내 이메일 |
| Sequence | sh:path (ex:knows ex:email) | 경로 체이닝 | 내 친구의 이메일 |
| Alternative | sh:alternativePath (ex:father ex:mother) | 여러 경로 중 하나 | 아버지 또는 어머니 |
| Inverse | sh:inversePath ex:parent | 역방향 탐색 | 나를 부모로 둔 사람 = 자녀 |
| Zero-or-More | sh:zeroOrMorePath rdfs:subClassOf | 0회 이상 반복 (*) | 조상 클래스 전체 |
| One-or-More | sh:oneOrMorePath ex:knows | 1회 이상 반복 (+) | 친구의 친구의 친구... |
| Zero-or-One | sh:zeroOrOnePath ex:spouse | 0회 또는 1회 (?) | 배우자 (있거나 없거나) |
정규표현식의 *, +, ?와 같은 개념이 그래프 탐색에 적용된 것이다. 이를 통해 "친구의 친구의 이메일이 올바른 형식인지"까지 검증할 수 있다.
SHACL Core만으로 충분하지 않을 때, SHACL-SPARQL 확장을 쓴다. SPARQL 쿼리를 제약 조건으로 직접 삽입할 수 있다.
ex:UniqueEmailConstraint
a sh:SPARQLConstraint ;
sh:message "이메일이 다른 사람과 중복됩니다" ;
sh:select """
SELECT $this (ex:email AS ?path) ?value
WHERE {
$this ex:email ?value .
?other ex:email ?value .
FILTER ($this != ?other)
}
""" .
이 예시는 "이메일 주소가 데이터 그래프 전체에서 유일해야 한다"는 제약을 표현한다. SHACL Core의 sh:uniqueLang이나 sh:maxCount로는 불가능한, 글로벌 유일성 검증이다.

2021년, Bogaerts, Jakubowski, Van den Bussche는 흥미로운 논문을 발표했다: "SHACL: A Description Logic in Disguise" (arXiv:2108.06096). 이 논문의 핵심 주장은 도발적이다:
"SHACL은 사실상 기술 논리학(Description Logic)이다."
기술 논리학(DL)은 OWL의 수학적 기반이다. 이 논문은 SHACL의 제약 표현력이 DL의 개념 표현력과 수학적으로 동치(equivalent)임을 증명했다. 즉:
이 발견이 중요한 이유는, SHACL의 계산 복잡도와 표현력의 한계를 DL 이론으로부터 직접 도출할 수 있게 되었기 때문이다. 수십 년간 DL 커뮤니티가 축적한 연구 성과를 SHACL에 바로 적용할 수 있다.
특히, 논문은 SHACL에서 전통적인 DL에 없는 4가지 고유 특성을 식별했다: Zero-or-One 경로, 동등성 테스트(sh:equals), 비교집합 테스트(sh:disjoint), 폐쇄 제약(sh:closed). 이 4가지 각각이 원시적(primitive) 임이 증명되었다 — 하나라도 빼면 SHACL의 표현력이 줄어든다.
SHACL은 활발한 학술 연구 대상이기도 하다:
| 논문 | 학회/연도 | 핵심 기여 |
|---|---|---|
| Corman, Reutter, Savkovic | ISWC 2018 | 재귀적 SHACL의 형식 의미론 제안. SHACL 검증이 NP-hard임을 증명 |
| Figuera, Rohde et al. | WWW 2021 | Trav-SHACL: 탐색 순서 최적화로 28.93배 빠른 검증 엔진 |
| Pareti & Konstantinidis | Reasoning Web 2021 | SHACL의 형식 체계, 의미론, 충족가능성, 포함관계에 대한 종합 리뷰 |
| Rabbani et al. | VLDB 2023 | 대규모 지식 그래프에서 SHACL 셰이프 자동 추출 |
| Ke & Acosta | VLDB 2024 | 추론 연동 SHACL 검증의 효율적 알고리즘 |
| Ahmetaj et al. | ACM Web 2025 | SHACL, ShEx, PG-Schema의 공통 형식적 기반 정립 |
EU는 DCAT-AP 3.0 표준에서 SHACL을 사용하여 70개 이상의 국가 데이터 제공기관이 제출하는 메타데이터를 검증한다. 유럽위원회는 TopBraid SHACL API 기반의 SEMIC SHACL Validator를 운영하며, 2025년에는 유럽 건강 데이터 공간(EHDS) 전용 SHACL 검증기까지 출시했다 (규정 EU 2025/327).
유럽 건강 데이터 공간(EHDS)은 HealthDCAT-AP 기반의 SHACL 검증기를 운영한다. 임상 정보 모델링 이니셔티브(CIMI)에서는 SHACL 셰이프로 EHR(전자건강기록) 데이터의 용어 바인딩 오류와 모델링 오류를 탐지한다.
금융 산업 온톨로지(FIBO)의 EDM Council은 2018년부터 SHACL을 공식 채택했다. "FIBO in SHACL: The Next Step in Data Validation and Interoperability" 세션이 EDW 2018에서 발표되었으며, OWL만으로는 불가능한 교차 기업 데이터 검증을 SHACL이 해결한다.
Google은 오픈소스 프로젝트 Schemarama를 통해 Schema.org 구조화된 데이터의 SHACL + ShEx 검증을 제공한다. 수십억 개의 웹 마크업이 올바른 형식을 따르는지 대규모로 검증하는 인프라다.
W3C의 공식 기록에 따르면, SHACL을 공식 채택한 기업들:

2024~2026년, AI 업계는 RAG(Retrieval-Augmented Generation) 과 지식 그래프를 결합하는 패러다임으로 급속히 이동하고 있다. GraphRAG, Cognee, LightRAG 같은 기술이 LLM의 환각(hallucination)을 줄이기 위해 구조화된 지식을 활용한다.
여기서 핵심 질문이 등장한다: "지식 그래프에 넣는 데이터의 품질은 누가 보장하는가?"
LLM이 비정형 텍스트에서 엔티티와 관계를 추출할 때, 그 결과가 온톨로지의 규칙을 따르는지 SHACL로 검증하는 것이다. "쓰레기가 들어가면 쓰레기가 나온다(Garbage In, Garbage Out)" — SHACL은 이 입구에서 품질을 보증하는 게이트키퍼다.
2025년 발표된 논문 "Stemming Hallucination in Language Models Using a Licensing Oracle" (Emanuilov & Ackermann, arXiv:2511.06073)는 SHACL을 LLM 환각 방지의 핵심 도구로 활용한 사례다. LLM이 생성한 사실(fact)을 지식 그래프에 넣기 전, SHACL 검증기가 라이센싱 오라클(Licensing Oracle) 로 작동하여 통과 여부를 결정한다. 결과는 놀라웠다:
추상 정밀도(Abstention Precision) = 1.0 — SHACL 검증을 통과하지 못한 답변은 100% 출력하지 않았고, 허위 답변은 0건이었다.
또한 xpSHACL (Publio & Labra Gayo, 2025)은 RAG 기반으로 SHACL 위반 사유를 자연어로 설명해주는 시스템이다. 868개 온톨로지에서 테스트하여 99.48%의 설명 캐시 적중률을 달성했다. 비기술 사용자도 왜 데이터가 거부되었는지 이해할 수 있다.
W3C는 SHACL의 다음 버전인 SHACL 1.2를 활발히 개발 중이다:
SHACL 1.2의 핵심 변화는 추론 규칙의 내장화다. 기존에는 검증만 가능했다면, 1.2부터는 SHACL 자체가 추론 엔진 역할도 수행한다. 또한 RDF 1.2의 구문화(reification) 지원, 데이터 타입 유니온의 간소화된 문법 등이 포함된다.
"JSON Schema로도 데이터 검증 가능하잖아?"라는 질문이 나올 수 있다. 차이점을 정리하면:
| 기준 | JSON Schema | SHACL |
|---|---|---|
| 대상 데이터 | JSON 문서 | RDF 그래프 |
| 그래프 탐색 | 트리 구조만 (JSON Pointer) | 임의 경로, 역방향, 반복 가능 |
| 추론 연동 | 없음 | RDFS/OWL 추론 + SPARQL 확장 |
| 글로벌 제약 | 같은 문서 내에서만 | 전체 그래프 대상 (SPARQL 확장) |
| 타겟 지정 | 파일/경로 기반 | 클래스, 속성, 노드 등 다양 |
| 도구 생태계 | 매우 풍부 (AJV 등) | 성장 중 (pySHACL, TopBraid 등) |
| 학습 곡선 | 낮음 | 중간 (RDF 지식 필요) |
요약하면: JSON Schema는 문서 검증에 최적화되어 있고, SHACL은 그래프 검증에 최적화되어 있다. 지식 그래프를 다룬다면 SHACL이 정답이다.
아래 인터랙티브 도구로 직접 SHACL 셰이프를 구성하고, 실시간으로 Turtle 문법을 확인해 보자:
from pyshacl import validate
data_graph = """
@prefix ex: <http://example.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ex:Alice a ex:Person ;
ex:name "Alice Kim" ;
ex:age 28 ;
ex:email "alice@example.com" .
ex:Bob a ex:Person ;
ex:age -5 .
"""
shapes_graph = """
@prefix ex: <http://example.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ex:PersonShape a sh:NodeShape ;
sh:targetClass ex:Person ;
sh:property [
sh:path ex:name ;
sh:minCount 1 ;
sh:datatype xsd:string ;
] ;
sh:property [
sh:path ex:age ;
sh:minInclusive 0 ;
sh:maxInclusive 150 ;
] ;
sh:property [
sh:path ex:email ;
sh:minCount 1 ;
] .
"""
conforms, results_graph, results_text = validate(
data_graph,
shacl_graph=shapes_graph,
data_graph_format="turtle",
shacl_graph_format="turtle",
)
print(f"적합: {conforms}")
print(results_text)
# 출력: 적합: False
# Bob: name 누락, age 범위 초과, email 누락
인체에 면역 체계가 없으면 어떻게 될까? 아무리 건강한 사람도 사소한 세균에 쓰러진다. 데이터 시스템도 마찬가지다. 아무리 정교한 온톨로지를 설계하고, 아무리 강력한 LLM을 연결해도 — 입력되는 데이터의 품질이 보장되지 않으면 전체 시스템이 무너진다.
SHACL은 지식 그래프의 면역 체계다.
"좋은 데이터는 좋은 AI의 전제 조건이다. SHACL은 그 전제를 코드로 보장한다."