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>
200 lines
8.0 KiB
Markdown
200 lines
8.0 KiB
Markdown
# WING-GIS Web Frontend
|
|
|
|
해양경찰청 통합 GIS 위치정보시스템 프론트엔드
|
|
|
|
## 기술 스택
|
|
|
|
| 분류 | 기술 | 버전 | 용도 |
|
|
|------|------|------|------|
|
|
| Framework | React | 19.x | SPA UI |
|
|
| Language | TypeScript | 5.9 | 타입 안전성 |
|
|
| Build | Vite | 8.x | 빌드 + HMR |
|
|
| Map Engine | MapLibre GL JS | 5.18 | ENC 전자해도 렌더링 |
|
|
| Map Overlay | deck.gl (MapboxOverlay) | 9.2 | 선박 아이콘 WebGL 렌더링 |
|
|
| State | Zustand | 5.x | 경량 상태 관리 |
|
|
| HTTP | Axios / fetch | - | REST API 통신 |
|
|
| WebSocket | STOMP.js | 7.x | 실시간 물표 수신 (예정) |
|
|
|
|
## 시작하기
|
|
|
|
```bash
|
|
# 의존성 설치
|
|
yarn install
|
|
|
|
# 개발 서버 (http://localhost:5174)
|
|
yarn dev
|
|
|
|
# 프로덕션 빌드
|
|
yarn build
|
|
|
|
# 빌드 결과물 프리뷰
|
|
yarn preview
|
|
```
|
|
|
|
## 프로젝트 구조
|
|
|
|
```
|
|
src/
|
|
├── App.tsx # 루트 컴포넌트 (레이아웃 + AIS 폴링)
|
|
├── main.tsx # 엔트리 포인트
|
|
├── App.css # 디자인 토큰 (CSS 변수)
|
|
│
|
|
├── components/
|
|
│ ├── layout/ # 5-패널 레이아웃
|
|
│ │ ├── TitleBar.tsx # 상단 헤더 (로고, 네비, 시계, 사용자)
|
|
│ │ ├── SubToolbar.tsx # 컨텍스트별 도구 모음
|
|
│ │ ├── Sidebar.tsx # 좌측 (검색, 레이어 트리)
|
|
│ │ ├── RightPanel.tsx # 우측 (물표현황/경보/해양정보)
|
|
│ │ └── BottomBar.tsx # 하단 상태바
|
|
│ ├── map/ # 지도 오버레이 컴포넌트
|
|
│ │ ├── MapViewML.tsx # MapLibre + deck.gl 통합 컨테이너
|
|
│ │ ├── MapTools.tsx # 지도 도구 (확대/축소/초기화)
|
|
│ │ ├── BaseMapSelector.tsx # 배경지도 탭
|
|
│ │ ├── ScaleBar.tsx # 축척바
|
|
│ │ ├── MapLegend.tsx # 물표 범례 (실시간 AIS 카운트)
|
|
│ │ └── CoordStatusBar.tsx # 좌표/줌 상태바
|
|
│ └── vessel/ # 선박 관련 UI
|
|
│ ├── VesselPopup.tsx # 선박 미니 팝업
|
|
│ ├── VesselSearch.tsx # 선박 통합 검색
|
|
│ └── VesselSignalToggle.tsx # 신호 소스 ON/OFF 토글
|
|
│
|
|
├── features/
|
|
│ ├── vesselLayer/ # 선박 렌더링 파이프라인
|
|
│ │ ├── hooks/
|
|
│ │ │ └── useVesselDeckLayer.ts # deck.gl 레이어 통합 훅
|
|
│ │ └── lib/
|
|
│ │ ├── aisAdapter.ts # AisTarget → AisFeature 변환
|
|
│ │ ├── aisDeckLayers.ts # AIS deck.gl IconLayer 빌더
|
|
│ │ ├── aisIcons.ts # SignalKindCode별 SVG 아이콘 (8종)
|
|
│ │ ├── shipTooltip.ts # 호버 툴팁 HTML 생성
|
|
│ │ ├── ShipBatchRenderer.ts # 뷰포트 컬링 + 밀도 제어
|
|
│ │ ├── vesselAdapter.ts # 비AIS 소스 어댑터
|
|
│ │ ├── vesselDeckLayers.ts # 비AIS deck.gl 레이어
|
|
│ │ └── vesselIcons.ts # 비AIS 소스별 SVG 아이콘
|
|
│ ├── nauticalChart/ # ENC 전자해도 오버레이
|
|
│ │ ├── hooks/
|
|
│ │ │ └── useNauticalChartOverlay.ts
|
|
│ │ ├── lib/
|
|
│ │ │ ├── fetchNauticalStyle.ts # gcnautical.com 스타일 fetch
|
|
│ │ │ └── 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 레이어 + 콜백 전달
|
|
│ ├── useStore.ts # Zustand 글로벌 스토어
|
|
│ ├── useAisPolling.ts # AIS REST 폴링 (60분 초기, 1분 간격)
|
|
│ └── useVesselStream.ts # STOMP WebSocket (예정)
|
|
│
|
|
├── services/
|
|
│ ├── aisApi.ts # AIS recent-positions API
|
|
│ ├── api.ts # Axios 인스턴스
|
|
│ └── vesselApi.ts # 물표 CRUD API
|
|
│
|
|
├── types/
|
|
│ ├── ais.ts # SignalKindCode, AisTarget, DTO
|
|
│ ├── vessel.ts # Vessel, VesselSource, 색상/형태 맵
|
|
│ └── 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 더미 선박 데이터
|
|
```
|
|
|
|
## 핵심 데이터 흐름
|
|
|
|
### AIS 선박 위치
|
|
|
|
```
|
|
API: GET /signal-batch/api/v2/vessels/recent-positions?minutes=N
|
|
│
|
|
▼
|
|
useAisPolling (60분 초기 → 60초 간격 2분 데이터 → 2시간 프루닝)
|
|
│
|
|
▼
|
|
Zustand Store: aisTargets (Map<mmsi, AisTarget>)
|
|
│
|
|
▼
|
|
useVesselDeckLayer → ShipBatchRenderer (뷰포트 컬링 + 밀도 제어)
|
|
│
|
|
▼
|
|
deck.gl IconLayer (signalKindCode별 색상 아이콘)
|
|
│
|
|
├── 호버 → getTooltip (이름, MMSI, SOG/COG, 사진 썸네일)
|
|
└── 클릭 → ShipImageModal (사진 있는 선박만)
|
|
```
|
|
|
|
### ENC 전자해도
|
|
|
|
```
|
|
gcnautical.com/styles/nautical.json → fetchEncStyle (폰트 패칭)
|
|
│
|
|
▼
|
|
MapLibre map.setStyle() (초기 로드 시 OSM → ENC 전환)
|
|
│
|
|
├── ENC 토글 → useNauticalChartOverlay (레이어 주입/제거)
|
|
└── S-52 테마 → applyS52Theme (주간/황혼/야간 색상)
|
|
```
|
|
|
|
## 선박 아이콘 체계
|
|
|
|
### AIS 선박 (SignalKindCode 기반, 실시간 데이터)
|
|
|
|
| 코드 | 종류 | 색상 | 형태 |
|
|
|------|------|------|------|
|
|
| 000020 | 어선 | #00C853 (녹색) | 항해: 화살표 32x48 / 정박: 원 16x16 |
|
|
| 000021 | 경비함정 | #FF5722 (주황) | 〃 |
|
|
| 000022 | 여객선 | #2196F3 (파랑) | 〃 |
|
|
| 000023 | 화물선 | #9C27B0 (보라) | 〃 |
|
|
| 000024 | 유조선 | #F44336 (빨강) | 〃 |
|
|
| 000025 | 관공선 | #FF9800 (오렌지) | 〃 |
|
|
| 000027 | 일반 | #607D8B (회색) | 〃 |
|
|
| 000028 | 부이 | #795548 (갈색) | 폴+몸체 32x44 (회전 없음) |
|
|
|
|
### 비AIS 소스 (VesselSource 기반, 더미 데이터)
|
|
|
|
| 소스 | 색상 | 형태 |
|
|
|------|------|------|
|
|
| V-Pass | #1a8a3a | 삼각형 |
|
|
| E-NAV | #8833cc | 삼각형 |
|
|
| VTS | #cc6600 | 사각형 |
|
|
| VTS-RADAR | #cc3300 | 다이아몬드 |
|
|
| AIR-AIS | #0099aa | 비행기 |
|
|
| VHF-DSC | #d63030 | 삼각형 (점멸) |
|
|
|
|
## 환경 변수
|
|
|
|
| 변수 | 기본값 | 설명 |
|
|
|------|--------|------|
|
|
| VITE_API_BASE | `http://localhost:8080` | 백엔드 API 기본 URL |
|
|
| VITE_WS_URL | `http://localhost:8080/ws/vessels` | WebSocket 엔드포인트 |
|
|
|
|
## Vite 프록시 (개발 환경)
|
|
|
|
| 경로 | 타겟 | 용도 |
|
|
|------|------|------|
|
|
| `/api` | `http://localhost:8080` | 백엔드 API |
|
|
| `/signal-batch` | `https://wing.gc-si.dev` | AIS 선박 위치 API |
|
|
| `/shipimg` | `https://wing.gc-si.dev` | 선박 사진 정적 파일 |
|
|
| `/martin` | `http://192.168.1.18:3030` | Martin ENC 타일 서버 |
|