WING-OPS
해양 오염 사고 대응을 위한 방제 운영 지원 시스템.
유류/HNS 확산 예측, 역추적 분석, 구조 시나리오, 항공 방제, 자산 관리, SCAT 해안평가, 기상/해상 정보를 통합 제공한다.
기술 스택
| 영역 |
기술 |
| Frontend |
React 19, Vite 7, TypeScript 5.9, Tailwind CSS 3 |
| 상태 관리 |
Zustand (클라이언트), TanStack Query (서버) |
| 지도 |
MapLibre GL JS 5.x + deck.gl 9.x (GPU 렌더링) |
| UI |
lucide-react (아이콘), @dnd-kit (드래그앤드롭), emoji-mart (이모지) |
| 실시간 |
Socket.IO Client 4.8 |
| Backend |
Express 4, TypeScript, PostgreSQL 16 + PostGIS |
| 인증 |
JWT HttpOnly Cookie (WING_SESSION) + Google OAuth + RBAC 2차원 권한 |
| 보안 |
Helmet, CORS, Rate-limit, 입력 살균 (sanitize) |
| CI/CD |
Gitea Actions (main 머지 시 자동 배포) |
아키텍처
[Browser]
|
| React 19 + MapLibre GL JS + deck.gl
| Zustand (로컬 상태) + TanStack Query (서버 상태)
|
|--- HTTP (Axios) ---> [Express 4 API]
|--- WebSocket ------> [Socket.IO]
|
[PostgreSQL 16 + PostGIS]
wing DB (운영) + wing_auth DB (인증)
HTTP 정책
- GET / POST only (보안취약점 가이드 준수, PUT/DELETE 미사용)
- JWT는 HttpOnly Cookie로 전송, Axios 인터셉터에서 자동 처리
- Helmet CORP cross-origin 설정 (sendBeacon 허용)
권한 체계
- RBAC 2차원 권한: 리소스(FEATURE_ID) x 오퍼레이션(RCUD)
permResolver 엔진이 AUTH_PERM 테이블의 OPER_CD 기반으로 권한 해석
- 백엔드:
requireAuth > requireRole > requirePermission 미들웨어 체인
프로젝트 구조
wing/
├── frontend/src/
│ ├── App.tsx MainTab 라우팅, 감사 로그 자동 기록
│ ├── index.css @tailwind + @import 엔트리
│ ├── common/ @common/ alias
│ │ ├── components/ auth/, layer/, layout/, map/, ui/
│ │ ├── hooks/ useFeatureTracking, useLayers, useSubMenu
│ │ ├── services/ api.ts, authApi.ts, layerService.ts
│ │ ├── store/ authStore, menuStore (Zustand)
│ │ ├── types/ backtrack, boomLine, hns, navigation
│ │ ├── utils/ cn, coordinates, geo, sanitize
│ │ ├── styles/ base.css, components.css, wing.css (@layer)
│ │ └── constants/ featureIds.ts (FEATURE_ID 상수 체계)
│ └── components/ @components/ alias (11개 탭, MPA 구조)
│ ├── prediction/ 유류 확산 예측
│ ├── hns/ HNS 분석
│ ├── rescue/ 구조 시나리오
│ ├── aerial/ 항공 방제
│ ├── weather/ 해양 기상
│ ├── incidents/ 사건/사고 관리
│ ├── board/ 게시판
│ ├── reports/ 보고서
│ ├── assets/ 자산 관리
│ ├── scat/ Pre-SCAT 해안평가
│ └── admin/ 관리자
├── backend/src/
│ ├── server.ts Express 진입점 + 보안 미들웨어
│ ├── auth/ JWT, OAuth, 미들웨어
│ ├── users/, roles/ 사용자/역할 관리, permResolver
│ ├── settings/, menus/ 시스템 설정, 메뉴
│ ├── audit/ 감사 로그
│ ├── board/, hns/, reports/ 업무 도메인
│ ├── assets/, incidents/ 업무 도메인
│ ├── scat/, prediction/ 업무 도메인
│ ├── aerial/, rescue/ 업무 도메인
│ ├── routes/ layers, simulation
│ ├── middleware/ security (sanitize, rate-limit)
│ └── db/ wingDb, authDb, seed
├── database/
│ ├── init.sql wing DB 스키마
│ ├── auth_init.sql wing_auth DB 스키마
│ └── migration/ 001~016 마이그레이션
└── .gitea/workflows/ CI/CD 파이프라인
Path Alias
| Alias |
경로 |
@common/* |
src/common/* |
@components/* |
src/components/* |
탭 구성 (11개)
| 탭 |
패키지 |
설명 |
| prediction |
확산 예측 |
유류 확산 모델 시뮬레이션 (KOSPS/POSEIDON/OpenDrift 앙상블) |
| hns |
HNS 분석 |
위험유해물질 거동 분석 + 물질 DB |
| rescue |
구조 시나리오 |
해상 구조 시나리오 모의 |
| aerial |
항공 방제 |
항공 탐색, 드론, CCTV, 위성 |
| weather |
해양 기상 |
실시간 해양기상 오버레이 |
| incidents |
사건/사고 |
사건 이력 관리, 미디어 |
| board |
게시판 |
공지/자료 게시판 |
| reports |
보고서 |
오염보고서 생성기 |
| assets |
자산 관리 |
방제 장비/기관/담당자/선박보험 |
| scat |
해안평가 |
Pre-SCAT 해안 구간 조사 |
| admin |
관리자 |
사용자/역할/권한/메뉴/설정 |
백엔드 API 라우트
모든 API는 /api/ 접두사 하위에 등록된다.
인증/관리
| 라우트 |
설명 |
/api/auth |
JWT 로그인/로그아웃, OAuth, 토큰 갱신 |
/api/users |
사용자 CRUD |
/api/roles |
역할/권한 관리, RCUD 매트릭스 |
/api/settings |
시스템 설정 |
/api/menus |
메뉴 설정 |
/api/audit |
감사 로그 |
업무 도메인
| 라우트 |
설명 |
/api/board |
게시판 CRUD + 첨부파일 |
/api/hns |
HNS 물질 검색/분석 |
/api/reports |
보고서 템플릿/생성/조회 |
/api/assets |
자산(장비/기관/선박/보험) 관리 |
/api/incidents |
사건/사고 이력 관리 |
/api/scat |
SCAT 구역/구간/조사 |
/api/prediction |
확산 분석/역추적/오일펜스 |
/api/aerial |
항공 미디어/CCTV/위성 |
/api/rescue |
구난 작전/시나리오 |
지도/시뮬레이션
| 라우트 |
설명 |
/api/layers |
지도 레이어 데이터 |
/api/simulation |
시뮬레이션 실행/결과 |
데이터베이스
| DB |
용도 |
비고 |
| wing |
운영 데이터 |
PostgreSQL 16 + PostGIS |
| wing_auth |
인증/권한 |
동일 서버, 별도 DB |
마이그레이션 파일: database/migration/001~016
퀵스타트
사전 요구사항
- Node.js 20+ (
.node-version 파일, fnm 사용)
- PostgreSQL 16+ (운영 DB 접근 가능해야 함)
실행
# 저장소 복제
git clone https://gitea.gc-si.dev/gc/wing-ops.git
cd wing-ops
# 백엔드 (터미널 1)
cd backend && npm install && npm run dev # localhost:3001
# 프론트엔드 (터미널 2)
cd frontend && npm install && npm run dev # localhost:5173
빌드/검증
# TypeScript 타입 체크
cd frontend && npx tsc --noEmit
cd backend && npx tsc --noEmit
# ESLint
cd frontend && npx eslint .
# 프로덕션 빌드
cd frontend && npm run build # tsc -b && vite build → dist/
cd backend && npm run build # tsc → dist/
환경 변수
프론트엔드 (frontend/.env):
VITE_API_URL=http://localhost:3001/api
VITE_GOOGLE_CLIENT_ID=your-google-client-id
백엔드 (backend/.env):
PORT=3001
NODE_ENV=development
JWT_SECRET=your-jwt-secret
AUTH_DB_HOST=localhost
AUTH_DB_PORT=5432
AUTH_DB_NAME=wing_auth
AUTH_DB_USER=wing_auth
AUTH_DB_PASSWORD=your-password
GOOGLE_CLIENT_ID=your-google-client-id
배포
개발 워크플로우
브랜치 분기 → 개발 → 커밋/푸시 → develop MR → main PR → 자동 배포
main: 배포 가능한 안정 브랜치 (보호됨)
develop: 개발 통합 브랜치 (보호됨)
feature/, bugfix/, hotfix/: 작업 브랜치
- 직접 push 금지, MR을 통해서만 머지
문서 안내
개발 가이드
운영 가이드
코드 컨벤션 (.claude/rules/)
| 규칙 |
설명 |
team-policy.md |
보안/품질 정책 |
git-workflow.md |
브랜치/커밋/MR 규칙 |
code-style.md |
TypeScript/React 코드 스타일 |
naming.md |
네이밍 규칙 |
testing.md |
테스트 규칙 |