291 lines
9.3 KiB
Markdown
Executable File
291 lines
9.3 KiB
Markdown
Executable File
# 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 (public, auth, wing 3개 스키마)
|
|
```
|
|
|
|
### 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 상수 체계)
|
|
│ └── tabs/ @tabs/ alias (11개 탭)
|
|
│ ├── 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는 re-export), seed
|
|
├── database/
|
|
│ ├── schema/ ERD용 순수 DDL (14파일)
|
|
│ ├── seed/ 초기 데이터 (14파일)
|
|
│ ├── migration/ 증분 마이그레이션 (001~016)
|
|
│ └── _deprecated/ 구 스크립트 (통합 이전)
|
|
└── .gitea/workflows/ CI/CD 파이프라인
|
|
```
|
|
|
|
### Path Alias
|
|
|
|
| Alias | 경로 |
|
|
|-------|------|
|
|
| `@common/*` | `src/common/*` |
|
|
| `@tabs/*` | `src/tabs/*` |
|
|
|
|
---
|
|
|
|
## 탭 구성 (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` | 시뮬레이션 실행/결과 |
|
|
|
|
---
|
|
|
|
## 데이터베이스
|
|
|
|
wing 단일 DB에 3개 스키마로 구성:
|
|
|
|
| 스키마 | 용도 | 테이블 수 |
|
|
|--------|------|-----------|
|
|
| public | PostGIS 확장 | - |
|
|
| auth | 인증/권한/감사로그 | 9 |
|
|
| wing | 운영 데이터 | 35 |
|
|
|
|
- 초기 DDL: `database/schema/` (14파일)
|
|
- 초기 데이터: `database/seed/` (14파일)
|
|
- 마이그레이션: `database/migration/001~016`
|
|
|
|
---
|
|
|
|
## 퀵스타트
|
|
|
|
### 사전 요구사항
|
|
|
|
- Node.js 20+ (`.node-version` 파일, fnm 사용)
|
|
- PostgreSQL 16+ (운영 DB 접근 가능해야 함)
|
|
|
|
### 실행
|
|
|
|
```bash
|
|
# 저장소 복제
|
|
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
|
|
```
|
|
|
|
### 빌드/검증
|
|
|
|
```bash
|
|
# 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
|
|
DB_HOST=211.208.115.83
|
|
DB_PORT=5432
|
|
DB_NAME=wing
|
|
DB_USER=wing
|
|
DB_PASSWORD=your-password
|
|
GOOGLE_CLIENT_ID=your-google-client-id
|
|
```
|
|
|
|
---
|
|
|
|
## 배포
|
|
|
|
| 항목 | 값 |
|
|
|------|---|
|
|
| 프론트엔드 | https://wing-demo.gc-si.dev |
|
|
| 백엔드 API | https://wing-demo.gc-si.dev/api/ |
|
|
| CI/CD | Gitea Actions (main 머지 시 자동 배포) |
|
|
|
|
---
|
|
|
|
## 개발 워크플로우
|
|
|
|
```
|
|
브랜치 분기 → 개발 → 커밋/푸시 → develop MR → main PR → 자동 배포
|
|
```
|
|
|
|
- `main`: 배포 가능한 안정 브랜치 (보호됨)
|
|
- `develop`: 개발 통합 브랜치 (보호됨)
|
|
- `feature/`, `bugfix/`, `hotfix/`: 작업 브랜치
|
|
- 직접 push 금지, MR을 통해서만 머지
|
|
|
|
---
|
|
|
|
## 문서 안내
|
|
|
|
### 개발 가이드
|
|
|
|
| 문서 | 설명 |
|
|
|------|------|
|
|
| [DEVELOPMENT-GUIDE.md](DEVELOPMENT-GUIDE.md) | 개발 워크플로우 전체 흐름 |
|
|
| [COMMON-GUIDE.md](COMMON-GUIDE.md) | 공통 로직 (인증, 감사로그, 메뉴, API, 상태관리) |
|
|
| [MENU-TAB-GUIDE.md](MENU-TAB-GUIDE.md) | 새 메뉴 탭 추가 절차 |
|
|
|
|
### 운영 가이드
|
|
|
|
| 문서 | 설명 |
|
|
|------|------|
|
|
| [INSTALL_GUIDE.md](INSTALL_GUIDE.md) | 설치 매뉴얼 (온라인/오프라인, DB 초기화) |
|
|
| [RELEASE-NOTES.md](RELEASE-NOTES.md) | 전체 변경 이력 |
|
|
|
|
### 코드 컨벤션 (`.claude/rules/`)
|
|
|
|
| 규칙 | 설명 |
|
|
|------|------|
|
|
| `team-policy.md` | 보안/품질 정책 |
|
|
| `git-workflow.md` | 브랜치/커밋/MR 규칙 |
|
|
| `code-style.md` | TypeScript/React 코드 스타일 |
|
|
| `naming.md` | 네이밍 규칙 |
|
|
| `testing.md` | 테스트 규칙 |
|