diff --git a/CLAUDE.md b/CLAUDE.md index 8695d31..42410c7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,8 +7,9 @@ - **프로젝트 타입**: react-ts (모노레포) - **Frontend**: React 19 + Vite 7 + TypeScript 5.9 + Tailwind CSS 3 - **Backend**: Express 4 + PostgreSQL (pg) + TypeScript +- **DB**: PostgreSQL 16 + PostGIS (wing 운영DB + wing_auth 인증DB) - **상태관리**: Zustand (클라이언트), TanStack Query (서버) -- **지도**: Leaflet +- **지도**: Leaflet + react-leaflet - **실시간**: Socket.IO ## 빌드/실행 @@ -49,16 +50,27 @@ wing/ ├── frontend/ React 19 + Vite + TypeScript + Tailwind │ └── src/ │ ├── App.tsx 메인 (탭 라우팅, 감사 로그 자동 기록) -│ ├── components/ UI 컴포넌트 -│ │ ├── auth/ 로그인 페이지 -│ │ ├── views/ 탭별 페이지 뷰 (11개) -│ │ ├── layout/ MainLayout, TopBar, LeftPanel, RightPanel -│ │ └── ... analysis, board, incidents, map, weather 등 -│ ├── hooks/ 커스텀 훅 -│ ├── services/ API 서비스 (api, authApi, weatherApi 등) -│ ├── store/ Zustand (authStore, menuStore) -│ ├── types/ 타입 정의 -│ └── utils/ 유틸리티 +│ ├── common/ 공통 모듈 (@common/ alias) +│ │ ├── components/ auth/, layer/, layout/, map/, ui/ +│ │ ├── hooks/ useLayers, useSubMenu +│ │ ├── services/ api.ts, authApi.ts, layerService.ts +│ │ ├── store/ authStore, menuStore (Zustand) +│ │ ├── types/ backtrack, boomLine, hns, navigation +│ │ ├── utils/ coordinates, geo, sanitize +│ │ ├── data/ layerData.ts (UI 레이어 트리) +│ │ └── mock/ vesselMockData, backtrackMockData +│ └── tabs/ 탭 단위 패키지 (@tabs/ alias) +│ ├── prediction/ 확산 예측 (OilSpillView, LeftPanel 등) +│ ├── hns/ HNS 분석 (HNSView, HNSSubstanceView 등) +│ ├── rescue/ 구조 시나리오 +│ ├── aerial/ 항공 방제 +│ ├── weather/ 해양 기상 (오버레이, hooks, services) +│ ├── incidents/ 사건/사고 관리 +│ ├── board/ 게시판 +│ ├── reports/ 보고서 +│ ├── assets/ 자산 관리 +│ ├── scat/ Pre-SCAT 조사 +│ └── admin/ 관리자 (사용자/권한/메뉴/설정) ├── backend/ Express + TypeScript │ └── src/ │ ├── server.ts 진입점 + 라우터 등록 @@ -68,15 +80,23 @@ wing/ │ ├── settings/ 시스템 설정 │ ├── menus/ 메뉴 설정 │ ├── audit/ 감사 로그 +│ ├── hns/ HNS 물질 검색 API │ ├── routes/ 레이어, 시뮬레이션 │ ├── middleware/ 보안 (입력 살균, rate-limit) -│ └── db/ DB 연결 (PostgreSQL: wing, wing_auth) -├── database/ SQL 초기화 스크립트 -├── docs/ 개발 문서 (README, 가이드, 변경이력) +│ └── db/ DB 연결 (wingDb, authDb), seed +├── database/ SQL 스크립트 +│ ├── init.sql wing DB 초기 스키마 +│ ├── auth_init.sql wing_auth DB 초기 스키마 +│ └── migration/ 마이그레이션 (001_layer, 002_hns_substance) +├── docs/ 개발 문서 ├── .claude/ 팀 워크플로우 (rules, skills, scripts) └── .githooks/ Git hooks (pre-commit, commit-msg) ``` +### Path Alias +- `@common/*` → `src/common/*` (공통 모듈) +- `@tabs/*` → `src/tabs/*` (탭 패키지) + ## 팀 컨벤션 `.claude/rules/` 디렉토리 참조: - `team-policy.md` — 보안/품질 정책 diff --git a/README.md b/README.md index 4fac801..aab89dc 100644 --- a/README.md +++ b/README.md @@ -90,17 +90,26 @@ cd frontend && npm install && npm run dev # localhost:5173 wing/ ├── frontend/ React 19 + Vite + TypeScript + Tailwind │ └── src/ -│ ├── App.tsx 메인 (탭 라우팅, 감사 로그 자동 기록) -│ ├── components/ UI 컴포넌트 -│ │ ├── auth/ 로그인 페이지 -│ │ ├── views/ 각 탭별 페이지 뷰 (11개) -│ │ ├── layout/ MainLayout, TopBar, LeftPanel, RightPanel -│ │ └── ... analysis, board, incidents, map, weather 등 -│ ├── hooks/ 커스텀 훅 -│ ├── services/ API 서비스 (api, authApi, weatherApi 등) -│ ├── store/ Zustand 상태 (authStore, menuStore) -│ ├── types/ 타입 정의 -│ └── utils/ 유틸리티 +│ ├── App.tsx 메인 (탭 라우팅, 감사 로그) +│ ├── common/ 공통 모듈 (@common/ alias) +│ │ ├── components/ auth/, layer/, layout/, map/, ui/ +│ │ ├── hooks/ useLayers, useSubMenu +│ │ ├── services/ api.ts, authApi.ts, layerService.ts +│ │ ├── store/ authStore, menuStore (Zustand) +│ │ ├── types/ backtrack, boomLine, hns, navigation +│ │ └── utils/ coordinates, geo, sanitize +│ └── tabs/ 탭 단위 패키지 (@tabs/ alias) +│ ├── prediction/ 확산 예측 +│ ├── hns/ HNS 분석 +│ ├── rescue/ 구조 시나리오 +│ ├── aerial/ 항공 방제 +│ ├── weather/ 해양 기상 +│ ├── incidents/ 사건/사고 +│ ├── board/ 게시판 +│ ├── reports/ 보고서 +│ ├── assets/ 자산 관리 +│ ├── scat/ Pre-SCAT +│ └── admin/ 관리자 ├── backend/ Express + TypeScript │ └── src/ │ ├── server.ts 진입점 + 라우터 등록 @@ -110,10 +119,11 @@ wing/ │ ├── settings/ 시스템 설정 │ ├── menus/ 메뉴 설정 │ ├── audit/ 감사 로그 +│ ├── hns/ HNS 물질 검색 API │ ├── routes/ 레이어, 시뮬레이션 │ ├── middleware/ 보안 (입력 살균, rate-limit) -│ └── db/ DB 연결 (PostgreSQL, SQLite) -├── database/ SQL 초기화 스크립트 +│ └── db/ DB 연결 (wingDb, authDb), seed +├── database/ SQL 스크립트 + 마이그레이션 ├── docs/ 개발 문서 ├── .claude/ 팀 워크플로우 (rules, skills, scripts) └── .githooks/ Git hooks (pre-commit, commit-msg) @@ -128,10 +138,10 @@ wing/ | Frontend | React 19, Vite 7, TypeScript 5.9, Tailwind CSS 3 | | Backend | Express 4, TypeScript, PostgreSQL (pg) | | 상태 관리 | Zustand (클라이언트), TanStack Query (서버) | -| 지도 | Leaflet, OpenLayers | +| 지도 | Leaflet + react-leaflet | | 실시간 | Socket.IO | | 인증 | JWT (HttpOnly Cookie), Google OAuth | -| DB | PostgreSQL 16 + PostGIS (운영 DB 직접 연결), SQLite | +| DB | PostgreSQL 16 + PostGIS (wing 운영DB + wing_auth 인증DB) | | CI/CD | Gitea Actions | --- diff --git a/docs/MENU-TAB-GUIDE.md b/docs/MENU-TAB-GUIDE.md index a9d68eb..e9bfb70 100644 --- a/docs/MENU-TAB-GUIDE.md +++ b/docs/MENU-TAB-GUIDE.md @@ -22,18 +22,19 @@ Frontend: menuStore.ts → TopBar.tsx (탭 렌더링) | 순서 | 파일 | 작업 | 필수 | |------|------|------|------| -| 1 | `frontend/src/components/views/XxxView.tsx` | 뷰 컴포넌트 생성 | O | -| 2 | `frontend/src/App.tsx` | MainTab 타입 + import + renderView | O | -| 3 | `backend/src/settings/settingsService.ts` | DEFAULT_MENU_CONFIG에 항목 추가 | O | -| 4 | `database/auth_init.sql` | menu.config 초기 JSON에 추가 | O | -| 5 | 관리자 UI | 메뉴 관리에서 활성화 | O | +| 1 | `frontend/src/tabs/{탭명}/components/XxxView.tsx` | 뷰 컴포넌트 생성 | O | +| 2 | `frontend/src/tabs/{탭명}/index.ts` | re-export 생성 | O | +| 3 | `frontend/src/App.tsx` | MainTab 타입 + import + renderView | O | +| 4 | `backend/src/settings/settingsService.ts` | DEFAULT_MENU_CONFIG에 항목 추가 | O | +| 5 | `database/auth_init.sql` | menu.config 초기 JSON에 추가 | O | +| 6 | 관리자 UI | 메뉴 관리에서 활성화 | O | ## Step 1: 뷰 컴포넌트 생성 -`frontend/src/components/views/` 에 새 뷰 컴포넌트를 생성합니다. +`frontend/src/tabs/{탭명}/components/` 에 새 뷰 컴포넌트를 생성합니다. ```tsx -// frontend/src/components/views/MonitoringView.tsx +// frontend/src/tabs/monitoring/components/MonitoringView.tsx export function MonitoringView() { return ( @@ -47,7 +48,14 @@ export function MonitoringView() { } ``` -기존 뷰 컴포넌트(`OilSpillView`, `WeatherView` 등)의 레이아웃 패턴을 참고하세요. +`index.ts`에서 re-export합니다: +```tsx +// frontend/src/tabs/monitoring/index.ts +export { MonitoringView } from './components/MonitoringView' +``` + +기존 탭(`@tabs/prediction`, `@tabs/weather` 등)의 레이아웃 패턴을 참고하세요. +공통 모듈은 `@common/` alias로 import합니다. ## Step 2: App.tsx 탭 등록 @@ -68,7 +76,7 @@ export type MainTab = 'prediction' | 'hns' | ... | 'monitoring' | 'admin' ### 2-2. 뷰 컴포넌트 import ```tsx -import { MonitoringView } from './components/views/MonitoringView' +import { MonitoringView } from '@tabs/monitoring' ``` ### 2-3. renderView switch에 case 추가 diff --git a/docs/README.md b/docs/README.md index 1606965..53f349e 100755 --- a/docs/README.md +++ b/docs/README.md @@ -36,10 +36,10 @@ claude | Frontend | React 19, Vite 7, TypeScript 5.9, Tailwind CSS 3 | | Backend | Express 4, TypeScript, PostgreSQL (pg) | | 상태 관리 | Zustand (클라이언트), TanStack Query (서버) | -| 지도 | Leaflet, OpenLayers | +| 지도 | Leaflet + react-leaflet | | 실시간 | Socket.IO | | 인증 | JWT (HttpOnly Cookie), Google OAuth | -| DB | PostgreSQL 16 + PostGIS (wing + wing_auth) | +| DB | PostgreSQL 16 + PostGIS (wing 운영DB + wing_auth 인증DB) | | CI/CD | Gitea Actions | --- @@ -50,18 +50,21 @@ claude wing/ ├── frontend/ React 19 + Vite + TypeScript + Tailwind │ └── src/ -│ ├── App.tsx 메인 (탭 라우팅, 감사 로그 자동 기록) -│ ├── components/ UI 컴포넌트 -│ │ ├── auth/ 로그인 페이지 -│ │ ├── views/ 각 탭별 페이지 뷰 (11개) -│ │ ├── layout/ MainLayout, TopBar, LeftPanel, RightPanel -│ │ ├── map/ 지도 관련 -│ │ └── ... analysis, board, incidents, weather 등 -│ ├── hooks/ 커스텀 훅 -│ ├── services/ API 서비스 (api, authApi, weatherApi 등) -│ ├── store/ Zustand 상태 (authStore, menuStore) -│ ├── types/ 타입 정의 -│ └── utils/ 유틸리티 +│ ├── App.tsx 메인 (탭 라우팅, 감사 로그) +│ ├── common/ 공통 모듈 (@common/ alias) +│ │ ├── components/ auth/, layer/, layout/, map/, ui/ +│ │ ├── hooks/ useLayers, useSubMenu +│ │ ├── services/ api.ts, authApi.ts, layerService.ts +│ │ ├── store/ authStore, menuStore (Zustand) +│ │ ├── types/ backtrack, boomLine, hns, navigation +│ │ └── utils/ coordinates, geo, sanitize +│ └── tabs/ 탭 단위 패키지 (@tabs/ alias) +│ ├── prediction/ 확산 예측 (OilSpillView, LeftPanel 등) +│ ├── hns/ HNS 분석 (HNSView, HNSSubstanceView 등) +│ ├── rescue/ 구조 시나리오 +│ ├── aerial/ 항공 방제 +│ ├── weather/ 해양 기상 +│ └── ... incidents, board, reports, assets, scat, admin ├── backend/ Express + TypeScript │ └── src/ │ ├── server.ts 진입점 + 라우터 등록 @@ -71,10 +74,11 @@ wing/ │ ├── settings/ 시스템 설정 │ ├── menus/ 메뉴 설정 │ ├── audit/ 감사 로그 +│ ├── hns/ HNS 물질 검색 API │ ├── routes/ 레이어, 시뮬레이션 │ ├── middleware/ 보안 (입력 살균, rate-limit) -│ └── db/ DB 연결 (PostgreSQL: wing, wing_auth) -├── database/ SQL 초기화 스크립트 +│ └── db/ DB 연결 (wingDb, authDb), seed +├── database/ SQL 스크립트 + 마이그레이션 ├── docs/ 개발 문서 ├── .claude/ 팀 워크플로우 (rules, skills, scripts) └── .githooks/ Git hooks (pre-commit, commit-msg) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index bc5b47b..7059d68 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -46,7 +46,8 @@ function App() { [JSON.stringify({ action: 'TAB_VIEW', detail: activeMainTab })], { type: 'text/plain' } ) - navigator.sendBeacon('/api/audit/log', blob) + const apiBase = import.meta.env.VITE_API_URL || 'http://localhost:3001/api' + navigator.sendBeacon(`${apiBase}/audit/log`, blob) }, [activeMainTab, isAuthenticated]) // 세션 확인 중 스플래시