# WING-GIS Architecture Design ## 해양경찰청 통합 GIS 위치정보시스템 --- ## 1. System Overview ``` WING-GIS System Architecture ============================ [Browser / ECDIS / Mobile] | v +-----------------+ +------------------+ +------------------+ | React 19 SPA | | Nginx / Gateway | | Keycloak SSO | | MapLibre+deck.gl|<--->| (API Gateway) |<--->| (INR-04 Auth) | | (wing-gis-web) | | | | | +-----------------+ +------------------+ +------------------+ | +--------------+--------------+ | | | +-----v----+ +-----v----+ +------v-----+ | GIS API | | Vessel | | Analysis | | Service | | Signal | | Service | | (SFR-01~ | | Service | | (SFR-09) | | SFR-04) | | (SFR-05~ | +------+-----+ +-----+----+ | SFR-08) | | | +-----+----+ | | | | +-----v--------------v--------------v-----+ | PostgreSQL + PostGIS | | (wing_gis_db / wing_vessel_db) | +-----------------------------------------+ | | +-----v----+ +-----v-----------+ | Redis | | Kafka / RabbitMQ| | (Cache) | | (Signal Stream) | +----------+ +-----------------+ ``` --- ## 2. Technology Stack ### Frontend (구현 완료) | Category | Technology | Version | Purpose | |----------|-----------|---------|---------| | Framework | React | 19.x | SPA UI | | Language | TypeScript | 5.9 | Type safety | | Map Engine | **MapLibre GL JS** | 5.18 | ENC 전자해도 렌더링 | | Map Overlay | **deck.gl (MapboxOverlay)** | 9.2 | 선박 아이콘 WebGL 렌더링 | | State | Zustand | 5.x | 경량 상태 관리 | | UI Library | Ant Design | 6.x | 해경 UI 컴포넌트 (일부 사용) | | API Client | Axios + fetch | - | 서버 통신 | | WebSocket | STOMP.js | 7.x | 실시간 물표 수신 (예정) | | Build | Vite | 8.x | 빌드 도구 | | Chart | ECharts | 6.x | 통계/분석 차트 (예정) | | ENC Tiles | gcnautical.com | - | S-57 전자해도 벡터 타일 | ### Backend | Category | Technology | Version | Purpose | |----------|-----------|---------|---------| | Framework | Spring Boot | 3.3.x | MSA 서비스 | | Language | Java | 21 (LTS) | 백엔드 로직 | | ORM | JPA/Hibernate + QueryDSL | - | DB 접근 | | GIS | GeoTools | 31.x | S-57/S-101 파싱 | | API Docs | SpringDoc (OpenAPI 3) | - | INR-05 API 명세 | | Security | Spring Security + Keycloak | - | SSO/GPKI (INR-04) | | Message | Kafka / RabbitMQ | - | 물표 스트리밍 | | Cache | Redis | 7.x | 물표 캐시 | | Container | Docker + K8s | - | ECR-01 MSA 인프라 | ### Database | Category | Technology | Purpose | |----------|-----------|---------| | Main DB | PostgreSQL 16 + PostGIS 3.4 | 공간데이터 저장 | | Tile Cache | pg_tileserv / Martin | 벡터 타일 서빙 | | Time Series | TimescaleDB (확장) | 물표 이력/항적 | | File Storage | MinIO (S3 호환) | SHP/GeoJSON 업로드 | --- ## 3. MSA Service Decomposition (ECR-01) ``` wing-gis/ ├── services/ │ ├── wing-gis-gateway/ # API Gateway (Spring Cloud Gateway) │ ├── wing-gis-auth/ # 인증/권한 (INR-04: SSO, GPKI) │ ├── wing-gis-map/ # 통합 GIS 서비스 (SFR-01~04) │ ├── wing-gis-vessel/ # 물표/선박 신호 (SFR-05~06, SFR-08) │ ├── wing-gis-layer/ # 레이어 관리 (SFR-07) │ ├── wing-gis-analysis/ # 분석 서비스 (SFR-09) │ ├── wing-gis-integration/ # 통합연계모듈 (SFR-06, SFR-10) │ ├── wing-gis-admin/ # 관리도구 │ └── wing-gis-mcp/ # MCP 에이전트 (INR-06: LLM 연계) ├── frontend/ │ └── wing-gis-web/ # React SPA ├── infra/ │ ├── docker-compose.yml # 개발환경 │ ├── k8s/ # 운영환경 K8s 매니페스트 │ └── sql/ # DB 초기화 스크립트 └── docs/ └── api/ # API 명세서 ``` --- ## 4. Frontend Structure (React) — 현재 구현 상태 ``` wing-gis-web/src/ ├── App.tsx # 루트 (레이아웃 + useAisPolling) ├── main.tsx # 엔트리 포인트 ├── App.css # 디자인 토큰 (CSS 변수) │ ├── components/ │ ├── layout/ # ✅ 5-패널 레이아웃 │ │ ├── TitleBar.tsx # 상단 헤더 │ │ ├── SubToolbar.tsx # 컨텍스트별 도구 모음 │ │ ├── Sidebar.tsx # 좌측 (검색, 레이어 트리) │ │ ├── RightPanel.tsx # 우측 (물표현황 실데이터/경보/해양정보) │ │ └── BottomBar.tsx # 하단 상태바 │ ├── map/ # ✅ MapLibre GL JS + deck.gl 기반 │ │ ├── MapViewML.tsx # 맵 컨테이너 + deck.gl 콜백 (툴팁/클릭) │ │ ├── MapTools.tsx # 확대/축소/초기화 │ │ ├── BaseMapSelector.tsx # 배경지도 탭 │ │ ├── ScaleBar.tsx # 축척바 │ │ ├── MapLegend.tsx # 물표 범례 (실시간 AIS 카운트) │ │ └── CoordStatusBar.tsx # 좌표/줌 상태바 │ └── vessel/ # ✅ 선박 UI │ ├── VesselPopup.tsx # 선박 미니 팝업 │ ├── VesselSearch.tsx # 선박 통합 검색 (SFR-08) │ └── VesselSignalToggle.tsx # 신호 소스 ON/OFF 토글 │ ├── features/ │ ├── vesselLayer/ # ✅ AIS 실시간 + 비AIS 더미 렌더링 │ │ ├── hooks/ │ │ │ └── useVesselDeckLayer.ts # AIS+비AIS deck.gl 레이어 통합 │ │ └── lib/ │ │ ├── aisAdapter.ts # AisTarget → AisFeature 변환 │ │ ├── aisDeckLayers.ts # AIS IconLayer + halo + overlay │ │ ├── aisIcons.ts # SignalKindCode별 SVG 아이콘 8종 │ │ ├── shipTooltip.ts # 호버 툴팁 HTML (사진 썸네일 포함) │ │ ├── ShipBatchRenderer.ts # 뷰포트 컬링 + 밀도 제어 (제네릭) │ │ ├── vesselAdapter.ts # 비AIS Vessel → VesselFeature │ │ ├── vesselDeckLayers.ts # 비AIS deck.gl 레이어 │ │ └── vesselIcons.ts # 비AIS VesselSource별 아이콘 │ ├── nauticalChart/ # ✅ ENC 전자해도 오버레이 │ │ ├── hooks/useNauticalChartOverlay.ts │ │ ├── lib/fetchNauticalStyle.ts # gcnautical.com 스타일 fetch │ │ ├── lib/nauticalLayerManager.ts # 레이어 주입/제거/S-52 테마 │ │ ├── model/types.ts # S52Theme, NauticalChartSettings │ │ └── ui/NauticalChartToggle.tsx # ENC on/off + 주간/황혼/야간 │ └── shipImage/ # ✅ 선박 사진 (호버 썸네일 + 클릭 모달) │ ├── api/shipImageApi.ts # 이미지 API + URL 유틸 │ └── ui/ShipImageModal.tsx # 사진 뷰어 모달 (네비게이션+캐러셀) │ ├── hooks/ │ ├── useMap.ts # ✅ MapLibre + MapboxOverlay 초기화 │ ├── useDeckLayers.ts # ✅ deck.gl 레이어 + getTooltip/onClick │ ├── useStore.ts # ✅ Zustand (vessels, aisTargets, signalState...) │ ├── useAisPolling.ts # ✅ AIS REST 폴링 (60분→1분→2시간 프루닝) │ └── useVesselStream.ts # ⏳ STOMP WebSocket (백엔드 연동 시) │ ├── services/ │ ├── aisApi.ts # ✅ /signal-batch/api/v2/vessels/recent-positions │ ├── api.ts # Axios 인스턴스 │ └── vesselApi.ts # 물표 CRUD API │ ├── types/ │ ├── ais.ts # ✅ SignalKindCode 8종, AisTarget, DTO, 색상맵 │ ├── vessel.ts # Vessel, VesselSource 7종 │ └── layer.ts # LayerGroup, S100_PRODUCTS │ ├── utils/ │ ├── coordinate.ts # DMS 변환, 축척 계산 │ ├── s52Colors.ts # S-52 수심 색상 팔레트 │ └── vesselIcon.ts # 범용 SVG 아이콘 생성 │ ├── lib/map/ │ ├── mapCore.ts # kickRepaint, onMapStyleReady │ ├── mapConstants.ts # 기본 좌표, 줌, OSM 폴백 스타일 │ └── MaplibreDeckCustomLayer.ts # Globe 모드용 커스텀 레이어 (예비) │ ├── context/MapContext.tsx # mapRef, overlayRef 전달 └── data/mockVessels.ts # 비AIS 더미 데이터 ``` ### 구현 상태 범례 - ✅ 구현 완료 (실동작) - ⏳ 코드 준비됨, 백엔드 연동 대기 ### 미구현 (향후 개발) - `components/layer/` — LayerTree, LayerUpload, LayerStyle (SLD 편집) - `components/analysis/` — AnalysisTabs, BufferAnalysis, HeatmapAnalysis - `components/admin/` — UserManage, IntegrationStatus, AuditLog - `components/common/` — LoginModal (SSO/GPKI), NotificationBell - `hooks/useAuth.ts`, `hooks/useLayer.ts` - `services/layerApi.ts`, `services/analysisApi.ts`, `services/authApi.ts` - `types/s100.ts`, `types/auth.ts` - React Router 라우팅 --- ## 5. Backend Structure (Spring Boot) ``` wing-gis-map/ # 대표 서비스 구조 ├── src/main/java/kr/go/kcg/wingis/ │ ├── WingGisMapApplication.java │ ├── config/ │ │ ├── SecurityConfig.java │ │ ├── CorsConfig.java │ │ ├── WebSocketConfig.java │ │ └── PostgisConfig.java │ ├── domain/ │ │ ├── vessel/ │ │ │ ├── Vessel.java # Entity │ │ │ ├── VesselTrack.java # 항적 Entity │ │ │ ├── VesselRepository.java │ │ │ ├── VesselService.java │ │ │ └── VesselController.java │ │ ├── layer/ │ │ │ ├── Layer.java │ │ │ ├── LayerGroup.java │ │ │ ├── S100Layer.java # S-100 전용 │ │ │ ├── LayerRepository.java │ │ │ ├── LayerService.java │ │ │ └── LayerController.java │ │ ├── chart/ │ │ │ ├── ChartDataset.java # S-101 ENC 데이터셋 │ │ │ ├── ChartFeature.java # 해도 피처 │ │ │ └── ChartService.java │ │ ├── boundary/ │ │ │ ├── Boundary.java # EEZ/NLL/관할구역 │ │ │ └── BoundaryService.java │ │ ├── analysis/ │ │ │ ├── AnalysisResult.java │ │ │ ├── AnalysisService.java │ │ │ └── AnalysisController.java │ │ └── user/ │ │ ├── User.java │ │ └── UserService.java │ ├── integration/ # SFR-06 통합연계모듈 │ │ ├── ais/ │ │ │ ├── AisReceiver.java # AIS 수신기 │ │ │ └── AisDecoder.java # NMEA 디코더 │ │ ├── vpass/ │ │ │ └── VPassClient.java │ │ ├── vts/ │ │ │ └── VtsRadarClient.java │ │ ├── lrit/ │ │ │ └── LritClient.java │ │ └── DataFusionEngine.java # 물표 융합 엔진 │ ├── dto/ │ │ ├── VesselDto.java │ │ ├── LayerDto.java │ │ └── SearchDto.java │ └── exception/ │ └── GlobalExceptionHandler.java ├── src/main/resources/ │ ├── application.yml │ ├── application-dev.yml │ └── application-prod.yml ├── build.gradle └── Dockerfile ``` --- ## 6. Database Schema (PostgreSQL + PostGIS) ### Core Tables ```sql -- 물표/선박 CREATE TABLE vessel ( id BIGSERIAL PRIMARY KEY, mmsi VARCHAR(20) UNIQUE, imo VARCHAR(20), name VARCHAR(100), callsign VARCHAR(20), ship_type VARCHAR(50), flag VARCHAR(5), gt DECIMAL, dwt DECIMAL, loa DECIMAL, beam DECIMAL, draft DECIMAL, status VARCHAR(30), source VARCHAR(20), -- AIS/V-Pass/VTS/RADAR/E-NAV/VHF-DSC position GEOMETRY(Point, 4326), sog DECIMAL, cog DECIMAL, heading DECIMAL, nav_status VARCHAR(30), destination VARCHAR(100), eta TIMESTAMP, last_updated TIMESTAMP DEFAULT NOW(), created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_vessel_position ON vessel USING GIST(position); CREATE INDEX idx_vessel_mmsi ON vessel(mmsi); CREATE INDEX idx_vessel_source ON vessel(source); -- 항적 (TimescaleDB hypertable 권장) CREATE TABLE vessel_track ( id BIGSERIAL, vessel_id BIGINT REFERENCES vessel(id), position GEOMETRY(Point, 4326), sog DECIMAL, cog DECIMAL, heading DECIMAL, recorded_at TIMESTAMP NOT NULL, PRIMARY KEY (id, recorded_at) ); CREATE INDEX idx_track_vessel ON vessel_track(vessel_id, recorded_at DESC); CREATE INDEX idx_track_position ON vessel_track USING GIST(position); -- 레이어 CREATE TABLE layer_group ( id SERIAL PRIMARY KEY, name VARCHAR(100), parent_id INTEGER REFERENCES layer_group(id), sort_order INTEGER DEFAULT 0, icon VARCHAR(10), is_system BOOLEAN DEFAULT FALSE ); CREATE TABLE layer ( id BIGSERIAL PRIMARY KEY, group_id INTEGER REFERENCES layer_group(id), name VARCHAR(200), layer_type VARCHAR(30), -- VECTOR/RASTER/WMS/S100 s100_product VARCHAR(10), -- S-101/S-102/S-104/S-111/S-122/S-124/S-127/S-412 geometry_type VARCHAR(20), -- POINT/LINE/POLYGON srid INTEGER DEFAULT 4326, style_sld TEXT, min_scale INTEGER, max_scale INTEGER, is_visible BOOLEAN DEFAULT TRUE, is_default_on BOOLEAN DEFAULT FALSE, feature_count INTEGER DEFAULT 0, source_url VARCHAR(500), created_by BIGINT, created_at TIMESTAMP DEFAULT NOW() ); -- S-100 전자해도 데이터셋 CREATE TABLE chart_dataset ( id BIGSERIAL PRIMARY KEY, cell_name VARCHAR(20), -- KR4G3A40 product VARCHAR(10), -- S-101, S-102, ... edition INTEGER, update_num INTEGER, scale INTEGER, status VARCHAR(20), -- CURRENT/SUPERSEDED/NEW coverage GEOMETRY(Polygon, 4326), fc_version VARCHAR(20), pc_version VARCHAR(20), feature_count INTEGER, file_path VARCHAR(500), issued_date DATE, created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_chart_coverage ON chart_dataset USING GIST(coverage); -- 해도 피처 CREATE TABLE chart_feature ( id BIGSERIAL PRIMARY KEY, dataset_id BIGINT REFERENCES chart_dataset(id), feature_type VARCHAR(50), -- Lighthouse/DepthArea/Buoy/... feature_name_ko VARCHAR(200), feature_name_en VARCHAR(200), geometry GEOMETRY(Geometry, 4326), attributes JSONB, -- S-101 속성 (유연한 구조) scamin INTEGER, created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_feature_geom ON chart_feature USING GIST(geometry); CREATE INDEX idx_feature_type ON chart_feature(feature_type); CREATE INDEX idx_feature_attrs ON chart_feature USING GIN(attributes); -- 경계/관할구역 CREATE TABLE boundary ( id SERIAL PRIMARY KEY, name VARCHAR(100), boundary_type VARCHAR(30), -- EEZ/NLL/TERRITORIAL/JURISDICTION geometry GEOMETRY(MultiPolygon, 4326), organization VARCHAR(100), attributes JSONB ); CREATE INDEX idx_boundary_geom ON boundary USING GIST(geometry); -- 분석 결과 CREATE TABLE analysis_result ( id BIGSERIAL PRIMARY KEY, analysis_type VARCHAR(50), -- ILLEGAL_FISHING/TRANSSHIP/DARK_VESSEL/... name VARCHAR(200), geometry GEOMETRY(Geometry, 4326), result_data JSONB, confidence DECIMAL, status VARCHAR(20), created_by BIGINT, created_at TIMESTAMP DEFAULT NOW(), expires_at TIMESTAMP ); -- 사용자 CREATE TABLE app_user ( id BIGSERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, name VARCHAR(50), department VARCHAR(100), organization VARCHAR(100), -- 지방청/해양경찰서 role VARCHAR(30), -- ADMIN/OPERATOR/VIEWER jurisdiction_id INTEGER REFERENCES boundary(id), sso_id VARCHAR(100), gpki_dn VARCHAR(500), is_active BOOLEAN DEFAULT TRUE, last_login TIMESTAMP, created_at TIMESTAMP DEFAULT NOW() ); -- 경보/알림 CREATE TABLE alert ( id BIGSERIAL PRIMARY KEY, alert_type VARCHAR(30), -- SOS/ZONE_VIOLATION/SIGNAL_LOST/... severity VARCHAR(10), -- CRITICAL/WARNING/INFO title VARCHAR(200), description TEXT, vessel_id BIGINT REFERENCES vessel(id), position GEOMETRY(Point, 4326), is_acknowledged BOOLEAN DEFAULT FALSE, acknowledged_by BIGINT REFERENCES app_user(id), created_at TIMESTAMP DEFAULT NOW() ); -- 감사 로그 CREATE TABLE audit_log ( id BIGSERIAL PRIMARY KEY, user_id BIGINT REFERENCES app_user(id), action VARCHAR(50), target_type VARCHAR(50), target_id VARCHAR(50), detail JSONB, ip_address VARCHAR(45), created_at TIMESTAMP DEFAULT NOW() ); ``` --- ## 7. API Endpoints (RESTful) ### Vessel API (SFR-05, SFR-08) ``` GET /api/v1/vessels # 물표 목록 (필터/페이징) GET /api/v1/vessels/{mmsi} # 물표 상세 GET /api/v1/vessels/{mmsi}/tracks # 항적 조회 GET /api/v1/vessels/search?q= # 통합 검색 (SFR-08) GET /api/v1/vessels/bbox?bbox= # 영역 내 물표 WS /ws/vessels # 실시간 물표 스트림 ``` ### Layer API (SFR-03, SFR-07) ``` GET /api/v1/layers # 레이어 트리 POST /api/v1/layers/upload # 레이어 업로드 PUT /api/v1/layers/{id}/style # SLD 스타일 변경 GET /api/v1/layers/{id}/features # 피처 조회 DELETE /api/v1/layers/{id} # 레이어 삭제 ``` ### Chart API (SFR-04) ``` GET /api/v1/charts # S-100 데이터셋 목록 GET /api/v1/charts/{cellName}/features # 해도 피처 GET /api/v1/charts/tile/{z}/{x}/{y} # 벡터 타일 ``` ### Analysis API (SFR-09) ``` POST /api/v1/analysis/buffer # 버퍼 분석 POST /api/v1/analysis/heatmap # 히트맵 POST /api/v1/analysis/upload # 결과 업로드 GET /api/v1/analysis/results # 결과 목록 ``` ### Auth API (INR-04) ``` POST /api/v1/auth/login # 로그인 POST /api/v1/auth/sso # SSO 인증 POST /api/v1/auth/gpki # GPKI 인증 GET /api/v1/auth/me # 현재 사용자 POST /api/v1/auth/logout # 로그아웃 ``` --- ## 8. S-100 Product Specification Support Matrix ### 8.1 Specification Inventory 본 사업에서 지원하는 IHO S-100 기반 제품 규격과 보유 문서 현황: | S-100 Product | Version | Full Name | PS | FC | PC | DCEG | Validation | Sample | |---------------|---------|-----------|:--:|:--:|:--:|:----:|:----------:|:------:| | **S-100** | Ed.5.2.1 (Dec 2025) | Universal Hydrographic Data Model | PDF | - | Lua/XSLT | - | S-158-100 v1.0.0 | - | | **S-101** | Ed.2.0.0 | Electronic Navigational Chart (ENC) | PDF | XML 2.0.0 | ZIP 2.0.0 | PDF 2.0.0 | S-158-101 v1.1.0 | - | | **S-102** | Ed.3.0.0 | Bathymetric Surface | PDF | XML 3.0.0 | ZIP 3.0.0 | - | S-158-102 v1.0.0 | - | | **S-104** | Ed.2.0.0 | Water Level Information | PDF | XML 2.0.0 | - | - | - | - | | **S-111** | Ed.2.0.0 | Surface Currents | PDF | XML 2.0.0 | ZIP 2.0.0 | - | - | - | | **S-122** | Ed.1.0.0 | Marine Protected Areas (MPA) | ZIP | XML 1.0.0 | - | - | - | ZIP | | **S-123** | Ed.1.0.0 | Marine Radio Services (MRS) | ZIP | XML 1.0.0 | - | - | - | ZIP | | **S-124** | Ed.2.0.0 | Navigational Warnings | PDF | XML 2.0.0 | ZIP 2.0.0 | PDF 2.0.0 | - | - | | **S-127** | Ed.1.0.0 | Marine Traffic Management | PDF | ZIP 1.0.0 | - | - | - | ZIP | > 참조 경로: `/Documents/GIS/S-100 Specifications/{S-1xx}/` ### 8.2 Service-to-Product Mapping 각 백엔드 서비스가 담당하는 S-100 제품과 구체적 활용 범위: ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ wing-gis-map (GIS API) │ │ │ │ S-101 ENC Ed.2.0.0 ─── 전자해도 렌더링, 피처 조회, Edition 관리 │ │ ├─ FC 2.0.0 ── FeatureType 정의 (DepthArea, Lighthouse, Buoy...) │ │ ├─ PC 2.0.0 ── S-52 Portrayal 렌더링 규칙 │ │ ├─ DCEG 2.0.0 ── 피처 속성 검증 (Data Capture Encoding Guide) │ │ └─ S-158-101 ── 데이터 품질 검증 (Validation Checks) │ │ │ │ S-102 Bathymetric Ed.3.0.0 ─── 수심 격자 데이터 표출 │ │ ├─ FC 3.0.0 ── BAG 수심 피처 정의 │ │ └─ PC 3.0.0 ── 수심 음영/등심선 색상 팔레트 │ │ │ │ S-104 Water Level Ed.2.0.0 ─── 실시간 조석/수위 오버레이 │ │ └─ FC 2.0.0 ── 조석 관측점/예측 격자 피처 정의 │ │ │ │ S-111 Surface Currents Ed.2.0.0 ─── 해류 벡터/격자 오버레이 │ │ ├─ FC 2.0.0 ── 해류 벡터 피처 정의 │ │ └─ PC 2.0.0 ── 해류 화살표/색상 렌더링 규칙 │ │ │ │ S-122 MPA Ed.1.0.0 ─── 해양보호구역 경계 표출 │ │ └─ FC 1.0.0 ── 보호구역 등급/경계 피처 정의 │ │ │ │ S-123 MRS Ed.1.0.0 ─── 해양무선 커버리지 표출 │ │ └─ FC 1.0.0 ── VHF/MF/HF 무선 범위 피처 정의 │ │ │ │ S-124 Nav Warnings Ed.2.0.0 ─── 항행경보 구역 실시간 표출 │ │ ├─ FC 2.0.0 ── 경보 구역/유형 피처 정의 │ │ ├─ PC 2.0.0 ── 경보 심볼/색상 렌더링 │ │ └─ DCEG 2.0.0 ── 경보 데이터 입력 검증 │ │ │ │ S-127 MTM Ed.1.0.0 ─── TSS/VTS 구역 표출 │ │ └─ FC 1.0.0 ── 통항분리대/VTS 관할 피처 정의 │ │ │ │ S-100 Ed.5.2.1 ─── 공통 데이터 모델 / Exchange Set / 인코딩 │ │ ├─ Part 5 (FC) ── Feature Catalogue 구조 파싱 │ │ ├─ Part 9/9a (Portrayal/Lua) ── 렌더링 엔진 │ │ ├─ Part 10a/10b/10c ── 인코딩 (8211/GML/HDF5) │ │ ├─ Part 15 ── 암호화/서명 (Encryption optional, Signing mandatory) │ │ ├─ Part 16/16a ── Interoperability / Harmonised Portrayal │ │ └─ Part 17 ── Discovery Metadata (Exchange Catalogue) │ ├─────────────────────────────────────────────────────────────────────────┤ │ wing-gis-vessel (Vessel Signal) │ │ │ │ S-124 ─── 조난 경보 연동 (VHF-DSC → S-124 Nav Warning 자동 생성) │ │ S-127 ─── VTS 관제 구역 내 선박 연계 │ ├─────────────────────────────────────────────────────────────────────────┤ │ wing-gis-integration (통합연계모듈) │ │ │ │ S-100 Part 10b (GML) ─── 물표 데이터 GML 인코딩 변환 │ │ S-100 Part 14 ─── Online Communication Exchange 프로토콜 │ │ S-100 Part 17 ─── Exchange Catalogue 메타데이터 관리 │ │ S-100 Part 15 ─── 데이터 서명/검증 (Digital Signature) │ ├─────────────────────────────────────────────────────────────────────────┤ │ wing-gis-analysis (분석 서비스) │ │ │ │ S-102 ─── 수심 격자 기반 해저 지형 분석 │ │ S-104 ─── 조석 데이터 기반 수위 예측 분석 │ │ S-111 ─── 해류 데이터 기반 표류 예측 분석 │ ├─────────────────────────────────────────────────────────────────────────┤ │ wing-gis-layer (레이어 관리) │ │ │ │ S-100 Part 5 ─── Feature Catalogue XML 파싱/관리 │ │ S-100 Part 9 ─── Portrayal Catalogue 관리 (SLD 변환) │ │ S-100 Part 11 ─── Product Specification 메타 관리 │ │ S-158 ─── Validation Checks 실행 엔진 │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### 8.3 Feature Catalogue Integration FC(Feature Catalogue) XML을 파싱하여 DB에 자동 로드하는 구조: ``` S-100 Specifications/S-101/101_Feature_Catalogue_2.0.0.xml │ ▼ ┌──────────────┐ ┌──────────────────────────────┐ │ FC Parser │────▶│ chart_feature_type (DB) │ │ (GeoTools/ │ │ ├─ feature_type: Lighthouse │ │ JAXB) │ │ ├─ attributes: JSONB │ │ │ │ ├─ geometry_type: Point │ └──────────────┘ │ └─ product: S-101 │ └──────────────────────────────┘ ``` | FC File | Product | Feature Types | DB Table | |---------|---------|---------------|----------| | `101_FC_2.0.0.xml` | S-101 | DepthArea, DepthContour, Lighthouse, Buoy, Rock, Wreck, FairwaySystem, AnchorageArea, RestrictedArea, Coastline, LandArea, ... (~180 types) | `chart_feature` | | `102_FC_3.0.0.xml` | S-102 | BathymetricDataset, TrackingList, QualityOfBathymetricData | `chart_feature` | | `104_FC_2.0.0.xml` | S-104 | WaterLevelTrend, WaterLevelTimeSeries, TidalStation | `chart_feature` | | `111_FC_2.0.0.xml` | S-111 | SurfaceCurrentDataset, SurfaceCurrentTimeSeries | `chart_feature` | | `122_FC_1.0.0.xml` | S-122 | MarineProtectedArea | `boundary` | | `123_FC_1.0.0.xml` | S-123 | RadioServiceArea, RadioStation | `chart_feature` | | `124_FC_2.0.0.xml` | S-124 | NavigationalWarningPart, NavigationalWarningFeaturePart | `alert` / `chart_feature` | | `S-127_FC_1.0.0` | S-127 | TrafficSeparationScheme, VTSArea, ReportingPoint | `boundary` | ### 8.4 Portrayal Catalogue Integration PC(Portrayal Catalogue)를 활용한 S-52 기반 렌더링 규칙: | PC File | Product | 렌더링 대상 | Frontend 적용 | |---------|---------|-----------|-------------| | `101_PC_2.0.0` | S-101 | 해도 심볼/색상/선형 | OpenLayers Style + Lua 엔진 | | `102_PC_3.0.0` | S-102 | 수심 음영/등심선 | Raster 타일 색상 팔레트 | | `111_PC_2.0.0` | S-111 | 해류 벡터 화살표 | SVG 벡터 오버레이 | | `124_PC_2.0.0` | S-124 | 항행경보 구역 심볼 | 경보 폴리곤 스타일 | | S-100 BPC (Lua) | 공통 | Lua 기반 Portrayal 스크립팅 | Part 9a Lua 인터프리터 | ### 8.5 Validation Integration (S-158) S-158 기반 데이터 품질 검증: | Validation File | 대상 | 검증 내용 | 서비스 | |----------------|------|---------|--------| | `S-158-100_v1.0.0` | S-100 공통 | Exchange Set 구조, 메타데이터, 인코딩 규칙 | wing-gis-integration | | `S-158-101_v1.1.0` | S-101 ENC | 피처 속성 완전성, 토폴로지, SCAMIN, 좌표 정밀도 | wing-gis-map | | `S-158-102_v1.0.0` | S-102 수심 | BAG 격자 무결성, 수심 범위 검증 | wing-gis-map | ### 8.6 Data Encoding Support (S-100 Part 10) | Encoding | S-100 Part | 지원 제품 | 라이브러리 | |----------|-----------|---------|-----------| | ISO/IEC 8211 | Part 10a | S-101 (레거시 S-57 호환) | GeoTools S-57 Driver | | GML 3.2 | Part 10b | S-122, S-123, S-124, S-127 | JAXB + GML Parser | | HDF5 | Part 10c | S-102, S-104, S-111 (격자 데이터) | JHdf5 / HDF5 Java | ### 8.7 S-100 Ed.5.2.1 Key Changes Applied 본 시스템에 반영된 S-100 Ed.5.2.1 (December 2025) 주요 변경사항: | Part | 변경 내용 | 시스템 반영 | |------|---------|-----------| | Part 1 | URI Derived Type에 fileURI 추가, MRN 형식 변경 | 메타데이터 URI 처리 | | Part 5 | FC InformationType/FeatureType 상속 관계 정정 | FC XML 파서 | | Part 10b | GML 파일 확장자 .GML 필수, xlink:title 명시 | GML 인코딩 모듈 | | Part 10c | HDF5 featureAttributeTableKey 컬럼명 변경, timePoint optional | HDF5 리더 | | Part 11 | Product Specification 참조를 IHO GI Registry로 변경 | PS 메타 관리 | | Part 14 | ISO/IEC 80000-13:2025 추가 | 온라인 교환 | | **Part 15** | **암호화 optional, 서명 mandatory**, schemeAdministrator [1] 필수 | **S-63 Encryptor** | | Part 16a | Harmonised Portrayal URL 변경 | 렌더링 엔진 | | Part 17 | editionNumber → PositiveInteger, boundingPolygon 좌표 순서 CRS 기준 | Exchange Catalogue | | Part 18 | URL 정규화 참조 변경 | 다국어 지원 | --- ## 9. RFP Requirement Mapping (80 Requirements) | RFP ID | 요구사항 | 서비스 | 상태 | 비고 | |--------|---------|--------|:----:|------| | SFR-01 | 통합 GIS 서비스 | wing-gis-map + MapViewML | ✅ | MapLibre GL JS | | SFR-02 | 서비스 제공 방식 | React SPA (WEB) | ✅ | Vite 8 | | SFR-03 | 전자해도+공간정보 통합조회 | nauticalChart 피처 | ✅ | gcnautical.com ENC | | SFR-04 | S-100 차세대 전자해도 | fetchEncStyle + S-52 테마 | ✅ | 주간/황혼/야간 | | SFR-05 | 물표정보 연계+융합 | useAisPolling + deck.gl | ✅ | AIS 실시간, 비AIS 더미 | | SFR-06 | 통합연계모듈 | wing-gis-integration | ⏳ | Kafka 스트림 | | SFR-07 | 관할 기반+사용자 레이어 | wing-gis-layer | ⏳ | 업로드/SLD | | SFR-08 | 선박 통합 검색 | VesselSearch | ⚠️ | UI 구현, 백엔드 미연동 | | SFR-09 | 외부 분석결과 시각화 | wing-gis-analysis | ⏳ | GeoJSON/SHP | | SFR-10 | 7개 시스템 통합 | wing-gis-integration | ⏳ | 7종 어댑터 | | PER-03 | 동시접속 3,000명 | K8s HPA + Redis | ⏳ | Scale-out | | ECR-01 | MSA 아키텍처 | Docker + K8s | ⚠️ | Docker Compose 완료, K8s 미구현 | | INR-04 | SSO/GPKI | wing-gis-auth + Keycloak | ⏳ | | | INR-05 | API 서비스 | SpringDoc OpenAPI | ⏳ | | | INR-06 | MCP 에이전트 | wing-gis-mcp | ⏳ | LLM 연계 | | DAR-01~12 | 데이터 요구사항 | PostgreSQL + PostGIS | ⚠️ | 스키마 완료, 데이터 미적재 | > ✅ 구현 완료 · ⚠️ 부분 구현 · ⏳ 미착수 --- ## 10. Development Phases ### Phase 1: 기반 구축 (M+0 ~ M+2) — 완료 - [x] 프로젝트 구조 설계 (ARCHITECTURE.md) - [x] React 프로젝트 초기화 (Vite 8 + TypeScript 5.9) - [x] PostgreSQL + PostGIS 스키마 생성 (001_init_schema.sql) - [x] Docker Compose 개발환경 (7개 서비스) - [x] **MapLibre GL JS 기반 지도** (OpenLayers → MapLibre 전환 완료) - [x] **deck.gl MapboxOverlay 통합** (선박 WebGL 렌더링) - [x] **ENC 전자해도** (gcnautical.com 벡터 타일, S-52 테마) - [x] 레이아웃 5-패널 구조 (TitleBar/SubToolbar/Sidebar/RightPanel/BottomBar) - [x] Zustand 상태 관리 (vessels, aisTargets, signalState, nauticalChartSettings) ### Phase 2: 핵심 기능 (M+2 ~ M+4) — 진행 중 - [x] **AIS 실시간 물표** (REST 폴링 60분 초기 → 1분 간격 → 2시간 프루닝) - [x] **SignalKindCode 기반 아이콘** (8종 색상/형태, 항해/정박 구분) - [x] **호버 툴팁** (이름, MMSI, SOG/COG, 사진 썸네일) - [x] **선박 사진 모달** (고화질 뷰어, 네비게이션, 캐러셀) - [x] **물표현황 실데이터** (AIS 카운트, 관할 내 선박 분류) - [x] 선박 통합 검색 UI (SFR-08, 백엔드 미연동) - [ ] EEZ/NLL/관할구역 경계 레이어 - [ ] 사용자 인증 (SSO/GPKI) ### Phase 3: 통합 (M+4 ~ M+6) - [ ] 7개 시스템 연계 어댑터 (V-Pass/E-NAV/VTS/VTS-RADAR/AIR-AIS/VHF-DSC/LRIT) - [ ] STOMP WebSocket 실시간 물표 스트리밍 - [ ] 통합연계모듈 (수집/정제/융합/배포) - [ ] 공간분석 기능 (버퍼/히트맵/통계) - [ ] 레이어 업로드/SLD 편집 - [ ] MCP 에이전트 (LLM 연계) ### Phase 4: 안정화 (M+6 ~ M+7) - [ ] 성능 최적화 (ShipBatchRenderer 밀도 컬링 고도화, 3,000명 동시접속) - [ ] 보안 감사 로그 - [ ] 운영 전환 + 교육