WING-GIS 해양경찰 통합 GIS 위치정보시스템. 모노레포: frontend(React 19 + MapLibre + deck.gl) + services(Spring Boot + Gradle). - npm + Nexus 프록시 레지스트리 설정 - 팀 워크플로우 v1.6.1 부트스트랩 파일 배치 - .githooks (commit-msg, post-checkout) - custom_pre_commit: true (모노레포 pre-commit 별도 관리) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
739 lines
36 KiB
Markdown
739 lines
36 KiB
Markdown
# 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명 동시접속)
|
|
- [ ] 보안 감사 로그
|
|
- [ ] 운영 전환 + 교육
|