import { useState } from 'react'; type TabId = 'framework' | 'target' | 'interface' | 'heterogeneous' | 'common-features'; const TABS: { id: TabId; label: string }[] = [ { id: 'framework', label: '표준 프레임워크' }, { id: 'target', label: '목표시스템 아키텍쳐' }, { id: 'interface', label: '시스템 인터페이스 연계' }, { id: 'heterogeneous', label: '이기종시스템연계' }, { id: 'common-features', label: '공통기능' }, ]; // ─── 기술 스택 테이블 데이터 ────────────────────────────────────────────────────── interface TechStackRow { category: string; tech: string; version: string; description: string; } const TECH_STACK: TechStackRow[] = [ { category: 'Frontend', tech: 'React', version: '19.x', description: '컴포넌트 기반 SPA' }, { category: 'Frontend', tech: 'TypeScript', version: '5.9', description: '정적 타입 시스템' }, { category: 'Frontend', tech: 'Vite', version: '7.x', description: '빌드 도구 (HMR)' }, { category: 'Frontend', tech: 'Tailwind CSS', version: '3.x', description: '유틸리티 기반 CSS' }, { category: 'Frontend', tech: 'MapLibre GL', version: '5.x', description: '오픈소스 GIS 엔진' }, { category: 'Frontend', tech: 'deck.gl', version: '9.x', description: '대규모 데이터 시각화' }, { category: 'Frontend', tech: 'Zustand', version: '-', description: '클라이언트 상태관리' }, { category: 'Frontend', tech: 'TanStack Query', version: '-', description: '서버 상태관리/캐싱' }, { category: 'Backend', tech: 'Express', version: '4.x', description: 'REST API 서버' }, { category: 'Backend', tech: 'Socket.IO', version: '-', description: '실시간 양방향 통신' }, { category: 'DB', tech: 'PostgreSQL', version: '16', description: '관계형 데이터베이스' }, { category: 'DB', tech: 'PostGIS', version: '-', description: '공간정보 확장' }, { category: '인증', tech: 'JWT', version: '-', description: '토큰 기반 인증 (HttpOnly Cookie)', }, { category: '인증', tech: 'Google OAuth', version: '2.0', description: 'SSO 연동' }, { category: '보안', tech: 'Helmet', version: '-', description: 'HTTP 헤더 보안' }, { category: '보안', tech: 'Rate Limiting', version: '-', description: 'API 호출 제한' }, { category: 'CI/CD', tech: 'Gitea Actions', version: '-', description: '자동 빌드/배포' }, ]; // ─── 탭 모듈 데이터 ─────────────────────────────────────────────────────────────── interface TabModuleRow { module: string; name: string; feature: string; integration: string; } const TAB_MODULES: TabModuleRow[] = [ { module: '확산예측', name: 'prediction', feature: '유출유 확산 시뮬레이션, 역추적 분석, 오일붐 배치', integration: 'KOSPS, 포세이돈 R&D', }, { module: 'HNS 분석', name: 'hns', feature: '화학물질 확산 예측, 물질 DB, 위험도 평가', integration: '충북대 R&D, 물질 DB', }, { module: '구조 시나리오', name: 'rescue', feature: '긴급구난 분석, 표류 예측', integration: '긴급구난 R&D', }, { module: '항공 방제', name: 'aerial', feature: '위성영상 분석, 드론 영상, 유막 면적 분석', integration: '위성/드론 데이터', }, { module: '해양 기상', name: 'weather', feature: '기상·해상 정보, 조위·해류 관측', integration: 'KHOA API, 기상청 API', }, { module: '사건/사고', name: 'incidents', feature: '해양오염 사고 등록·관리·이력', integration: '해경 사고 DB', }, { module: '자산 관리', name: 'assets', feature: '기관·장비·선박 보험 관리', integration: '해경 자산 DB', }, { module: 'SCAT 조사', name: 'scat', feature: 'Pre-SCAT 해안 조사 기록', integration: '현장 조사 데이터', }, { module: '관리자', name: 'admin', feature: '사용자/권한/메뉴/설정/연계 관리', integration: '전체 시스템', }, ]; // ─── 연계 인터페이스 데이터 ─────────────────────────────────────────────────────── interface InterfaceRow { system: string; method: string; data: string; cycle: string; protocol: string; } const INTERFACES: InterfaceRow[] = [ { system: 'KHOA (해양조사원)', method: 'REST API', data: '조위, 해류, 수온', cycle: '실시간/1시간', protocol: 'HTTPS', }, { system: '기상청', method: 'REST API', data: '풍향/풍속, 기압, 기온, 강수', cycle: '3시간', protocol: 'HTTPS', }, { system: 'HYCOM', method: '파일 수신', data: 'SST, 해류(U/V), SSH', cycle: '6시간', protocol: 'HTTPS/FTP', }, { system: '해경 KBP (인사)', method: '배치 수집', data: '사용자, 부서, 직위, 조직', cycle: '1일 1회', protocol: '내부망 API', }, { system: 'AIS 선박위치', method: '실시간 수집', data: '선박 위치, 속도, 방향', cycle: '실시간', protocol: 'Socket/API', }, { system: '포세이돈 R&D', method: 'API 연계', data: '유출유 확산 예측 결과', cycle: '요청 시', protocol: 'HTTPS', }, { system: 'KOSPS (광주)', method: 'DLL 호출', data: '유출유 확산 예측 결과', cycle: '요청 시', protocol: 'HTTPS (Fortran DLL)', }, { system: '충북대 HNS', method: 'API 호출', data: 'HNS 대기확산 결과', cycle: '요청 시', protocol: 'HTTPS', }, { system: '긴급구난 R&D', method: '내부 연계', data: '구난 분석 결과', cycle: '요청 시', protocol: '내부망 API', }, ]; // ─── 탭 1: 표준 프레임워크 ──────────────────────────────────────────────────────── function FrameworkTab() { return (
{/* 1. 개발 프레임워크 구성 */}

