클래스, 관계, 공리: 어휘를 짓는 일
📍 현재 위치: 1부 · 모델의 기초 — 2장. 상위 척추가 자리를 잡았으니, 이제 어떤 종류의 대상이 존재하는가에서 그것들을 실제로 적어 내는 기예로 넘어갑니다 — 하나의 클래스, 하나의 관계, 그리고 그 어휘가 일을 하게 만드는 공리들로 말입니다.
지난 장에서는 바이오공정을 이루는 살림살이를 BFO의 범주에 분류해 넣었습니다. 그 덕분에 우리는 Batch가 지속체이고 발효가 발생체라는 것을 알게 되었습니다 — 하지만 그것만으로는 아직 쓸 수 있는 Batch를 손에 넣은 것이 아닙니다. 거기에 이르려면 우리는 직접 저작(author)해야 합니다. 클래스를 선언하고, derivedFrom 관계를 선언하고, 그리고 — 진짜 온톨로지를 그럴듯하게 포장한 용어집과 갈라놓는 바로 그 부분 — 우리가 선언한 것 위에서 컴퓨터가 추론할 수 있게 해 주는 공리(axiom)를 적어야 합니다. 이번 장은 바로 그 저작이라는 행위이며, 데이터 관리 책이 소개했던 그 RDF/OWL/SHACL 언어를 이번에는 우리 자신의 어휘에 적용해 봅니다.
제빵을 떠올려 보세요. 클래스(class)는 쿠키 커터 — "Batch"라는 모양 — 입니다. 인스턴스(instance)는 그 커터로 찍어낸 실제 쿠키 하나 — BATCH-2026-001 — 입니다. 관계(relation)는 쿠키들을 서로 묶는 실입니다 — 이 쿠키는 저 쿠키로부터 derivedFrom(파생됨)이라는 식이죠. 그리고 공리(axiom)는 매번 따로 부탁하지 않아도 주방 검사관이 알아서 강제하는 규칙입니다. "모든 쿠키는 정확히 하나의 라벨을 가진다", "쿠키는 결코 오븐이기도 할 수는 없다", "A가 B에서 나오고 B가 C에서 나왔다면, A는 C에서 나온 것이다" 같은 규칙들이죠. 클래스와 인스턴스는 모양과 사물을 주고, 공리는 기계가 쟁반 전체를 스스로 검사하고 확장하게 해 주는 것입니다.
이 장에서 다루는 내용
우리는 작은 바이오공정 어휘를 OWL로 저작하되, RDF 트리플을 Turtle로 적는 방식으로 씁니다. 그다음 제 몫을 하는 공리들 — 서브클래스, 정의역과 치역, 추이성, 서로소 — 을 더하고, 추론기가 그것들을 써서 새로운 사실을 추론하고 모순을 잡아내는 것을 지켜봅니다. 하나의 클래스 정의를 필드별로 해부하고, 품질 설계(Quality by Design)의 파라미터-속성 연결이 어떻게 저작된 관계가 되는지를 보이며, 이 기예를 보기보다 어렵게 만드는 열린 세계의 함정과 과도한 공리화의 덫으로 마무리합니다.
척추에서 구문으로: OWL의 클래스와 속성
데이터 책에서 다룬 세 원자를 떠올려 봅시다. 클래스(class)는 범주(Batch, CapturePool)이고, 인스턴스(instance)는 구체적인 한 구성원(BATCH-2026-001)이며, 관계(relation)(또는 속성, property)는 대상들을 연결합니다(derivedFrom) [1]. 이것들을 적어 내는 토대는 RDF로, 모든 사실을 트리플 — 주어, 술어, 목적어 — 로 표현하며, 각 부분은 전 세계적으로 유일한 IRI로 명명됩니다 [2]. 그 위에 얹히는 계층이 웹 온톨로지 언어 OWL 2로, 추론기가 작동할 수 있을 만큼 형식적으로 클래스와 속성이 무엇인지를 진술할 수 있게 해 줍니다 [1].
OWL은 일찍 못 박아 둘 만한 한 가지 구분을 그립니다. 객체 속성(object property)은 한 대상을 다른 대상에 연결하고(derivedFrom은 한 로트를 모(母)로트에 관계 짓습니다), 데이터타입 속성(datatype property)은 한 대상을 리터럴 값에 연결합니다(monomerPct는 한 로트를 98.611이라는 숫자에 관계 짓습니다). 이는 오픈소스 지식 그래프 장이 "간선이냐 값이냐"라고 부르는 바로 그 갈림길이며, 따라갈 수 있는 관계와 읽어낼 수 있는 측정값의 차이입니다. 다음은 우리 어휘의 씨앗을 Turtle로 적은 것으로, 동반 저장소가 IOF와 앨로트로프(Allotrope)에 정렬하는 것과 같은 모양입니다.
# bioproc.ttl — the local vocabulary, aligned up to IOF Core (illustrative).
@prefix bp: <https://example.org/bioproc#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
bp:Material a owl:Class ; rdfs:label "Bioprocess material" .
bp:Batch a owl:Class ; rdfs:label "Bioreactor batch" ;
rdfs:subClassOf bp:Material .
bp:CapturePool a owl:Class ; rdfs:label "Protein A capture pool" ;
rdfs:subClassOf bp:Material .
bp:derivedFrom a owl:ObjectProperty ;
rdfs:label "derived from" .
bp:monomerPct a owl:DatatypeProperty ;
rdfs:label "SEC %monomer" ;
rdfs:range xsd:float .
여기까지는 아직 아무런 논리도 일하고 있지 않습니다 — 이것들은 선언, 곧 어휘의 명사와 동사일 뿐입니다. 지능은 우리가 그것들에 대해 무엇을 말하느냐에서 나옵니다.
제 몫을 하는 공리들
공리(axiom)는 컴퓨터가 모델을 추론할 수 있도록 모델을 제약하는 논리적 진술입니다 [1]. 바이오공정 온톨로지에서 일의 대부분을 떠맡는 것은 네 종류이며, 각각은 구체적인 능력 하나를 사 줍니다.
서브클래스(subclass)(rdfs:subClassOf)는 한 클래스가 다른 클래스의 한 종류임을 말합니다. bp:ProductionBioreactor rdfs:subClassOf bp:Bioreactor라고 선언하면 모든 생산 생물반응기가 생물반응기이다는 뜻이 되므로, 생물반응기에 참인 사실은 무엇이든 자동으로 상속됩니다 — 일반 클래스에서 제약을 한 번만 진술하면 모든 특수화가 그것을 공짜로 물려받습니다.
정의역과 치역(domain and range)은 한 속성이 무엇을 연결해도 되는지를 못 박습니다. bp:derivedFrom rdfs:domain bp:Material ; rdfs:range bp:Material은 양쪽 끝이 모두 물질이어야 한다고 말합니다. 이제 누군가 BATCH-2026-001 derivedFrom SomeOperator라고 적으면, 추론기는 SomeOperator가 반드시 bp:Material이어야 한다고 추론할 수 있습니다 — 그리고 만약 그것이 Person으로 선언되어 있고 Person이 Material과 서로소라면, 그 그래프는 비일관(inconsistent)으로 표시됩니다. 정의역과 치역은 헐거운 간선을 타입이 부여된 간선으로 바꿉니다.
추이성(transitivity)은 이 책 전체에서 단연 가장 값진 공리입니다. bp:derivedFrom a owl:TransitiveProperty라고 선언하면, DS-001 derivedFrom PApool-001이고 PApool-001 derivedFrom BATCH-2026-001이라면 추론기에게 DS-001 derivedFrom BATCH-2026-001이라고 알려 주는 것입니다 — 사슬을 끝까지 내려가도록, 그 누구도 장거리 연결을 주장하지 않아도 말이죠. 그 한 단어 덕분에 계보 질문은 원료의약품에서 세포 은행까지 의미의 단 한 번의 도약으로 닿을 수 있으며, 이는 오픈소스 장이 그것을 걸어가는 데 쓰는 SPARQL 속성 경로를 보완합니다.
서로소(disjointness)는 척추 장이 경고했던 바로 그 오류를 잡아냅니다. bp:Batch owl:disjointWith bp:CellCultureProcess는 어떤 것도 배치(지속체)이면서 동시에 발효(발생체)일 수는 없다고 말합니다 — "배치가 곧 실행이다"라는 그 고전적인 혼동이죠. 그리고 bp:Material owl:disjointWith bp:Equipment는 어떤 것도 물질이면서 동시에 그것을 담는 용기일 수는 없다고 말합니다 — 순진한 다중 출처 적재가 만들어 내는, 더 미묘한 "배치가 곧 생물반응기다"라는 혼동입니다. 하나의 IRI에 두 타입을 모두 주장하면 모델은 모순이 됩니다. DL 추론기(HermiT, ELK)는 그것을 보고하고, 그리고 — 대부분의 파이프라인이 돌리는 경량 OWL-RL 추론기는 owl:disjointWith에 작동하지 않으므로 — 출하 게이트 SHACL 형상이 닫힌 세계 가드를 함께 지녀 실행 가능한 검증기에서도 그것을 잡아냅니다. 서로소는 지속체/발생체 규율과 물질/장비 규율이 조언에 그치지 않고 강제되는 규칙이 되게 하는 방법입니다.
bp:ProductionBioreactor rdfs:subClassOf bp:Bioreactor .
bp:derivedFrom rdfs:domain bp:Material ; rdfs:range bp:Material ;
a owl:TransitiveProperty .
bp:Batch owl:disjointWith bp:CellCultureProcess . # material continuant ≠ occurrent
bp:Material owl:disjointWith bp:Equipment . # the batch ≠ the vessel
공리가 일하는 모습: 주장된
derivedFrom 간선(실선)은 추론기가 추이성으로 장거리 연결(점선)을 추론하게 해 주고, 정의역과 치역은 양 끝에 타입을 부여하며, Batch와 CellCultureProcess 사이의 서로소 막대는 "배치는 실행이 아니다"를 강제되는 규칙으로 바꿔 줍니다.
저자가 AI의 도움을 받아 직접 제작한 그림입니다.
추론이 사 주는 것: 추론과 모순 탐지
공리는 문서가 아닙니다. 실행 가능한 것입니다. 추론기(reasoner) — Protégé에 딸려 오는 HermiT나 ELK 같은 분류 엔진 — 를 어휘와 사실 위에서 돌리면 두 가지 일이 일어납니다 [5]. 첫째, 추론(inference)입니다. 추론기는 그 누구도 진술하지 않은 사실을 도출합니다. 위의 추이적 계보 같은 것이나, ProductionBioreactor라고 주장된 인스턴스가 따라서 Bioreactor이자 장비이며 BFO 물질 개체(독립적 지속체)라는 결론처럼 말이죠 — 장비는 BFO 물질 개체이기는 하지만 bp:Material은 아니며, 이 둘은 여기서 서로소라는 점에 유의하세요. 둘째, 모순 탐지(contradiction detection)입니다. 주장된 사실이 공리를 위반하면 — 공정이기도 한 배치, 목적어가 물질일 수 없는 derivedFrom — 추론기는 그 그래프를 비일관으로 보고하고 충돌 지점을 가리킵니다. 관계형 데이터베이스는 스키마만으로는 둘 중 어느 것도 하지 못합니다. 공리화된 온톨로지는 둘 다 공짜로 해 주며, 이것이 바로 저작 비용을 치를 이유 전부입니다. 실행 예제 위에서 추론기를 돌리면 둘이 한꺼번에 일어납니다 — 새 사실이 나타나고, 심어 둔 모순이 잡힙니다.
# Real output from validate.py (owlrl OWL-RL closure + SHACL over the running example).
[1] parsed 2100 triples (bioproc + align + instances)
[2] reasoned: 2100 -> 7089 triples after OWL-RL closure
transitive derivedFrom inferred DS-001 -> WCB-CHO-001: True
transitive derivedFrom inferred DS-001 -> RCB-CHO-001: True
planted Batch-is-a-Process caught (conforms False): True
planted Batch-also-Bioreactor caught (conforms False): True
추론기는 그 누구도 주장하지 않은 장거리 derivedFrom 연결을 만들어 냈고, 닫힌 세계 가드는 "배치가 실행이다"와 "배치가 곧 용기다"라는 혼동을 둘 다 거부했습니다 — 둘 중 어느 것도 원래 트리플에는 진술되어 있지 않았던 것입니다. (conforms False 판정은 SHACL의 것입니다. OWL-RL은 owl:disjointWith에 작동하지 않으므로, 실행 가능한 포착은 형상이 하고, 공리는 Protégé DL 추론기가 직접 강제하는 것입니다.)
OWL은 추론하고, SHACL은 검증한다
누구나 한 번은 걸려 넘어지는 미묘한 지점이 하나 있는데, 이것이 어떤 도구를 집어 들지를 결정합니다. OWL은 열린 세계(open-world) 방식입니다. 진술되지 않은 것은 거짓이 아니라 단지 알려지지 않았을 뿐이라고 가정하죠. 그것은 추론에는 정확히 옳습니다 — 부모 간선이 아직 적재되지 않았다는 이유만으로 추론기가 배치에 부모가 없다고 결론짓기를 바라지는 않을 테니까요. 하지만 데이터 검증에는 정확히 틀렸습니다. 거기서는 빠진 필수 필드가 진짜로 오류이기 때문입니다. "이 출하된 로트에는 출하 상태가 없다"는 출하 점검에서 실패해야지, "상태 미상"으로 너그럽게 취급되어서는 안 됩니다.
그 검증 작업은 SHACL, 곧 형상 제약 언어(Shapes Constraint Language)의 몫입니다. SHACL은 닫힌 세계 해석 아래 그래프를 형상에 비추어 검사하고 — "모든 DrugSubstance 또는 DrugProduct 로트는 이 목록에서 가져온 정확히 하나의 releaseStatus를 가져야 한다" — 위반을 보고합니다 [3]. 역할 분담은 깔끔하며 외워 둘 가치가 있습니다. OWL은 대상이 무엇을 의미하는지를 말하고 그 귀결을 추론하며, SHACL은 유효한 기록이 무엇을 담고 있어야 하는지를 말하고 그것을 통과시키거나 막습니다. 추이적 계보는 OWL의 일이고, 우리가 나중에 짓는 출하 게이트는 SHACL의 일입니다. 같은 어휘에 대해 둘 다를 저작하는 것이 그래프를 동시에 똑똑하고 또 신뢰할 만하게 만드는 길입니다.
두 엔진, 하나의 어휘: OWL의 열린 세계 추론기는 새 사실을 추론하고 모순을 잡아내며, SHACL의 닫힌 세계 검증기는 기록이 유효한 기록이 담아야 할 것을 담고 있도록 강제합니다.
저자가 AI의 도움을 받아 직접 제작한 그림입니다.
하나의 클래스 정의 해부
저작을 목록이 아니라 하나의 기예로 보려면, bp:Batch 클래스를 필드별로 뜯어보면 됩니다 — 모든 줄이 실제 선언이고, 모든 줄이 무언가를 사 줍니다. rdfs:label("Bioreactor batch")은 사람이 읽을 수 있는 이름으로, 기계가 쓰는 IRI와는 구별됩니다. rdfs:subClassOf는 이것을 bp:Material 아래에, 그리고 그것을 통해 IOF 코어와 BFO 아래에 놓습니다 — 맞춤형 어댑터 없이도 상호운용 가능하게 만드는 그 정렬이죠. owl:disjointWith bp:CellCultureProcess는 지속체/발생체 경계를 강제되는 규칙으로 부호화합니다. 클래스가 지니는(bears) 속성들 — 부모를 향한 bp:derivedFrom 간선, 그리고 출하 성질인 bp:releaseStatus와 bp:monomerPct — 은 정의역을 bp:Material(배치의 상위 클래스)로 두고 선언되므로, 그중 어느 하나를 주장하면 주어에 bp:Batch가 아니라 bp:Material이라는 타입이 부여됩니다. 그 넓이는 의도된 것입니다. 출하 상태와 단량체 결과를 실제로 지니는 출하된 로트는 원료의약품과 완제의약품 로트이며, 이들 역시 bp:Material이므로, 이 속성들을 bp:Batch로 좁혔다면 모든 로트를 배치로 잘못 타입 지정했을 것입니다. 그리고 주석(annotation)(rdfs:comment, skos:definition, 출처 메모)은 그 클래스가 왜 존재하는지를 기록하는데, 이것은 미래의 유지보수자와 감사관 모두에게 필요한 것입니다.
하나의 클래스를 완전히 펼친 모습: 사람을 위한 라벨, 위로 정렬해 주는 서브클래스 사슬, 범주 오류를 막는 서로소 공리, 그것이 지니는 속성들, 그리고 왜 존재하는지를 기록하는 주석.
저자가 AI의 도움을 받아 직접 제작한 그림입니다.
이것은 이 시리즈의 나머지가 데이터 포인트에 적용하는 바로 그 식별 카드 규율을 스키마에 적용한 것입니다. 측정값이 단위와 품질을 데리고 다니듯, 클래스는 자신의 정렬, 제약, 정의를 데리고 다닙니다 — 그래서 의미가 모델러의 기억이 아니라 모델 안에 있게 되는 것입니다.
저작된 관계로서의 품질 설계
서문은 품질 설계(QbD)가 실은 하나의 온톨로지라고 주장했습니다. 바로 여기서 그것이 문자 그대로가 됩니다. 개발 팀이 그토록 애써 확립하려는 연결 — 이 핵심 공정 파라미터가 저 핵심 품질 속성에 영향을 미친다 — 은 선언되기를 기다리는 하나의 관계일 뿐입니다. bp:affectsQuality, 곧 bp:ProcessParameter에서 bp:QualityAttribute로 향하는 객체 속성이죠. 그것을 선언하면 bp:FeedRate bp:affectsQuality bp:MonomerPct-CQA 같은 사실이 산문 보고서 속에 살기를 멈추고 질의 가능한 간선이 됩니다 — 그래서 조사자가 나중에 그래프에 "어떤 파라미터가 단량체 순도에 영향을 미치는가?"라고 물어 읽을거리 숙제가 아니라 답을 얻을 수 있습니다. 우리는 이것을 공정 개발 장에서 본격적으로 풀어냅니다. 여기서의 요점은, 공정 개발에서 가장 귀하게 여겨지는 지식이 구조적으로는 저작된 관계 하나 더라는 것입니다.
미해결 과제: 일관됨은 옳음과 같지 않다
추론기는 당신의 온톨로지가 일관됨 — 내적 모순이 없음 — 을 증명할 수 있습니다. 하지만 그것이 옳음 — 공장을 충실히 반영한 모델임 — 을 증명할 수는 없습니다. 이 둘은 서로 다른 보증이며, 둘을 뭉뚱그리는 것이 공리화된 모델의 조용한 실패입니다. 완벽하게 일관되면서도 틀린 것을 말하는 온톨로지를 저작할 수 있습니다. 방향이 뒤집힌 derivedFrom, 선언하는 것을 잊는 바람에 "배치가 실행이다" 오류가 말없이 빠져나가게 만든 서로소, "정확히 하나"여야 하는데 "적어도 하나"로 남겨 둔 카디널리티 같은 것이죠. 논리는 일관성을 점검하지, 진리를 점검하지 않습니다.
이 기예에 특유한 함정이 둘 더 있습니다. 첫째는 열린 세계의 의외성(open-world surprise)입니다. OWL은 빠진 사실을 미상으로 취급하므로, OWL 추론기는 필수 필드가 없다고 알려 주지 않습니다 — 초심자는 알려 주리라 기대하다가, SHACL만이 잡아냈을 빈틈을 그대로 내보냅니다. 둘째는 과도한 공리화(over-axiomatization)입니다. 당신이 더하는 모든 공리는 추론기가 지켜야 할 약속이며, 빽빽하게 제약된 온톨로지는 계산적으로 비싸지거나 심지어 결정 가능한 OWL DL 프로파일을 벗어나 추론이 더 이상 안정적으로 종료되지 않는 영역으로 들어설 수 있습니다 [5]. 기예는 중요한 오류를 잡아내기에 딱 충분할 만큼만, 그 이상은 아니게 공리화하는 데 있습니다. 그래서 이 장의 정직한 기준은 "추론이 되는가?"가 아니라 "옳은 세계에 대해 추론하고, 거기서 멈추는가?"입니다 — 어떤 엔진도 당신 대신 내려 주지 않는 판단이며, 온톨로지 저작이 생성된 산출물이 아니라 검토되고 관장되는 인간의 실천으로 남아 있는 이유입니다.
왜 중요한가
이후의 모든 장은 새로운 클래스와 관계를 선언하며, 그 선언의 품질이 그래프가 자산이 될지 부채가 될지를 결정합니다. 공리는 데이터에 단지 이름표를 붙이는 어휘와 그것을 점검하고 확장하는 어휘의 차이입니다. 추이성은 계보를 걸어갈 수 있게 만들고, 서로소는 범주 오류를 시끄럽게 만들며, 정의역과 치역은 간선에 타입을 부여합니다. 공리를 제대로 잡으면 모델은 자라나면서 스스로의 무결성을 방어합니다. 잘못 잡거나 빠뜨리면 IRI가 붙은 값비싼 스프레드시트를 갖게 될 뿐입니다. 이 접근법 전체의 지렛대는 바로 이 장에 살고 있습니다.
실제 현장에서는
이것을 텍스트 편집기로 저작하지는 않습니다. 사실상의 표준 도구는 스탠퍼드(Stanford)의 무료 오픈소스 온톨로지 편집기 Protégé로, 도메인 전문가가 클래스와 속성을 시각적으로 정의하고, 무언가를 내보내기 전에 추론기를 돌려 일관성을 점검하고 추론 결과를 살펴볼 수 있게 해 줍니다 [4]. 그 밑에 깔린 RDF/OWL/SHACL은 교환 형식이며, 이는 스타일이 입혀진 페이지 밑에 깔린 HTML이 형식인 것과 같습니다. 규제 환경에서는 저작된 온톨로지 그 자체가 통제 대상 산출물입니다 — 버전이 매겨지고, 검토되고, 변경 통제되죠 — 이는 6부 모델 거버넌스의 주제입니다. 하나의 공리는 공장을 어떻게 모델링할지에 대한 결정이며, 규제 대상 시스템에 관한 결정은 노트북 한 대 위의 버전 없는 파일에서 내려지지 않습니다.
핵심 용어
- 클래스 / 인스턴스 / 관계(class / instance / relation) — 대상의 범주; 구체적인 한 구성원; 대상들 사이의 연결.
- OWL(웹 온톨로지 언어, Web Ontology Language) — RDF에 형식 논리를 더해 추론기가 사실을 추론하고 모순을 탐지할 수 있게 하는 W3C 언어.
- 객체 속성 / 데이터타입 속성(object property / datatype property) — 다른 대상으로 향하는 관계(걸어갈 수 있는 간선)와 리터럴 값으로 향하는 관계(읽어낼 수 있는 측정값)의 대비.
- 공리(axiom) — 모델을 제약하는 논리적 진술: 서브클래스, 정의역/치역, 추이성, 서로소, 카디널리티.
- 추이 속성(transitive property) — A→B이고 B→C이면 A→C가 성립하는 OWL 관계(
derivedFrom같은)로, 계보를 어떤 깊이까지든 추론 가능하게 만듦. - 서로소(disjointness) — 두 클래스가 어떤 구성원도 공유하지 않음을 선언하는 공리로, 한 대상에 대해 둘 다를 주장하면 표시되는 모순이 됨(지속체/발생체 가드).
- 추론기(reasoner) — OWL 온톨로지 위에서 추론된 사실을 계산하고 일관성을 점검하는 엔진(HermiT, ELK).
- 열린 세계 가정(open-world assumption) — 진술되지 않은 사실이 거짓이 아니라 미상이라는 OWL의 입장; 추론에는 옳고 검증에는 틀림.
- SHACL — 그래프가 유효한 기록이 담아야 할 것을 담고 있는지 검증하는 닫힌 세계의 형상 제약 언어(Shapes Constraint Language).
- Protégé — OWL 온톨로지를 저작하고 추론하는, 표준이 된 무료 오픈소스 편집기.
다음 이야기
이제 우리는 클래스를 선언하고, 관계로 그것들을 잇고, 추론기가 강제하는 공리로 제약할 수 있습니다. 하지만 우리가 적은 모든 주어, 술어, 값은 아직 살펴보지 않은 한 가지를 전제하고 있습니다. 바로 하나의 이름이 어디서나 같은 것을 뜻하고, 하나의 숫자가 결코 단위 없이 떠돌지 않는다는 것이죠. 다음 장 식별자와 단위: IRI, QUDT, 그리고 타입 지정 값은 그 보장을 구체화합니다 — 두 시스템의 BATCH-2026-001이 충돌하지 못하게 막는 전 세계적으로 유일한 식별자, 그리고 98.611이 한 시스템에서는 분수, 다른 시스템에서는 퍼센트를 뜻하는 일이 다시는 없게 막는 단위·데이터타입 규율을요.