4

속성 설계와 제약 3층

관계·속성·제약 설계

학습 목표
  • 클래스별 핵심 속성과 식별자 우선 원칙을 적용한다
  • source 속성이 왜 전 이벤트 필수인지 안다
  • 제약을 세 층으로 나눠 강제 주체를 정한다

속성 설계 — 각 기둥의 표준 장착 세트

주요 클래스의 핵심 속성(발췌)과 원칙입니다. 식별자 우선, 표준 단위 명시, 원천 기록.

클래스핵심 속성비고
VesselimoNumber(키), mmsi, callSign, name, vesselType, loa, beam, grossTonnageMMSI·호출부호는 이력 관리 대상(AN-09)
ContainercontainerNumber(키, ISO 6346), sizeType, tareWeight, maxGross체크디지트 검증(CO-03)
PortunLocode(키), name, country, position(point)공간 타입
BerthberthCode(키), length, depth, position(point)시설제원 데이터 정합
PortCallcallId(키, MRN 호환 로컬), voyageNumber, status코스 1 식별자 정책
각 EventeventType, E/R/P/A 4종, timeBasis, source(원천 시스템), recordedAtsource 는 전 이벤트 필수
DangerousGoodsunNumber, imdgClass, packingGroupIMDG 정합(CO-02)
MetricmetricType, value, unit, periodStart, periodEnd, definitiondefinition 에 TIC 4.0 기준 명시(PL-06)

source 속성을 강조해 둡니다

같은 접안 시각도 입항신고(Port-MIS)와 관제 기록(VTS)이 다를 수 있습니다. AN-10(신고-실적 불일치)은 바로 그 차이를 묻는 CQ입니다. 원천을 기록하지 않으면 이 CQ는 영구히 답할 수 없습니다.

그리고 이것이 할루시네이션 제로 정책(코스 4)의 데이터 기반이기도 합니다 — 모든 답변은 source가 있는 사실로만 조립됩니다.

제약 설계 — 그래프가 스스로 지키는 규칙

제약은 세 층으로 나눠 겁니다. 층을 구분하는 이유는 강제 수단이 각각 다르기 때문입니다.

L1. DB 제약 (Neo4j 가 강제)

유일성·존재성입니다. 다음 모듈에서 Cypher로 구현합니다.

Vessel.imoNumber UNIQUE / Container.containerNumber UNIQUE
Port.unLocode UNIQUE / PortCall.callId UNIQUE
각 Event.actualTime EXISTS(확정 이벤트에 한해)

⚠️ 이 목록은 다음 모듈에서 한 줄 개정됩니다. 존재성 제약(actualTime EXISTS)이 Neo4j Enterprise 전용 기능이라 Community 에서는 DB 로 강제할 수 없다는 사실을 에디션을 고르면서 만나게 됩니다. 설계가 현실을 만나 수정되는 첫 사례이니, 지금은 "이렇게 걸고 싶다"는 의도로 읽고 다음 모듈에서 결말을 확인하세요.

L2. 스키마 검증 (적재 파이프라인이 강제)

값 형식·범위·관계 카디널리티입니다. ISO 6346 체크디지트, imdgClass ∈ {1..9}, "PortCall은 정확히 1척의 Vessel에 속한다" 등.

⚠️ Neo4j Community는 이런 제약을 DB 수준에서 못 겁니다(속성 존재·유일성 정도만 가능). 그래서 코스 3 ETL의 검증 단계가 담당합니다. 에디션 선택이 아키텍처에 미치는 실례입니다 — 다음 모듈에서 에디션을 고를 때 이 비용을 기억하세요.

L3. 도메인 규칙 (질의로 감시)

"위험물 이격 규정 준수"(CO-02), "통관 미완료 반출 금지"(CO-04) 같은 비즈니스 규칙입니다. 이건 막는 게 아니라 위반을 탐지하는 CQ로 상시 감시합니다.

Rule 기둥의 클래스들이 규칙 자체를 데이터로 들고 있으므로, 규정이 바뀌면 코드가 아니라 그래프의 Rule 노드를 갱신합니다. CO-09(규정 개정 영향 분석)가 가능해지는 구조입니다.

용어