1. 개발 프레임워크 구성

{/* 프레젠테이션 계층 */}

프레젠테이션 계층

React 19 + TypeScript 5.9 + Tailwind CSS 3

{[ { name: 'MapLibre', sub: 'GL JS 5' }, { name: 'deck.gl', sub: '9.x' }, { name: 'Zustand', sub: '상태관리' }, { name: 'TanStack', sub: 'Query' }, ].map((item) => (

{item.name}

{item.sub}

))}
{/* 비즈니스 로직 계층 */}

비즈니스 로직 계층

Express 4 + TypeScript

{[ { name: 'JWT 인증', sub: 'OAuth2.0' }, { name: 'RBAC', sub: '권한엔진' }, { name: 'Socket.IO', sub: '실시간' }, { name: 'Helmet', sub: '보안' }, ].map((item) => (

{item.name}

{item.sub}

))}
{/* 데이터 접근 계층 */}

데이터 접근 계층

PostgreSQL 16 + PostGIS

{[ { name: 'wing DB', sub: '운영 DB' }, { name: 'wing_auth', sub: '인증 DB' }, { name: 'PostGIS', sub: '공간정보' }, ].map((item) => (

{item.name}

{item.sub}

))}
{/* 2. 기술 스택 상세 */}

2. 기술 스택 상세

{['구분', '기술', '버전', '설명'].map((h) => ( ))} {TECH_STACK.map((row, idx) => ( ))}
{h}
{row.category} {row.tech} {row.version} {row.description}
{/* 3. 개발 표준 및 규칙 */}

3. 개발 표준 및 규칙

{[ { title: 'HTTP 정책', content: 'GET/POST만 사용 (PUT/DELETE/PATCH 금지) — 한국 보안취약점 점검 가이드 준수', }, { title: '코드 표준', content: 'ESLint + Prettier 적용, TypeScript strict 모드 필수', }, { title: '모듈 구조', content: '@common/ (공통 모듈) + @tabs/ (업무별 탭) Path Alias 기반 분리', }, { title: '보안', content: '입력 살균(sanitize), XSS/SQL Injection 방지, CORS 정책, Rate Limiting', }, ].map((item) => (

{item.title}

{item.content}

))}
); } // ─── 탭 2: 목표시스템 아키텍쳐 ─────────────────────────────────────────────────── function TargetArchTab() { return (
{/* 1. 시스템 전체 구성도 */}

1. 시스템 전체 구성도

{/* 사용자 접근 계층 */}

사용자 접근 계층

웹 브라우저 (React SPA)

확산예측 | HNS분석 | 구조시나리오 | 항공방제 | 기상정보 | 사고관리 | SCAT조사 | 자산관리 | 관리자

{/* 화살표 + 프로토콜 */}
HTTPS (TLS 1.2+)
{/* API 서버 계층 */}

API 서버 계층

Express 4 REST API (Port 3001)

{[ 'JWT 인증 미들웨어', 'RBAC 권한 엔진 (permResolver)', '감사로그 자동 기록', '입력 살균 / Rate Limiting / Helmet', ].map((item) => (

{item}

))}
{/* 화살표 + 프로토콜 */}
pg connection pool
{/* 데이터 계층 */}

데이터 계층

PostgreSQL 16 + PostGIS

{[ { name: 'wing DB', sub: '운영' }, { name: 'wing_auth', sub: '인증' }, ].map((item) => (

{item.name}

({item.sub})

))}
{/* 2. 탭 기반 업무 모듈 구조 */}

2. 탭 기반 업무 모듈 구조

{['모듈', '패키지명', '기능', '주요 연계'].map((h) => ( ))} {TAB_MODULES.map((row) => ( ))}
{h}
{row.module} {row.name} {row.feature} {row.integration}
{/* 3. RBAC 권한 체계 */}

3. RBAC 권한 체계

{[ { title: '2차원 권한 엔진', content: 'AUTH_PERM OPER_CD 기반: R(조회), C(생성), U(수정), D(삭제) — 역할별 메뉴·기능 접근 제어', }, { title: 'permResolver', content: '역할(Role)과 권한(Permission)의 2차원 매핑으로 메뉴 표시 여부 및 기능 사용 가능 여부를 동적으로 판단', }, { title: '감사로그 자동 기록', content: '누가(사용자) / 언제(타임스탬프) / 무엇을(기능) / 어디서(IP, 메뉴) — 모든 주요 작업 자동 기록', }, ].map((item) => (

{item.title}

{item.content}

))}
); } // ─── 탭 3: 시스템 인터페이스 연계 ──────────────────────────────────────────────── function InterfaceTab() { const dataFlowSteps = [ '수집', '전처리', '저장', '분석/예측', '시각화', '의사결정지원', ]; return (
{/* 1. 외부 시스템 연계 구성도 */}

1. 외부 시스템 연계 구성도

{/* 외부 시스템 */}

외부 시스템

{['KHOA API', '기상청 API', '해경 KBP', 'AIS 선박'].map((item) => (

{item}

))}
{/* 화살표 */}
{/* 통합지원시스템 */}

해양환경 위기대응
통합지원시스템

연계관리 모듈

{['수집자료 관리', '연계 모니터링', '비식별화 조치'].map((item) => (

- {item}

))}
{/* 화살표 */}
{/* R&D 시스템 */}

R&D 시스템

{['포세이돈', 'KOSPS', '충북대 HNS', '긴급구난'].map((item) => (

{item}

))}
{/* 2. 연계 인터페이스 목록 */}

2. 연계 인터페이스 목록

{['연계 시스템', '연계 방식', '데이터', '주기', '프로토콜'].map((h) => ( ))} {INTERFACES.map((row) => ( ))}
{h}
{row.system} {row.method} {row.data} {row.cycle} {row.protocol}
{/* 3. 데이터 흐름도 */}

3. 데이터 흐름도

{dataFlowSteps.map((step, idx) => (

{step}

{idx < dataFlowSteps.length - 1 && ( )}
))}
{[ { step: '수집', desc: 'KHOA, 기상청, HYCOM, AIS 등 외부 원천 데이터 수신' }, { step: '전처리', desc: '포맷 변환, 좌표계 통일, 비식별화, 품질 검사' }, { step: '저장', desc: 'PostgreSQL 16 + PostGIS 공간정보 DB 적재' }, { step: '분석/예측', desc: 'R&D 모델 연계 (포세이돈, KOSPS, 충북대, 긴급구난)' }, { step: '시각화', desc: 'MapLibre GL + deck.gl 기반 지도 레이어 렌더링' }, { step: '의사결정지원', desc: '방제작전 시나리오, 구조분석, 경보 발령 지원' }, ].map((item) => (

{item.step}

{item.desc}

))}
{/* 4. 연계 장애 대응 */}

4. 연계 장애 대응

{[ { title: '연계 모니터링', content: '관리자 > 연계관리 > 연계모니터링에서 실시간 연계 상태 확인', }, { title: 'R&D 파이프라인 모니터링', content: '관리자 > 연계관리 > R&D과제에서 과제별 데이터 수신 이력 및 처리 현황 확인', }, { title: '장애 알림', content: '데이터 수신 지연/실패 발생 시 알림 발생 — 운영자 즉시 인지 가능', }, { title: '비식별화 조치', content: '개인정보 포함 데이터(해경 KBP 인사 등) 수집 시 자동 비식별화 처리 적용', }, ].map((item) => (

{item.title}

{item.content}

))}
); } // ─── 이기종시스템 연계 데이터 ───────────────────────────────────────────────────── interface HeterogeneousSystemRow { system: string; lang: string; os: string; location: string; protocol: string; description: string; } const HETEROGENEOUS_SYSTEMS: HeterogeneousSystemRow[] = [ { system: 'KOSPS', lang: 'Fortran', os: 'Linux', location: '광주', protocol: 'HTTPS (REST 래퍼)', description: '유출유 확산 예측 — Fortran DLL을 REST API로 래핑하여 연계', }, { system: '충북대 HNS', lang: 'Python / C++', os: 'Linux', location: '충북대', protocol: 'HTTPS', description: 'HNS 대기확산 예측 — Python/C++ 모델을 REST API로 호출', }, { system: '긴급구난', lang: 'Python', os: 'Linux', location: '해경 내부', protocol: '내부망 API', description: '구난 표류 분석 — Python 모델을 내부망 REST API로 연계', }, { system: 'HYCOM', lang: 'Fortran / NetCDF', os: 'Linux HPC', location: '미 해군 공개', protocol: 'HTTPS / FTP', description: '전지구 해류·수온 예측 — NetCDF 파일 수신 후 ETL 전처리', }, { system: '기상청', lang: '-', os: '-', location: '기상청 API Hub', protocol: 'HTTPS', description: '풍향·풍속·기온·강수 등 기상 데이터 REST API 수집', }, { system: 'KHOA', lang: '-', os: '-', location: '해양조사원', protocol: 'HTTPS', description: '조위·해류·수온 등 해양관측 데이터 REST API 수집', }, { system: '해경 KBP', lang: 'Java 전자정부', os: 'Linux', location: '해경 내부망', protocol: '내부망 API', description: '사용자·조직·직위 인사 데이터 배치 수집 (비식별화 적용)', }, { system: 'AIS', lang: '-', os: '-', location: '해경 AIS 서버', protocol: 'Socket / API', description: '선박 위치·속도·방향 실시간 수신', }, ]; interface HeterogeneousStrategyCard { challenge: string; solution: string; description: string; } interface IntegrationPlanItem { title: string; description: string; details?: string[]; } const INTEGRATION_PLANS: IntegrationPlanItem[] = [ { title: '사용자 정보 연계', description: '해양경찰청의 인사관리플랫폼과 연계 또는 사용자 정보를 제공받아 구성할 수 있어야 함', }, { title: '해양공간 데이터 연계', description: '해경 해양공간 데이터 구축사업(해양공간정보 활용체계 구축 및 빅데이터 관련 사업)의 \'데이터통합저장소\' 시스템과 연계하여 현장탐색 전자지도 자동표출 기술 등에 영상 및 사진자료를 연계하여 구축', }, { title: 'DB 통합설계 기반 맞춤형 인터페이스', description: '플랫폼 변경 및 신규 통합설계 되는 데이터베이스(DB) 구조 설계를 기반으로 사용자 맞춤형 화면 인터페이스를 구현해야 함', details: [ 'DBMS는 분리되어 있는 시스템들을 통합설계를 통하여 공통, 분야별 등으로 설계하여야 함', ], }, { title: '유출유 확산예측 정확성 향상 (KOSPS 연계)', description: '유출유 확산예측 정확성 향상을 위해, 해양오염방제지원시스템(KOSPS)를 연계·탑재하여야 함', details: [ '다양한 유출유 확산 예측 결과를 사용자가 한눈에 확인 가능하여야 함', '확산예측 기반으로 역추적, 최초 유출유 발생지점을 예측할 수 있어야 함', '그 밖에 유출유 확산예측 정확성 향상을 위한 대책을 마련하여야 함', ], }, { title: '기타 시스템 연계', description: '그 밖에 시스템 구축 중 효율적인 사고대응을 위한 타 시스템 연계할 수 있음', }, ]; const HETEROGENEOUS_STRATEGIES: HeterogeneousStrategyCard[] = [ { challenge: '언어 이질성', solution: 'REST API 래퍼 계층', description: 'Fortran, Python, C++, Java 등 각 언어로 작성된 모델을 REST API 래퍼로 감싸 언어·플랫폼 독립적인 표준 인터페이스 제공', }, { challenge: '데이터 형식 차이', solution: 'ETL 전처리 파이프라인', description: 'NetCDF, CSV, Binary, JSON 등 이기종 포맷을 ETL 파이프라인으로 표준 JSON/GeoJSON 형식으로 변환 후 DB 적재', }, { challenge: '네트워크 분리', solution: '이중 네트워크 연계', description: '외부망(인터넷) 연계와 내부망(해경 내부) 연계를 분리 운영하여 보안 정책 준수 및 데이터 안전성 확보', }, { challenge: '가용성·장애 대응', solution: '연계 모니터링 + 알림', description: '연계 상태를 실시간 모니터링하고 수신 지연·실패 발생 시 운영자에게 즉시 알림 발송하여 신속 대응', }, { challenge: '인증·보안 차이', solution: 'API Gateway 패턴', description: '시스템별 상이한 인증 방식(API Key, JWT, IP 제한 등)을 API Gateway 계층에서 통합 관리하여 단일 보안 정책 적용', }, { challenge: '프로토콜 차이', solution: '어댑터 패턴 적용', description: 'HTTP REST, FTP, Socket, 배치 파일 등 다양한 프로토콜을 어댑터 패턴으로 추상화하여 표준 인터페이스로 통일', }, ]; const HETEROGENEOUS_FLOW_STEPS = [ '원본 데이터', '수집 어댑터', 'ETL 전처리', '표준 변환', 'DB 적재', 'API 제공', ]; interface SecurityPolicyCard { title: string; items: string[]; } const HETEROGENEOUS_SECURITY: SecurityPolicyCard[] = [ { title: '외부망 연계', items: [ 'TLS 1.2+ 암호화 통신', 'API Key / OAuth 인증', 'IP 화이트리스트 제한', 'Rate Limiting 적용', ], }, { title: '내부망 연계', items: [ '전용 내부망 구간 분리', '상호 인증서 검증', '비식별화 자동 처리', '접근 이력 감사로그', ], }, { title: '데이터 보호', items: [ '개인정보 수집 최소화', 'ETL 단계 비식별화', '전송 구간 암호화', '저장 데이터 접근 제어', ], }, ]; // ─── 탭 4: 이기종시스템연계 ─────────────────────────────────────────────────────── function HeterogeneousTab() { return (
{/* 1. 이기종시스템 연계 개요 */}

1. 이기종시스템 연계 개요

통합지원시스템은 Fortran, Python, C++, Java 등 다양한 언어와 플랫폼으로 구현된 이기종 시스템과 연계한다. REST API 표준화, ETL 전처리, 어댑터 패턴을 통해 언어·플랫폼 독립적인 연계 구조를 구현하며, 외부망·내부망 이중 네트워크 정책을 준수한다.

이기종 시스템

{['Fortran KOSPS', 'Python/C++ 충북대', 'Java 해경KBP', 'NetCDF HYCOM'].map((item) => (

{item}

))}

연계 어댑터 계층

{['REST API 래퍼', 'ETL 전처리', '프로토콜 변환', '인증 통합'].map((item) => (

{item}

))}

통합지원시스템

{['Express REST API', 'PostgreSQL+PostGIS', 'React SPA', '표준 JSON'].map((item) => (

{item}

))}
{/* 2. 이기종 시스템 간의 연계 방안 */}

2. 이기종 시스템 간의 연계 방안

{INTEGRATION_PLANS.map((item, idx) => (

{idx + 1}. {item.title}

{item.description}

{item.details && (
    {item.details.map((detail) => (
  • {detail}
  • ))}
)}
))}
{/* 3. 연계 대상 이기종 시스템 목록 */}

3. 연계 대상 이기종 시스템 목록

{['시스템', '구현 언어', 'OS', '위치', '연계 프로토콜', '연계 설명'].map((h) => ( ))} {HETEROGENEOUS_SYSTEMS.map((row) => ( ))}
{h}
{row.system} {row.lang} {row.os} {row.location} {row.protocol} {row.description}
{/* 4. 이기종 연계 전략 */}

4. 이기종 연계 전략

{HETEROGENEOUS_STRATEGIES.map((card) => (
{card.challenge} {card.solution}

{card.description}

))}
{/* 5. 이기종 데이터 변환 흐름 */}

5. 이기종 데이터 변환 흐름

{HETEROGENEOUS_FLOW_STEPS.map((step, idx) => (

{step}

{idx < HETEROGENEOUS_FLOW_STEPS.length - 1 && ( )}
))}
{/* 6. 이기종 연계 보안 정책 */}

6. 이기종 연계 보안 정책

{HETEROGENEOUS_SECURITY.map((card) => (

{card.title}

    {card.items.map((item) => (
  • · {item}
  • ))}
))}
); } // ─── 공통기능 탭 데이터 ────────────────────────────────────────────────────────── interface CommonFeatureItem { title: string; description: string; details: string[]; } const COMMON_FEATURES: CommonFeatureItem[] = [ { title: '인증 시스템', description: 'JWT 기반 세션 인증 + Google OAuth 소셜 로그인', details: [ 'HttpOnly 쿠키(WING_SESSION) 기반 토큰 관리 — XSS 방어', 'Access Token(15분) + Refresh Token(7일) 이중 토큰 구조', 'Google OAuth 2.0 소셜 로그인 지원', 'Zustand authStore 기반 프론트엔드 인증 상태 통합 관리', ], }, { title: 'RBAC 2차원 권한', description: 'AUTH_PERM 기반 기능별·역할별 2차원 권한 엔진', details: [ 'OPER_CD (R: 조회, C: 생성, U: 수정, D: 삭제) 4단계 조작 권한', '역할(Role) × 기능(Feature) 매트릭스 기반 권한 매핑', 'permResolver 엔진으로 백엔드·프론트엔드 동시 권한 검증', '메뉴 접근, 버튼 노출, API 호출 3중 권한 통제', ], }, { title: 'API 통신 패턴', description: 'Axios 기반 공통 API 클라이언트 + 자동 인증·에러 처리', details: [ 'GET/POST만 사용 (PUT/DELETE/PATCH 금지 — 보안취약점 점검 가이드 준수)', '요청 인터셉터: 쿠키 자동 첨부 (withCredentials)', '응답 인터셉터: 401 시 자동 토큰 갱신, 실패 시 로그아웃', 'TanStack Query 기반 서버 상태 캐싱 및 자동 재검증', ], }, { title: '상태 관리', description: 'Zustand(클라이언트) + TanStack Query(서버) 이중 상태 관리', details: [ 'Zustand: authStore(인증), menuStore(메뉴) 등 클라이언트 전역 상태', 'TanStack Query: API 응답 캐싱, 자동 재요청, 낙관적 업데이트', '컴포넌트 로컬 상태: useState 활용', ], }, { title: '메뉴 시스템', description: 'DB 기반 동적 메뉴 + 권한 연동 자동 필터링', details: [ 'DB에서 메뉴 트리 구조를 동적으로 로드', '사용자 권한에 따라 메뉴 항목 자동 필터링 (접근 불가 메뉴 미노출)', '관리자 화면에서 메뉴 순서·표시 여부·아이콘 실시간 편집', 'menuStore(Zustand)로 현재 활성 메뉴 상태 전역 관리', ], }, { title: '지도 엔진', description: 'MapLibre GL JS 5.x + deck.gl 9.x 기반 GIS 시각화', details: [ 'MapLibre GL JS: 오픈소스 벡터 타일 기반 지도 렌더링', 'deck.gl: 대규모 공간 데이터(파티클, 히트맵, 궤적) 고성능 시각화', 'PostGIS 공간 쿼리 → GeoJSON → deck.gl 레이어 파이프라인', '레이어 트리 UI로 사용자별 레이어 표시·숨김 제어', ], }, { title: '스타일링', description: 'Tailwind CSS @layer 아키텍처 + CSS 변수 디자인 시스템', details: [ '@layer base → components → wing 3단계 CSS 계층 구조', 'CSS 변수 기반 시맨틱 컬러 (bg-bg-base, text-t1, border-stroke-1 등)', '다크 모드 기본 적용 — CSS 변수 전환으로 테마 일괄 변경', '인라인 스타일 지양, Tailwind 유틸리티 클래스 우선', ], }, { title: '감사 로그', description: '사용자 행위 자동 기록 — 접속·조회·변경 이력 추적', details: [ '로그인/로그아웃, 메뉴 접근, 데이터 변경 자동 기록', 'App.tsx에서 탭 전환 시 감사 로그 자동 전송', '관리자 화면에서 사용자별·기간별 감사 로그 조회 가능', 'IP 주소, User-Agent, 요청 경로 등 부가 정보 기록', ], }, { title: '보안', description: '입력 살균·CORS·CSP·Rate Limiting 다층 보안 정책', details: [ '입력 살균(sanitize): XSS·SQL Injection 방어 미들웨어 적용', 'Helmet: CSP, X-Frame-Options, HSTS 등 보안 헤더 자동 설정', 'CORS: 허용 오리진 화이트리스트 제한', 'Rate Limiting: API 요청 빈도 제한으로 DoS 방어', ], }, ]; // ─── 방제대응 프로세스 데이터 ───────────────────────────────────────────────────── interface ProcessStep { phase: string; description: string; modules: string[]; } const RESPONSE_PROCESS: ProcessStep[] = [ { phase: '사고 접수', description: '해양오염 사고 신고 접수 및 초동 상황 등록', modules: ['사건/사고'], }, { phase: '상황 파악', description: '사고 현장 기상·해상 조건 확인, 유출원·유출량 파악', modules: ['해양기상', '사건/사고'], }, { phase: '확산 예측', description: '유출유/HNS 확산 시뮬레이션 및 역추적 분석 수행', modules: ['확산예측', 'HNS분석'], }, { phase: '방제 계획', description: '오일붐 배치, 유처리제 살포 구역, 방제선 투입 계획 수립', modules: ['확산예측', '자산관리'], }, { phase: '구조 작전', description: '인명 구조 시나리오 수립, 표류 예측 기반 수색 구역 결정', modules: ['구조시나리오'], }, { phase: '항공 감시', description: '위성·드론 영상으로 유막 면적 모니터링 및 방제 효과 확인', modules: ['항공방제'], }, { phase: '해안 조사', description: 'Pre-SCAT 해안 오염 조사, 피해 범위 기록', modules: ['SCAT조사'], }, { phase: '상황 종료', description: '방제 완료 보고, 감사 이력 정리, 사후 분석', modules: ['사건/사고', '관리자'], }, ]; // ─── 시스템별 기능 유무 매트릭스 데이터 ──────────────────────────────────────────── const SYSTEM_MODULES = [ '확산예측', 'HNS분석', '구조시나리오', '항공방제', '해양기상', '사건/사고', '자산관리', 'SCAT조사', '게시판', '관리자', ] as const; interface FeatureMatrixRow { feature: string; category: '공통기능' | '기본정보관리' | '업무기능'; integrated: boolean; systems: Record; } const FEATURE_MATRIX: FeatureMatrixRow[] = [ { feature: '사용자 인증 (JWT)', category: '공통기능', integrated: true, systems: { '확산예측': true, 'HNS분석': true, '구조시나리오': true, '항공방제': true, '해양기상': true, '사건/사고': true, '자산관리': true, 'SCAT조사': true, '게시판': true, '관리자': true }, }, { feature: 'RBAC 권한 제어', category: '공통기능', integrated: true, systems: { '확산예측': true, 'HNS분석': true, '구조시나리오': true, '항공방제': true, '해양기상': true, '사건/사고': true, '자산관리': true, 'SCAT조사': true, '게시판': true, '관리자': true }, }, { feature: '감사 로그', category: '공통기능', integrated: true, systems: { '확산예측': true, 'HNS분석': true, '구조시나리오': true, '항공방제': true, '해양기상': true, '사건/사고': true, '자산관리': true, 'SCAT조사': true, '게시판': true, '관리자': true }, }, { feature: 'API 통신 (Axios)', category: '공통기능', integrated: true, systems: { '확산예측': true, 'HNS분석': true, '구조시나리오': true, '항공방제': true, '해양기상': true, '사건/사고': true, '자산관리': true, 'SCAT조사': true, '게시판': true, '관리자': true }, }, { feature: '입력 살균/보안', category: '공통기능', integrated: true, systems: { '확산예측': true, 'HNS분석': true, '구조시나리오': true, '항공방제': true, '해양기상': true, '사건/사고': true, '자산관리': true, 'SCAT조사': true, '게시판': true, '관리자': true }, }, { feature: '사용자 관리', category: '기본정보관리', integrated: true, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': true }, }, { feature: '지도 엔진 (MapLibre)', category: '기본정보관리', integrated: true, systems: { '확산예측': true, 'HNS분석': true, '구조시나리오': true, '항공방제': true, '해양기상': true, '사건/사고': true, '자산관리': false, 'SCAT조사': true, '게시판': false, '관리자': false }, }, { feature: '레이어 관리', category: '기본정보관리', integrated: true, systems: { '확산예측': true, 'HNS분석': true, '구조시나리오': true, '항공방제': true, '해양기상': true, '사건/사고': true, '자산관리': false, 'SCAT조사': true, '게시판': false, '관리자': true }, }, { feature: '메뉴 관리', category: '기본정보관리', integrated: true, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': true }, }, { feature: '시스템 설정', category: '기본정보관리', integrated: true, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': true }, }, { feature: '확산 시뮬레이션', category: '업무기능', integrated: false, systems: { '확산예측': true, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': false }, }, { feature: 'HNS 대기확산', category: '업무기능', integrated: false, systems: { '확산예측': false, 'HNS분석': true, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': false }, }, { feature: '표류 예측', category: '업무기능', integrated: false, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': true, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': false }, }, { feature: '위성/드론 영상', category: '업무기능', integrated: false, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': false, '항공방제': true, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': false }, }, { feature: '기상/해상 정보', category: '업무기능', integrated: false, systems: { '확산예측': true, 'HNS분석': true, '구조시나리오': true, '항공방제': false, '해양기상': true, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': false }, }, { feature: '역추적 분석', category: '업무기능', integrated: false, systems: { '확산예측': true, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': false }, }, { feature: '사고 등록/이력', category: '업무기능', integrated: false, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': true, '자산관리': false, 'SCAT조사': false, '게시판': false, '관리자': false }, }, { feature: '장비/선박 관리', category: '업무기능', integrated: false, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': true, 'SCAT조사': false, '게시판': false, '관리자': false }, }, { feature: '해안 조사', category: '업무기능', integrated: false, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': true, '게시판': false, '관리자': false }, }, { feature: '게시판 CRUD', category: '업무기능', integrated: false, systems: { '확산예측': false, 'HNS분석': false, '구조시나리오': false, '항공방제': false, '해양기상': false, '사건/사고': false, '자산관리': false, 'SCAT조사': false, '게시판': true, '관리자': false }, }, ]; const CATEGORY_STYLES: Record = { '공통기능': 'bg-cyan-600/20 text-cyan-300', '기본정보관리': 'bg-emerald-600/20 text-emerald-300', '업무기능': 'bg-bg-elevated text-t3', }; // ─── 탭 5: 공통기능 ───────────────────────────────────────────────────────────── function CommonFeaturesTab() { return (
{/* 1. 방제대응 프로세스 */}

1. 방제대응 프로세스

해양오염 사고 발생 시 사고 접수부터 상황 종료까지의 단계별 대응 프로세스이며, 각 단계에서 활용하는 시스템 모듈을 표시한다.

{/* 프로세스 흐름도 */}
{RESPONSE_PROCESS.map((step, idx) => (

{step.phase}

{step.modules.map((mod) => ( {mod} ))}
{idx < RESPONSE_PROCESS.length - 1 && ( )}
))}
{/* 프로세스 상세 */}
{RESPONSE_PROCESS.map((step, idx) => (
{idx + 1}

{step.phase}

{step.description}

{step.modules.map((mod) => ( {mod} ))}
))}
{/* 2. 시스템별 기능 유무 매트릭스 */}

2. 시스템별 기능 유무 매트릭스

각 시스템(업무 모듈)별 기능의 유무를 파악하여 공통기능, 기본정보 관리(사용자, 지도 등) 등 통합할 수 있는 기능을 표시한다. 통합 대상 기능은 공통 모듈로 일원화하여 중복 개발을 방지한다.

{SYSTEM_MODULES.map((mod) => ( ))} {FEATURE_MATRIX.map((row) => ( {SYSTEM_MODULES.map((mod) => ( ))} ))}
기능 분류 통합 {mod}
{row.feature} {row.category} {row.integrated ? ( 통합 ) : ( 개별 )} {row.systems[mod] ? ( O ) : ( - )}
{/* 범례 */}
공통기능 전 모듈 공통 적용
기본정보관리 사용자·지도·메뉴·설정 통합 관리
업무기능 모듈별 고유 기능
{/* 3. 공통기능 상세 */}

3. 공통기능 상세

{COMMON_FEATURES.map((feature, idx) => (
{idx + 1}

{feature.title}

{feature.description}

    {feature.details.map((detail) => (
  • {detail}
  • ))}
))}
{/* 4. 공통 모듈 구조 */}

4. 공통 모듈 디렉토리 구조

{['디렉토리', '역할', '주요 파일'].map((h) => ( ))} {[ { dir: 'common/components/', role: '공통 UI 컴포넌트', files: 'auth/, layout/, map/, ui/, layer/' }, { dir: 'common/hooks/', role: '공통 커스텀 훅', files: 'useLayers, useSubMenu, useFeatureTracking' }, { dir: 'common/services/', role: 'API 통신 모듈', files: 'api.ts, authApi.ts, layerService.ts' }, { dir: 'common/store/', role: '전역 상태 스토어', files: 'authStore.ts, menuStore.ts' }, { dir: 'common/styles/', role: 'CSS @layer 스타일', files: 'base.css, components.css, wing.css' }, { dir: 'common/types/', role: '공통 타입 정의', files: 'backtrack, hns, navigation 등' }, { dir: 'common/utils/', role: '유틸리티 함수', files: 'coordinates, geo, sanitize, cn.ts' }, { dir: 'common/constants/', role: '상수 정의', files: 'featureIds.ts' }, { dir: 'common/data/', role: 'UI 데이터', files: 'layerData.ts (레이어 트리)' }, ].map((row) => ( ))}
{h}
{row.dir} {row.role} {row.files}
); } // ─── 메인 패널 ─────────────────────────────────────────────────────────────────── export default function SystemArchPanel() { const [activeTab, setActiveTab] = useState('framework'); return (
{/* 헤더 */}

시스템구조

{/* 탭 버튼 */}
{TABS.map((tab) => ( ))}
{/* 탭 콘텐츠 */}
{activeTab === 'framework' && } {activeTab === 'target' && } {activeTab === 'interface' && } {activeTab === 'heterogeneous' && } {activeTab === 'common-features' && }
); }