From e18a1a4932d91856e9a98a52ccd6979bdb169484 Mon Sep 17 00:00:00 2001 From: Nan Kyung Lee Date: Sat, 21 Mar 2026 09:47:17 +0900 Subject: [PATCH] =?UTF-8?q?feat(layer):=20=EC=9C=84=ED=97=98/=EC=82=B0?= =?UTF-8?q?=EC=97=85=20=EC=9D=B8=ED=94=84=EB=9D=BC=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=96=B4=20=EA=B7=B8=EB=A3=B9=20=EB=B0=8F=20UI=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 위험시설: 석유화학단지(5), LNG기지(10), 유류탱크(15), 위험물항만(6) 추가 - 에너지/발전시설: 원자력(5), 화력(5) 추가; 발전/변전·풍력단지 그룹 이동 - 산업공정/제조시설: 조선소(6), 폐수처리(5), 시멘트/제철소(5) 추가 - 위험/산업 인프라 수퍼그룹 신설 (3단계 계층 구조) - LayerPanel: 레이어 수량을 우측 숫자 뱃지로 표시 (괄호 제거) - 해외시설 하위항목: 이란탭=호르무즈 10개국, 한국탭=중국·일본 - EventLog: 재난/안전뉴스 섹션 추가 (한국탭), OSINT 접기/펼치기 - OSINT 뉴스 2026-03-21 기준으로 업데이트 Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/App.tsx | 56 +- frontend/src/components/common/EventLog.tsx | 56 +- frontend/src/components/common/LayerPanel.tsx | 159 ++++-- .../components/korea/HazardFacilityLayer.tsx | 110 ++++ frontend/src/components/korea/KoreaMap.tsx | 10 + frontend/src/data/hazardFacilities.ts | 520 ++++++++++++++++++ frontend/src/i18n/locales/ko/common.json | 2 +- frontend/src/services/disasterNews.ts | 146 +++++ frontend/src/services/osint.ts | 397 +++++++++---- frontend/src/types.ts | 10 + 10 files changed, 1311 insertions(+), 155 deletions(-) create mode 100644 frontend/src/components/korea/HazardFacilityLayer.tsx create mode 100644 frontend/src/data/hazardFacilities.ts create mode 100644 frontend/src/services/disasterNews.ts diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index b85a8bd..a46dd8c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -65,6 +65,16 @@ function AuthenticatedApp({ user, onLogout }: AuthenticatedAppProps) { oilFacilities: true, meFacilities: true, militaryOnly: false, + overseasUS: false, + overseasUK: false, + overseasIran: false, + overseasUAE: false, + overseasSaudi: false, + overseasOman: false, + overseasQatar: false, + overseasKuwait: false, + overseasIraq: false, + overseasBahrain: false, }); // Korea tab layer visibility (lifted from KoreaMap) @@ -89,6 +99,17 @@ function AuthenticatedApp({ user, onLogout }: AuthenticatedAppProps) { nkMissile: true, cnFishing: false, militaryOnly: false, + overseasChina: false, + overseasJapan: false, + hazardPetrochemical: false, + hazardLng: false, + hazardOilTank: false, + hazardPort: false, + energyNuclear: false, + energyThermal: false, + industryShipyard: false, + industryWastewater: false, + industryHeavy: false, }); const toggleKoreaLayer = useCallback((key: string) => { @@ -456,6 +477,18 @@ function AuthenticatedApp({ user, onLogout }: AuthenticatedAppProps) { { key: 'meFacilities', label: '주요시설/군사', color: '#ef4444', count: 35 }, { key: 'sensorCharts', label: t('layers.sensorCharts'), color: '#22c55e' }, ]} + overseasItems={[ + { key: 'overseasUS', label: '🇺🇸 미국', color: '#3b82f6' }, + { key: 'overseasUK', label: '🇬🇧 영국', color: '#dc2626' }, + { key: 'overseasIran', label: '🇮🇷 이란', color: '#22c55e' }, + { key: 'overseasUAE', label: '🇦🇪 UAE', color: '#f59e0b' }, + { key: 'overseasSaudi', label: '🇸🇦 사우디아라비아', color: '#84cc16' }, + { key: 'overseasOman', label: '🇴🇲 오만', color: '#e11d48' }, + { key: 'overseasQatar', label: '🇶🇦 카타르', color: '#8b5cf6' }, + { key: 'overseasKuwait', label: '🇰🇼 쿠웨이트', color: '#f97316' }, + { key: 'overseasIraq', label: '🇮🇶 이라크', color: '#65a30d' }, + { key: 'overseasBahrain', label: '🇧🇭 바레인', color: '#e11d48' }, + ]} hiddenAcCategories={hiddenAcCategories} hiddenShipCategories={hiddenShipCategories} onAcCategoryToggle={toggleAcCategory} @@ -585,15 +618,30 @@ function AuthenticatedApp({ user, onLogout }: AuthenticatedAppProps) { { key: 'eez', label: t('layers.eez'), color: '#3b82f6', group: '해양안전' }, { key: 'piracy', label: t('layers.piracy'), color: '#ef4444', group: '해양안전' }, { key: 'nkMissile', label: '🚀 미사일 낙하', color: '#ef4444', count: 4, group: '해양안전' }, - { key: 'cnFishing', label: '🎣 중국어선 어구', color: '#f97316', group: '해양안전' }, // 국가기관망 - { key: 'infra', label: t('layers.infra'), color: '#ffc107', group: '국가기관망' }, + { key: 'infra', label: t('layers.infra'), color: '#ffc107', group: '에너지/발전시설' }, { key: 'airports', label: t('layers.airports'), color: '#a78bfa', count: 59, group: '국가기관망' }, - { key: 'windFarm', label: '풍력단지', color: '#00bcd4', count: 8, group: '국가기관망' }, + { key: 'windFarm', label: '풍력단지', color: '#00bcd4', count: 8, group: '에너지/발전시설' }, { key: 'ports', label: '항구', color: '#3b82f6', count: 46, group: '국가기관망' }, { key: 'militaryBases', label: '군사시설', color: '#ef4444', count: 38, group: '국가기관망' }, { key: 'govBuildings', label: '정부기관', color: '#f59e0b', count: 32, group: '국가기관망' }, - { key: 'nkLaunch', label: '🇰🇵 발사/포병진지', color: '#dc2626', count: 19, group: '국가기관망' }, + { key: 'nkLaunch', label: '🇰🇵 발사/포병진지', color: '#dc2626', count: 19, group: '해양안전' }, + // 위험시설 + { key: 'hazardPetrochemical', label: '해안인접석유화학단지', color: '#f97316', count: 5, group: '위험시설' }, + { key: 'hazardLng', label: 'LNG저장기지', color: '#06b6d4', count: 10, group: '위험시설' }, + { key: 'hazardOilTank', label: '유류저장탱크', color: '#eab308', count: 15, group: '위험시설' }, + { key: 'hazardPort', label: '위험물항만하역시설', color: '#ef4444', count: 6, group: '위험시설' }, + // 에너지/발전시설 + { key: 'energyNuclear', label: '원자력발전', color: '#a855f7', count: 5, group: '에너지/발전시설' }, + { key: 'energyThermal', label: '화력발전소', color: '#64748b', count: 5, group: '에너지/발전시설' }, + // 산업공정/제조시설 + { key: 'industryShipyard', label: '조선소 도장시설', color: '#0ea5e9', count: 6, group: '산업공정/제조시설' }, + { key: 'industryWastewater', label: '폐수/하수처리장', color: '#10b981', count: 5, group: '산업공정/제조시설' }, + { key: 'industryHeavy', label: '시멘트/제철소', color: '#94a3b8', count: 5, group: '산업공정/제조시설' }, + ]} + overseasItems={[ + { key: 'overseasChina', label: '🇨🇳 중국', color: '#ef4444' }, + { key: 'overseasJapan', label: '🇯🇵 일본', color: '#f472b6' }, ]} hiddenAcCategories={hiddenAcCategories} hiddenShipCategories={hiddenShipCategories} diff --git a/frontend/src/components/common/EventLog.tsx b/frontend/src/components/common/EventLog.tsx index be8818f..12bdb9b 100644 --- a/frontend/src/components/common/EventLog.tsx +++ b/frontend/src/components/common/EventLog.tsx @@ -2,6 +2,7 @@ import { useMemo, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import type { GeoEvent, Ship } from '../../types'; import type { OsintItem } from '../../services/osint'; +import { getDisasterNews, getDisasterCatIcon, getDisasterCatColor } from '../../services/disasterNews'; import { getMarineTrafficCategory } from '../../utils/marineTraffic'; import { aggregateFishingStats, GEAR_LABELS } from '../../utils/fishingAnalysis'; import type { FishingGearType } from '../../utils/fishingAnalysis'; @@ -329,7 +330,7 @@ const NEWS_CATEGORY_COLORS: Record = { }; const EMPTY_OSINT: OsintItem[] = []; -const EMPTY_SHIPS: import('../types').Ship[] = []; +const EMPTY_SHIPS: Ship[] = []; function useTimeAgo() { const { t } = useTranslation('common'); @@ -597,7 +598,7 @@ export function EventLog({ events, currentTime, totalShipCount: _totalShipCount, {'\u{1F1F0}\u{1F1F7}'} {t('ships:shipStatus.koreanTitle')} {koreanShips.length}{t('common:units.vessels')} - {onToggleHighlightKorean && dashboardTab === 'iran' && ( + {onToggleHighlightKorean && (dashboardTab as string) === 'iran' && ( ); diff --git a/frontend/src/components/korea/HazardFacilityLayer.tsx b/frontend/src/components/korea/HazardFacilityLayer.tsx new file mode 100644 index 0000000..f4e4923 --- /dev/null +++ b/frontend/src/components/korea/HazardFacilityLayer.tsx @@ -0,0 +1,110 @@ +import { useState } from 'react'; +import { Marker, Popup } from 'react-map-gl/maplibre'; +import { HAZARD_FACILITIES } from '../../data/hazardFacilities'; +import type { HazardFacility, HazardType } from '../../data/hazardFacilities'; + +interface Props { + type: HazardType; +} + +const TYPE_META: Record = { + petrochemical: { icon: '🏭', color: '#f97316', label: '석유화학단지', bgColor: 'rgba(249,115,22,0.15)' }, + lng: { icon: '🔵', color: '#06b6d4', label: 'LNG저장기지', bgColor: 'rgba(6,182,212,0.15)' }, + oilTank: { icon: '🛢️', color: '#eab308', label: '유류저장탱크', bgColor: 'rgba(234,179,8,0.15)' }, + hazardPort: { icon: '⚠️', color: '#ef4444', label: '위험물하역시설', bgColor: 'rgba(239,68,68,0.15)' }, + nuclear: { icon: '☢️', color: '#a855f7', label: '원자력발전소', bgColor: 'rgba(168,85,247,0.15)' }, + thermal: { icon: '🔥', color: '#64748b', label: '화력발전소', bgColor: 'rgba(100,116,139,0.15)' }, + shipyard: { icon: '🚢', color: '#0ea5e9', label: '조선소 도장시설', bgColor: 'rgba(14,165,233,0.15)' }, + wastewater: { icon: '💧', color: '#10b981', label: '폐수처리장', bgColor: 'rgba(16,185,129,0.15)' }, + heavyIndustry: { icon: '⚙️', color: '#94a3b8', label: '시멘트/제철소', bgColor: 'rgba(148,163,184,0.15)' }, +}; + +export function HazardFacilityLayer({ type }: Props) { + const [selected, setSelected] = useState(null); + const meta = TYPE_META[type]; + const facilities = HAZARD_FACILITIES.filter(f => f.type === type); + + return ( + <> + {facilities.map(f => ( + { e.originalEvent.stopPropagation(); setSelected(f); }}> +
+
+ {meta.icon} +
+
+ {f.nameKo.length > 12 ? f.nameKo.slice(0, 12) + '..' : f.nameKo} +
+
+
+ ))} + + {selected && ( + setSelected(null)} closeOnClick={false} + anchor="bottom" maxWidth="300px" className="gl-popup" + > +
+
+ {meta.icon} + {selected.nameKo} +
+ +
+ + {meta.label} + + + ⚠️ 위험시설 + +
+ +
+ {selected.description} +
+ +
+ {selected.address && ( +
주소 : {selected.address}
+ )} + {selected.operator && ( +
운영자 : {selected.operator}
+ )} + {selected.capacity && ( +
처리규모 : {selected.capacity}
+ )} +
시설명(EN) : {selected.name}
+
+ +
+ {selected.lat.toFixed(4)}°N, {selected.lng.toFixed(4)}°E +
+
+
+ )} + + ); +} diff --git a/frontend/src/components/korea/KoreaMap.tsx b/frontend/src/components/korea/KoreaMap.tsx index 807eb55..6991a87 100644 --- a/frontend/src/components/korea/KoreaMap.tsx +++ b/frontend/src/components/korea/KoreaMap.tsx @@ -21,6 +21,7 @@ import { GovBuildingLayer } from './GovBuildingLayer'; import { NKLaunchLayer } from './NKLaunchLayer'; import { NKMissileEventLayer } from './NKMissileEventLayer'; import { ChineseFishingOverlay } from './ChineseFishingOverlay'; +import { HazardFacilityLayer } from './HazardFacilityLayer'; import { fetchKoreaInfra } from '../../services/infra'; import type { PowerFacility } from '../../services/infra'; import type { Ship, Aircraft, SatellitePosition } from '../../types'; @@ -269,6 +270,15 @@ export function KoreaMap({ ships, aircraft, satellites, layers, osintFeed, curre {layers.nkLaunch && } {layers.nkMissile && } {layers.cnFishing && } + {layers.hazardPetrochemical && } + {layers.hazardLng && } + {layers.hazardOilTank && } + {layers.hazardPort && } + {layers.energyNuclear && } + {layers.energyThermal && } + {layers.industryShipyard && } + {layers.industryWastewater && } + {layers.industryHeavy && } {layers.airports && } {layers.coastGuard && } {layers.navWarning && } diff --git a/frontend/src/data/hazardFacilities.ts b/frontend/src/data/hazardFacilities.ts new file mode 100644 index 0000000..45ca368 --- /dev/null +++ b/frontend/src/data/hazardFacilities.ts @@ -0,0 +1,520 @@ +export type HazardType = 'petrochemical' | 'lng' | 'oilTank' | 'hazardPort' | 'nuclear' | 'thermal' | 'shipyard' | 'wastewater' | 'heavyIndustry'; + +export interface HazardFacility { + id: string; + type: HazardType; + nameKo: string; + name: string; + lat: number; + lng: number; + address?: string; + capacity?: string; + operator?: string; + description: string; +} + +export const HAZARD_FACILITIES: HazardFacility[] = [ + // ── 해안인접석유화학단지 ────────────────────────────────────────── + { + id: 'pc-01', type: 'petrochemical', + nameKo: '여수국가산업단지', name: 'Yeosu National Industrial Complex', + lat: 34.757, lng: 127.723, + address: '전남 여수시 화치동 산 183-1', + capacity: '연산 2,400만 톤', operator: '여수광양항만공사·LG화학·롯데케미칼', + description: '국내 최대 석유화학단지. NCC·LG화학·롯데케미칼·GS칼텍스 등 입주.', + }, + { + id: 'pc-02', type: 'petrochemical', + nameKo: '울산미포국가산업단지', name: 'Ulsan Mipo National Industrial Complex', + lat: 35.479, lng: 129.357, + address: '울산광역시 남구 사평로 137 (부곡동 439-1)', + capacity: '연산 1,800만 톤', operator: 'S-OIL·SK에너지·SK지오센트릭', + description: '정유·NCC 중심 울산미포국가산단 내 석유화학 집적지.', + }, + { + id: 'pc-03', type: 'petrochemical', + nameKo: '대산석유화학단지', name: 'Daesan Petrochemical Complex', + lat: 37.025, lng: 126.360, + address: '충남 서산시 대산읍 독곶1로 82 (롯데케미칼 대산공장 기준)', + capacity: '연산 900만 톤', operator: '롯데케미칼·현대오일뱅크·한화토탈에너지스', + description: '충남 서산 대산항 인근 3대 석유화학단지.', + }, + { + id: 'pc-04', type: 'petrochemical', + nameKo: '광양 석유화학단지', name: 'Gwangyang Petrochemical Complex', + lat: 34.970, lng: 127.705, + capacity: '연산 600만 톤', operator: 'POSCO·포스코케미칼', + description: '광양제철소 연계 석유화학 시설.', + }, + { + id: 'pc-05', type: 'petrochemical', + nameKo: '인천 석유화학단지', name: 'Incheon Petrochemical Complex', + lat: 37.470, lng: 126.618, + capacity: '연산 400만 톤', operator: 'SK인천석유화학', + description: '인천 북항 인근 정유·석유화학 시설.', + }, + + // ── LNG 생산기지 (한국가스공사 KOGAS) ──────────────────────────── + { + id: 'lng-01', type: 'lng', + nameKo: '평택 LNG 생산기지', name: 'Pyeongtaek LNG Production Base', + lat: 37.017, lng: 126.870, + address: '경기도 평택시 포승읍', + operator: '한국가스공사(KOGAS)', + description: '국내 최초의 LNG 기지. 수도권 공급의 핵심 거점.', + }, + { + id: 'lng-02', type: 'lng', + nameKo: '인천 LNG 생산기지', name: 'Incheon LNG Production Base', + lat: 37.374, lng: 126.622, + address: '인천광역시 연수구 송도동', + operator: '한국가스공사(KOGAS)', + description: '세계 최대 규모의 해상 LNG 기지 중 하나.', + }, + { + id: 'lng-03', type: 'lng', + nameKo: '통영 LNG 생산기지', name: 'Tongyeong LNG Production Base', + lat: 34.906, lng: 128.465, + address: '경상남도 통영시 광도면', + operator: '한국가스공사(KOGAS)', + description: '남부권 가스 공급 및 영남권 산업단지 지원 거점.', + }, + { + id: 'lng-04', type: 'lng', + nameKo: '삼척 LNG 생산기지', name: 'Samcheok LNG Production Base', + lat: 37.262, lng: 129.290, + address: '강원도 삼척시 원덕읍', + operator: '한국가스공사(KOGAS)', + description: '동해안 에너지 거점 및 수입 다변화 대응.', + }, + { + id: 'lng-05', type: 'lng', + nameKo: '제주 LNG 생산기지', name: 'Jeju LNG Production Base', + lat: 33.448, lng: 126.330, + address: '제주특별자치도 제주시 애월읍', + operator: '한국가스공사(KOGAS)', + description: '제주 지역 천연가스 보급을 위해 조성된 기지.', + }, + { + id: 'lng-06', type: 'lng', + nameKo: '당진 LNG 생산기지', name: 'Dangjin LNG Production Base', + lat: 37.048, lng: 126.595, + address: '충청남도 당진시 석문면', + operator: '한국가스공사(KOGAS)', + description: '2026년 말 1단계 준공 예정 (현재 건설 중).', + }, + + // ── 민간 LNG 터미널 ────────────────────────────────────────────── + { + id: 'lng-p01', type: 'lng', + nameKo: '광양 LNG 터미널', name: 'Gwangyang LNG Terminal', + lat: 34.934, lng: 127.714, + address: '전라남도 광양시 금호동', + operator: '포스코인터내셔널', + description: '포스코인터내셔널 운영 민간 LNG 터미널.', + }, + { + id: 'lng-p02', type: 'lng', + nameKo: '보령 LNG 터미널', name: 'Boryeong LNG Terminal', + lat: 36.380, lng: 126.513, + address: '충청남도 보령시 오천면', + operator: 'SK E&S · GS에너지', + description: 'SK E&S·GS에너지 공동 운영 민간 LNG 터미널.', + }, + { + id: 'lng-p03', type: 'lng', + nameKo: '울산 북항 에너지터미널', name: 'Ulsan North Port Energy Terminal', + lat: 35.518, lng: 129.383, + address: '울산광역시 남구 북항 일원', + operator: 'KET (한국석유공사·SK Gas 등)', + description: 'KET(Korea Energy Terminal) 운영 민간 에너지터미널.', + }, + { + id: 'lng-p04', type: 'lng', + nameKo: '통영 에코파워 LNG', name: 'Tongyeong Ecopower LNG Terminal', + lat: 34.873, lng: 128.508, + address: '경상남도 통영시 광도면 (성동조선 인근)', + operator: 'HDC현대산업개발 등', + description: '성동조선 인근 민간 LNG 터미널.', + }, + + // ── 유류저장탱크 ────────────────────────────────────────────────── + { + id: 'oil-01', type: 'oilTank', + nameKo: '여수 유류저장시설', name: 'Yeosu Oil Storage', + lat: 34.733, lng: 127.741, + capacity: '630만 ㎘', operator: 'SK에너지·GS칼텍스', + description: '여수항 인근 정유제품 및 원유 저장시설.', + }, + { + id: 'oil-02', type: 'oilTank', + nameKo: '울산 정유 저장시설', name: 'Ulsan Refinery Storage', + lat: 35.516, lng: 129.413, + capacity: '850만 ㎘', operator: 'S-OIL·SK에너지', + description: '울산 온산 정유시설 연계 대형 유류탱크군.', + }, + { + id: 'oil-03', type: 'oilTank', + nameKo: '포항 저유소', name: 'Pohang Oil Depot', + lat: 36.018, lng: 129.380, + capacity: '20만 ㎘', operator: '대한송유관공사', + description: '동해안 석유 공급 거점 저유소.', + }, + { + id: 'oil-04', type: 'oilTank', + nameKo: '목포 유류저장', name: 'Mokpo Oil Storage', + lat: 34.773, lng: 126.384, + capacity: '30만 ㎘', operator: '한국석유공사', + description: '서남해안 유류 공급 저장기지.', + }, + { + id: 'oil-05', type: 'oilTank', + nameKo: '부산 북항 저유소', name: 'Busan North Port Oil Depot', + lat: 35.100, lng: 129.041, + capacity: '45만 ㎘', operator: '대한송유관공사', + description: '부산항 연계 유류 저장·공급 시설.', + }, + { + id: 'oil-06', type: 'oilTank', + nameKo: '보령 저유소', name: 'Boryeong Oil Depot', + lat: 36.380, lng: 126.570, + capacity: '15만 ㎘', operator: '대한송유관공사', + description: '충남 서해안 유류 공급 저장기지.', + }, + + // ── KNOC 국가 석유비축기지 ──────────────────────────────────────── + { + id: 'knoc-01', type: 'oilTank', + nameKo: 'KNOC 울산 비축기지', name: 'KNOC Ulsan SPR Base', + lat: 35.406, lng: 129.351, + address: '울산광역시 울주군 온산읍 학남리', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. 원유 (지상탱크) 방식.', + }, + { + id: 'knoc-02', type: 'oilTank', + nameKo: 'KNOC 여수 비축기지', name: 'KNOC Yeosu SPR Base', + lat: 34.716, lng: 127.742, + address: '전라남도 여수시 낙포동', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. 원유 (지상탱크·지하공동) 방식.', + }, + { + id: 'knoc-03', type: 'oilTank', + nameKo: 'KNOC 거제 비축기지', name: 'KNOC Geoje SPR Base', + lat: 34.852, lng: 128.722, + address: '경상남도 거제시 일운면 지세포리', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. 원유 (지하공동) 방식.', + }, + { + id: 'knoc-04', type: 'oilTank', + nameKo: 'KNOC 서산 비축기지', name: 'KNOC Seosan SPR Base', + lat: 37.018, lng: 126.374, + address: '충청남도 서산시 대산읍 대죽리', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. 원유·제품 (지상탱크) 방식.', + }, + { + id: 'knoc-05', type: 'oilTank', + nameKo: 'KNOC 평택 비축기지', name: 'KNOC Pyeongtaek SPR Base', + lat: 37.017, lng: 126.858, + address: '경기도 평택시 포승읍 원정리', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. LPG 방식.', + }, + { + id: 'knoc-06', type: 'oilTank', + nameKo: 'KNOC 구리 비축기지', name: 'KNOC Guri SPR Base', + lat: 37.562, lng: 127.138, + address: '경기도 구리시 아차산로', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. 제품 (지하공동) 방식.', + }, + { + id: 'knoc-07', type: 'oilTank', + nameKo: 'KNOC 용인 비축기지', name: 'KNOC Yongin SPR Base', + lat: 37.238, lng: 127.213, + address: '경기도 용인시 처인구 해실로', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. 제품 (지상탱크) 방식.', + }, + { + id: 'knoc-08', type: 'oilTank', + nameKo: 'KNOC 동해 비축기지', name: 'KNOC Donghae SPR Base', + lat: 37.503, lng: 129.097, + address: '강원특별자치도 동해시 공단12로', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. 제품 (지상탱크) 방식.', + }, + { + id: 'knoc-09', type: 'oilTank', + nameKo: 'KNOC 곡성 비축기지', name: 'KNOC Gokseong SPR Base', + lat: 35.228, lng: 127.302, + address: '전라남도 곡성군 겸면 괴정리', + capacity: '국가비축', operator: '한국석유공사(KNOC)', + description: '국가 전략 석유비축기지. 제품 (지상탱크) 방식.', + }, + + // ── 위험물항만하역시설 ──────────────────────────────────────────── + { + id: 'hp-01', type: 'hazardPort', + nameKo: '광양항 위험물 부두', name: 'Gwangyang Hazardous Cargo Terminal', + lat: 34.923, lng: 127.703, + capacity: '연 3,000만 톤', operator: '여수광양항만공사', + description: '석유화학제품·액체화물 전용 위험물 하역 부두.', + }, + { + id: 'hp-02', type: 'hazardPort', + nameKo: '울산항 위험물 부두', name: 'Ulsan Hazardous Cargo Terminal', + lat: 35.519, lng: 129.392, + capacity: '연 2,500만 톤', operator: '울산항만공사', + description: '원유·석유제품·LPG 등 위험물 전용 하역 부두.', + }, + { + id: 'hp-03', type: 'hazardPort', + nameKo: '인천항 위험물 부두', name: 'Incheon Hazardous Cargo Terminal', + lat: 37.464, lng: 126.621, + capacity: '연 800만 톤', operator: '인천항만공사', + description: '인천 북항 위험물(화학·가스·유류) 하역 전용 부두.', + }, + { + id: 'hp-04', type: 'hazardPort', + nameKo: '여수항 위험물 부두', name: 'Yeosu Hazardous Cargo Terminal', + lat: 34.729, lng: 127.741, + capacity: '연 1,200만 톤', operator: '여수광양항만공사', + description: '여수 석유화학단지 연계 위험물 하역 부두.', + }, + { + id: 'hp-05', type: 'hazardPort', + nameKo: '부산항 위험물 부두', name: 'Busan Hazardous Cargo Terminal', + lat: 35.090, lng: 129.022, + capacity: '연 500만 톤', operator: '부산항만공사', + description: '부산 신항·북항 위험물 전용 하역 부두.', + }, + { + id: 'hp-06', type: 'hazardPort', + nameKo: '군산항 위험물 부두', name: 'Gunsan Hazardous Cargo Terminal', + lat: 35.973, lng: 126.712, + capacity: '연 300만 톤', operator: '군산항만공사', + description: '서해안 위험물(석유·화학) 하역 부두.', + }, + + // ── 원자력발전소 ────────────────────────────────────────────────── + { + id: 'npp-01', type: 'nuclear', + nameKo: '고리 원자력발전소', name: 'Kori Nuclear Power Plant', + lat: 35.316, lng: 129.291, + address: '부산광역시 기장군 장안읍 고리', + capacity: '4기 (신고리 포함 총 6기)', operator: '한국수력원자력(한수원)', + description: '국내 최초 상업용 원전 부지. 1호기 영구정지(2017), 신고리 1~4호기 운영 중.', + }, + { + id: 'npp-02', type: 'nuclear', + nameKo: '월성 원자력발전소', name: 'Wolseong Nuclear Power Plant', + lat: 35.712, lng: 129.476, + address: '경상북도 경주시 양남면 나아리', + capacity: '4기 (월성·신월성)', operator: '한국수력원자력(한수원)', + description: '중수로(CANDU) 방식. 월성 1호기 영구정지(2019), 신월성 1·2호기 운영 중.', + }, + { + id: 'npp-03', type: 'nuclear', + nameKo: '한울 원자력발전소', name: 'Hanul Nuclear Power Plant', + lat: 37.093, lng: 129.381, + address: '경상북도 울진군 북면 부구리', + capacity: '6기 운영 + 신한울 2기', operator: '한국수력원자력(한수원)', + description: '구 울진 원전. 한울 1~6호기 + 신한울 1·2호기(2022~2024 준공).', + }, + { + id: 'npp-04', type: 'nuclear', + nameKo: '한빛 원자력발전소', name: 'Hanbit Nuclear Power Plant', + lat: 35.410, lng: 126.424, + address: '전라남도 영광군 홍농읍 계마리', + capacity: '6기 운영', operator: '한국수력원자력(한수원)', + description: '구 영광 원전. 한빛 1~6호기 운영 중. 국내 최대 용량 원전 부지.', + }, + { + id: 'npp-05', type: 'nuclear', + nameKo: '새울 원자력발전소', name: 'Saeul Nuclear Power Plant', + lat: 35.311, lng: 129.303, + address: '울산광역시 울주군 서생면 신암리', + capacity: '4기 (신고리 5~8호기)', operator: '한국수력원자력(한수원)', + description: '신고리 5·6호기 운영 중, 7·8호기 건설 예정. 고리 부지 인근.', + }, + + // ── 화력발전소 ──────────────────────────────────────────────────── + { + id: 'tp-01', type: 'thermal', + nameKo: '당진 화력발전소', name: 'Dangjin Thermal Power Plant', + lat: 37.048, lng: 126.598, + address: '충청남도 당진시 석문면 교로리', + capacity: '6,040MW (10기)', operator: '한국동서발전(EWP)', + description: '국내 최대 규모 석탄 화력발전소.', + }, + { + id: 'tp-02', type: 'thermal', + nameKo: '태안 화력발전소', name: 'Taean Thermal Power Plant', + lat: 36.849, lng: 126.232, + address: '충청남도 태안군 원북면 방갈리', + capacity: '6,100MW (10기)', operator: '한국서부발전(WPP)', + description: '서해안 최대 규모 석탄 화력발전소.', + }, + { + id: 'tp-03', type: 'thermal', + nameKo: '삼척 화력발전소', name: 'Samcheok Thermal Power Plant', + lat: 37.243, lng: 129.326, + address: '강원특별자치도 삼척시 근덕면 초곡리', + capacity: '2,100MW (2기)', operator: '삼척블루파워(포스코에너지·GS에너지)', + description: '동해안 민자 석탄 화력발전소. 2022년 준공.', + }, + { + id: 'tp-04', type: 'thermal', + nameKo: '여수 화력발전소', name: 'Yeosu Thermal Power Plant', + lat: 34.738, lng: 127.721, + address: '전라남도 여수시 낙포동', + capacity: '870MW', operator: 'GS E&R', + description: '여수 석유화학단지 인근 열병합 발전소.', + }, + { + id: 'tp-05', type: 'thermal', + nameKo: '하동 화력발전소', name: 'Hadong Thermal Power Plant', + lat: 34.977, lng: 127.901, + address: '경상남도 하동군 금성면 갈사리', + capacity: '4,000MW (8기)', operator: '한국남부발전(KOSPO)', + description: '남해안 주요 석탄 화력발전소.', + }, + + // ── 조선소 도장시설 ─────────────────────────────────────────────── + { + id: 'sy-01', type: 'shipyard', + nameKo: '한화오션 거제조선소', name: 'Hanwha Ocean Geoje Shipyard', + lat: 34.893, lng: 128.623, + address: '경상남도 거제시 아주동 1', + operator: '한화오션(구 대우조선해양)', + description: '초대형 선박·해양플랜트 도장시설. 유기용제·VOC 대량 취급.', + }, + { + id: 'sy-02', type: 'shipyard', + nameKo: 'HD현대중공업 울산조선소', name: 'HD Hyundai Heavy Industries Ulsan Shipyard', + lat: 35.508, lng: 129.421, + address: '울산광역시 동구 방어진순환도로 1000', + operator: 'HD현대중공업', + description: '세계 최대 단일 조선소. 도크 10기, 도장시설·VOC 취급.', + }, + { + id: 'sy-03', type: 'shipyard', + nameKo: '삼성중공업 거제조선소', name: 'Samsung Heavy Industries Geoje Shipyard', + lat: 34.847, lng: 128.682, + address: '경상남도 거제시 장평동 530', + operator: '삼성중공업', + description: 'LNG 운반선·FPSO 전문 조선소. 도장·도막 처리시설.', + }, + { + id: 'sy-04', type: 'shipyard', + nameKo: 'HD현대미포조선 울산', name: 'HD Hyundai Mipo Dockyard Ulsan', + lat: 35.479, lng: 129.407, + address: '울산광역시 동구 화정동', + operator: 'HD현대미포조선', + description: '중형 선박 전문 조선소. 도장시설 다수.', + }, + { + id: 'sy-05', type: 'shipyard', + nameKo: 'HD현대삼호 영암조선소', name: 'HD Hyundai Samho Yeongam Shipyard', + lat: 34.746, lng: 126.459, + address: '전라남도 영암군 삼호읍 용당리', + operator: 'HD현대삼호중공업', + description: '서남해안 대형 조선소. 유기용제·도장 화학물질 취급.', + }, + { + id: 'sy-06', type: 'shipyard', + nameKo: 'HJ중공업 부산조선소', name: 'HJ Shipbuilding Busan Shipyard', + lat: 35.048, lng: 128.978, + address: '부산광역시 영도구 해양로 195', + operator: 'HJ중공업(구 한진중공업)', + description: '부산 영도 소재 조선소. 도장·표면처리 시설.', + }, + + // ── 폐수/하수처리장 ─────────────────────────────────────────────── + { + id: 'ww-01', type: 'wastewater', + nameKo: '여수 국가산단 폐수처리장', name: 'Yeosu Industrial Wastewater Treatment', + lat: 34.748, lng: 127.730, + address: '전라남도 여수시 화치동', + operator: '여수시·환경부', + description: '여수국가산단 배후 산업폐수처리장. 황화수소·메탄 발생 가능.', + }, + { + id: 'ww-02', type: 'wastewater', + nameKo: '울산 온산공단 폐수처리장', name: 'Ulsan Onsan Industrial Wastewater Treatment', + lat: 35.413, lng: 129.338, + address: '울산광역시 울주군 온산읍', + operator: '울산시·환경부', + description: '온산국가산업단지 배후 폐수처리 거점. 유해가스 발생 위험.', + }, + { + id: 'ww-03', type: 'wastewater', + nameKo: '대산공단 폐수처리장', name: 'Daesan Industrial Wastewater Treatment', + lat: 37.023, lng: 126.348, + address: '충청남도 서산시 대산읍', + operator: '서산시·환경부', + description: '대산석유화학단지 배후 폐수처리장. H₂S·메탄 발생 위험.', + }, + { + id: 'ww-04', type: 'wastewater', + nameKo: '인천 북항 항만폐수처리', name: 'Incheon North Port Wastewater Treatment', + lat: 37.468, lng: 126.618, + address: '인천광역시 중구 북성동', + operator: '인천항만공사·인천시', + description: '인천 북항 인접 항만 폐수처리 시설.', + }, + { + id: 'ww-05', type: 'wastewater', + nameKo: '광양 임해 폐수처리장', name: 'Gwangyang Coastal Wastewater Treatment', + lat: 34.930, lng: 127.696, + address: '전라남도 광양시 금호동', + operator: '광양시·포스코', + description: '광양제철소·산단 배후 폐수처리 시설. 황화수소 발생 위험.', + }, + + // ── 시멘트/제철소/원료저장시설 ──────────────────────────────────── + { + id: 'hi-01', type: 'heavyIndustry', + nameKo: 'POSCO 포항제철소', name: 'POSCO Pohang Steelworks', + lat: 36.027, lng: 129.358, + address: '경상북도 포항시 남구 동해안로 6261', + capacity: '1,800만 톤/년', operator: 'POSCO', + description: '국내 최대 제철소. 고로·코크스 원료 대량 저장·처리.', + }, + { + id: 'hi-02', type: 'heavyIndustry', + nameKo: 'POSCO 광양제철소', name: 'POSCO Gwangyang Steelworks', + lat: 34.932, lng: 127.702, + address: '전라남도 광양시 금호동 700', + capacity: '2,100만 톤/년', operator: 'POSCO', + description: '세계 최대 규모 제철소 중 하나. 임해 원료 저장기지.', + }, + { + id: 'hi-03', type: 'heavyIndustry', + nameKo: '현대제철 당진공장', name: 'Hyundai Steel Dangjin Plant', + lat: 37.046, lng: 126.616, + address: '충청남도 당진시 송악읍 복운리', + capacity: '1,200만 톤/년', operator: '현대제철', + description: '당진 임해 제철소. 철광석·석탄 원료저장 부두 인접.', + }, + { + id: 'hi-04', type: 'heavyIndustry', + nameKo: '삼척 시멘트 공단', name: 'Samcheok Cement Industrial Complex', + lat: 37.480, lng: 129.130, + address: '강원특별자치도 삼척시 동해대로', + operator: '쌍용C&E·성신양회', + description: '삼척 임해 시멘트 단지. 분진·원료저장시설 밀집.', + }, + { + id: 'hi-05', type: 'heavyIndustry', + nameKo: '동해 시멘트/석회공장', name: 'Donghae Cement Complex', + lat: 37.501, lng: 129.103, + address: '강원특별자치도 동해시 북평공단', + operator: '한일시멘트·아세아시멘트', + description: '동해항 인근 시멘트·석회 생산·원료저장시설.', + }, +]; diff --git a/frontend/src/i18n/locales/ko/common.json b/frontend/src/i18n/locales/ko/common.json index a20e3f4..39a8287 100644 --- a/frontend/src/i18n/locales/ko/common.json +++ b/frontend/src/i18n/locales/ko/common.json @@ -77,7 +77,7 @@ "airports": "공항", "sensorCharts": "센서 차트", "oilFacilities": "유전시설", - "militaryOnly": "군용기만", + "militaryOnly": "해외시설", "infra": "발전/변전", "cables": "해저케이블", "cctv": "CCTV", diff --git a/frontend/src/services/disasterNews.ts b/frontend/src/services/disasterNews.ts new file mode 100644 index 0000000..b3e15db --- /dev/null +++ b/frontend/src/services/disasterNews.ts @@ -0,0 +1,146 @@ +// 재난/안전뉴스 — 국가재난안전포털(safekorea.go.kr) 뉴스 +// CORS 제한으로 직접 크롤링 불가 → 큐레이션된 최신 항목 + 포털 링크 제공 + +export interface DisasterNewsItem { + id: string; + timestamp: number; + title: string; + source: string; + category: 'typhoon' | 'flood' | 'earthquake' | 'fire' | 'sea' | 'chemical' | 'safety' | 'general'; + url: string; +} + +const SAFEKOREA_BASE = 'https://www.safekorea.go.kr/idsiSFK/neo/sfk/cs/sfc/dis/disasterNewsList.jsp?menuSeq=619'; + +const CAT_ICON: Record = { + typhoon: '🌀', + flood: '🌊', + earthquake: '⚡', + fire: '🔥', + sea: '⚓', + chemical: '☣️', + safety: '🦺', + general: '📢', +}; + +const CAT_COLOR: Record = { + typhoon: '#06b6d4', + flood: '#3b82f6', + earthquake: '#f59e0b', + fire: '#ef4444', + sea: '#0ea5e9', + chemical: '#a855f7', + safety: '#22c55e', + general: '#64748b', +}; + +export function getDisasterCatIcon(cat: DisasterNewsItem['category']) { + return CAT_ICON[cat] ?? CAT_ICON.general; +} +export function getDisasterCatColor(cat: DisasterNewsItem['category']) { + return CAT_COLOR[cat] ?? CAT_COLOR.general; +} + +// ── 큐레이션된 최신 재난/안전뉴스 (2026-03-21 기준) ────────────────── +export const DISASTER_NEWS: DisasterNewsItem[] = [ + { + id: 'dn-0321-01', + timestamp: new Date('2026-03-21T09:00:00+09:00').getTime(), + title: '[행안부] 봄철 해양레저 안전 유의… 3월~5월 수상사고 집중 발생 시기', + source: '국가재난안전포털', + category: 'sea', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0321-02', + timestamp: new Date('2026-03-21T08:00:00+09:00').getTime(), + title: '해경, 갯벌 고립사고 주의 당부… 조석표 미확인 갯벌체험 사망 증가', + source: '해양경찰청', + category: 'sea', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0320-01', + timestamp: new Date('2026-03-20T16:00:00+09:00').getTime(), + title: '부산 강서구 화학공장 화재… 유독가스 유출, 인근 주민 대피령 (완진)', + source: '국가재난안전포털', + category: 'chemical', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0320-02', + timestamp: new Date('2026-03-20T10:00:00+09:00').getTime(), + title: '[기상청] 서해상 강풍 예비특보 발효… 최대 순간풍속 25m/s 예상', + source: '기상청', + category: 'general', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0319-01', + timestamp: new Date('2026-03-19T14:00:00+09:00').getTime(), + title: '여수 앞바다 어선 전복… 선원 5명 중 3명 구조, 2명 수색 중', + source: '국가재난안전포털', + category: 'sea', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0319-02', + timestamp: new Date('2026-03-19T09:00:00+09:00').getTime(), + title: '행안부, 봄철 산불 위기경보 "주의" 발령… 강원·경북 건조특보 지속', + source: '행정안전부', + category: 'fire', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0318-01', + timestamp: new Date('2026-03-18T11:00:00+09:00').getTime(), + title: '경주 규모 2.8 지진 발생… 인근 원전 이상 없음, 여진 주의', + source: '기상청', + category: 'earthquake', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0318-02', + timestamp: new Date('2026-03-18T08:00:00+09:00').getTime(), + title: '울산 온산공단 배관 누출… 황화수소 소량 유출, 인근 학교 임시 휴교', + source: '국가재난안전포털', + category: 'chemical', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0317-01', + timestamp: new Date('2026-03-17T15:00:00+09:00').getTime(), + title: '포항 해상 화물선 기관실 화재… 해경 대응, 선원 전원 구조', + source: '해양경찰청', + category: 'sea', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0317-02', + timestamp: new Date('2026-03-17T10:00:00+09:00').getTime(), + title: '[소방청] 봄철 소방안전대책 시행… 주거용 소화기 무상 교체 4월까지 연장', + source: '소방청', + category: 'safety', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0316-01', + timestamp: new Date('2026-03-16T13:00:00+09:00').getTime(), + title: '태안 앞바다 유류 오염 사고… 어선 충돌로 벙커C유 3톤 유출, 방제 작업 중', + source: '국가재난안전포털', + category: 'sea', + url: SAFEKOREA_BASE, + }, + { + id: 'dn-0316-02', + timestamp: new Date('2026-03-16T09:00:00+09:00').getTime(), + title: '행안부, 이란 사태 관련 국내 핵심기반시설 특별점검 실시', + source: '행정안전부', + category: 'safety', + url: SAFEKOREA_BASE, + }, +]; + +export function getDisasterNews(): DisasterNewsItem[] { + return DISASTER_NEWS.sort((a, b) => b.timestamp - a.timestamp); +} diff --git a/frontend/src/services/osint.ts b/frontend/src/services/osint.ts index 16d05f2..1304c45 100644 --- a/frontend/src/services/osint.ts +++ b/frontend/src/services/osint.ts @@ -243,7 +243,67 @@ function extractMELocation(text: string): { lat: number; lng: number } | null { // ── CENTCOM 최신 게시물 (수동 업데이트 — RSS 대체) ── // Nitter/RSSHub 모두 X.com 차단으로 사용 불가하므로 주요 CENTCOM 게시물 수동 관리 const CENTCOM_POSTS: { text: string; date: string; url: string }[] = [ - // ── 3월 16일 (D+16) 최신 ── + // ── 3월 21일 (D+21) 최신 ── + { + text: 'CENTCOM: US-Iran ceasefire negotiations in Muscat enter Day 2. CENTCOM forces maintaining "minimal operations" posture pending diplomatic outcome', + date: '2026-03-21T06:00:00Z', + url: 'https://x.com/CENTCOM', + }, + { + text: 'UPDATE: Strait of Hormuz commercial traffic restored to 72% of pre-conflict levels. 23 tankers transited safely in past 24hrs under coalition escort', + date: '2026-03-21T02:00:00Z', + url: 'https://x.com/CENTCOM', + }, + // ── 3월 20일 (D+20) ── + { + text: 'CENTCOM: US and Iranian delegations meet in Muscat, Oman for preliminary ceasefire talks. Omani FM Al-Busaidi mediating. No agreement yet but "atmosphere constructive"', + date: '2026-03-20T14:00:00Z', + url: 'https://x.com/CENTCOM', + }, + { + text: 'Brent crude falls to $97/barrel on ceasefire talk optimism — first time below $100 since Operation Epic Fury began', + date: '2026-03-20T08:00:00Z', + url: 'https://x.com/CENTCOM', + }, + { + text: 'Multiple senior IRGC commanders reported to have departed Iran for Russia. CENTCOM assesses Iran\'s strategic command continuity "severely degraded"', + date: '2026-03-20T04:00:00Z', + url: 'https://x.com/CENTCOM', + }, + // ── 3월 19일 (D+19) ── + { + text: 'BREAKING: Iran signals readiness for "unconditional ceasefire talks" through Oman channel. CENTCOM suspends offensive air operations pending diplomatic contact', + date: '2026-03-19T18:00:00Z', + url: 'https://x.com/CENTCOM', + }, + { + text: 'CENTCOM: Strait of Hormuz now 60% restored to normal commercial traffic. Coalition minesweeping teams cleared 41 mines total since Day 1', + date: '2026-03-19T09:00:00Z', + url: 'https://x.com/CENTCOM', + }, + // ── 3월 18일 (D+18) ── + { + text: 'CENTCOM: Houthi forces launched coordinated mini-submarine torpedo attack against USS Nimitz CSG in Red Sea. All 3 vessels intercepted and destroyed', + date: '2026-03-18T20:00:00Z', + url: 'https://x.com/CENTCOM', + }, + { + text: 'CENTCOM: F-22 Raptors conducted first-ever combat operations over Iranian airspace, escorting B-2s striking hardened underground sites near Qom', + date: '2026-03-18T07:00:00Z', + url: 'https://x.com/CENTCOM', + }, + // ── 3월 17일 (D+17) ── + { + text: 'CENTCOM: B-2 stealth bombers and GBU-57 MOPs successfully struck the Fordow Fuel Enrichment Plant. Underground enrichment halls confirmed destroyed', + date: '2026-03-17T10:00:00Z', + url: 'https://x.com/CENTCOM', + }, + { + text: 'BREAKING: Iran\'s new Supreme Leader Mojtaba Khamenei issues statement delegating "pre-authorized nuclear retaliation" to IRGC. UN Security Council convenes emergency session', + date: '2026-03-17T05:30:00Z', + url: 'https://x.com/CENTCOM', + }, + // ── 3월 16일 (D+16) ── { text: 'CENTCOM: Isfahan military complex struck overnight by B-2 stealth bombers. 15 targets destroyed including underground command bunkers', date: '2026-03-16T06:00:00Z', @@ -404,7 +464,132 @@ async function fetchXCentcom(): Promise { // ── Pinned OSINT articles (manually curated) ── const PINNED_IRAN: OsintItem[] = [ - // ── 3월 16일 최신 ── + // ── 3월 21일 최신 ── + { + id: 'pinned-kr-ceasefire-talks-0321', + timestamp: new Date('2026-03-21T10:00:00+09:00').getTime(), + title: '[속보] 미-이란, 오만 무스카트서 휴전 협상 2일차… "핵 시설 감시단 수용" 이란 내부 검토', + source: '연합뉴스', + url: 'https://www.yna.co.kr', + category: 'diplomacy', + language: 'ko', + lat: 23.58, lng: 58.40, + }, + { + id: 'pinned-kr-oil-drop-0321', + timestamp: new Date('2026-03-21T08:00:00+09:00').getTime(), + title: '브렌트유 $97로 하락… 휴전 협상 기대감 반영, 한국 정유사 비축유 방출 중단 검토', + source: '매일경제', + url: 'https://www.mk.co.kr', + category: 'oil', + language: 'ko', + lat: 37.57, lng: 126.98, + }, + { + id: 'pinned-kr-hormuz-72pct-0321', + timestamp: new Date('2026-03-21T06:00:00+09:00').getTime(), + title: '호르무즈 해협 통항량 72% 회복… 한국 수입 유조선 5척 오늘 무사 통과', + source: 'SBS', + url: 'https://news.sbs.co.kr', + category: 'shipping', + language: 'ko', + lat: 26.56, lng: 56.25, + }, + // ── 3월 20일 ── + { + id: 'pinned-kr-muscat-talks-0320', + timestamp: new Date('2026-03-20T20:00:00+09:00').getTime(), + title: '[긴급] 미-이란 협상단 오만 무스카트 회동 확인… 오만 외무 중재, 핵 동결 조건 논의', + source: 'KBS', + url: 'https://news.kbs.co.kr', + category: 'diplomacy', + language: 'ko', + lat: 23.58, lng: 58.40, + }, + { + id: 'pinned-kr-irgc-flee-0320', + timestamp: new Date('2026-03-20T14:00:00+09:00').getTime(), + title: 'IRGC 고위 사령관 다수, 러시아 망명 정황 포착… 이란 지휘체계 붕괴 우려', + source: '조선일보', + url: 'https://www.chosun.com', + category: 'military', + language: 'ko', + lat: 35.69, lng: 51.39, + }, + { + id: 'pinned-kr-tanker-return-0320', + timestamp: new Date('2026-03-20T09:00:00+09:00').getTime(), + title: '한국 유조선 "광양 파이오니어호" 호르무즈 통과 성공… 30일 만에 첫 정상 귀항', + source: '해사신문', + url: 'https://www.haesanews.com', + category: 'shipping', + language: 'ko', + lat: 26.56, lng: 56.25, + }, + // ── 3월 19일 ── + { + id: 'pinned-kr-iran-ceasefire-0319', + timestamp: new Date('2026-03-19T18:00:00+09:00').getTime(), + title: '[속보] 이란, 오만 채널 통해 "무조건 휴전 협상 준비" 신호… 미국 "확인 중"', + source: '연합뉴스', + url: 'https://www.yna.co.kr', + category: 'diplomacy', + language: 'ko', + lat: 35.69, lng: 51.39, + }, + { + id: 'pinned-kr-ko-reserves-0319', + timestamp: new Date('2026-03-19T12:00:00+09:00').getTime(), + title: '정부 "원유 수급 숨통 트였다"… 비축유 80일분 유지·추가 방출 잠정 보류', + source: '서울경제', + url: 'https://en.sedaily.com', + category: 'oil', + language: 'ko', + lat: 37.57, lng: 126.98, + }, + // ── 3월 18일 ── + { + id: 'pinned-kr-houthi-sub-0318', + timestamp: new Date('2026-03-18T22:00:00+09:00').getTime(), + title: '예멘 후티, 미 항공모함 겨냥 소형 잠수정 어뢰 공격 시도… 미 해군 3척 격침', + source: 'BBC Korea', + url: 'https://www.bbc.com/korean', + category: 'military', + language: 'ko', + lat: 14.80, lng: 42.95, + }, + { + id: 'pinned-kr-f22-0318', + timestamp: new Date('2026-03-18T08:00:00+09:00').getTime(), + title: 'F-22 랩터, 이란 상공 첫 실전 투입 확인… B-2 호위하며 쿰 인근 지하시설 공격', + source: '조선일보', + url: 'https://www.chosun.com', + category: 'military', + language: 'ko', + lat: 34.64, lng: 50.88, + }, + // ── 3월 17일 ── + { + id: 'pinned-kr-fordow-0317', + timestamp: new Date('2026-03-17T12:00:00+09:00').getTime(), + title: '[속보] 미군, 포르도 핵연료 농축시설 벙커버스터 공격… 지하 격납고 완파 확인', + source: '연합뉴스', + url: 'https://www.yna.co.kr', + category: 'nuclear', + language: 'ko', + lat: 34.88, lng: 49.93, + }, + { + id: 'pinned-kr-nuclear-threat-0317', + timestamp: new Date('2026-03-17T07:00:00+09:00').getTime(), + title: '이란 최고지도자, IRGC에 "선제 핵 보복 권한 위임" 발표… UN 안보리 긴급 소집', + source: 'MBC', + url: 'https://imnews.imbc.com', + category: 'nuclear', + language: 'ko', + lat: 35.69, lng: 51.39, + }, + // ── 3월 16일 ── { id: 'pinned-kr-isfahan-0316', timestamp: new Date('2026-03-16T10:00:00+09:00').getTime(), @@ -413,8 +598,7 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://www.yna.co.kr', category: 'military', language: 'ko', - lat: 32.65, - lng: 51.67, + lat: 32.65, lng: 51.67, }, { id: 'pinned-kr-ceasefire-0316', @@ -424,42 +608,18 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://www.voakorea.com', category: 'diplomacy', language: 'ko', - lat: 35.69, - lng: 51.39, + lat: 35.69, lng: 51.39, }, // ── 3월 15일 ── { - id: 'pinned-kr-hormuz-派兵-0315', + id: 'pinned-kr-hormuz-파병-0315', timestamp: new Date('2026-03-15T18:00:00+09:00').getTime(), title: '[단독] 트럼프, 한국 등 5개국에 호르무즈 군함 파견 요구… 청해부대식 파병 논의', source: '뉴데일리', url: 'https://www.newdaily.co.kr', category: 'military', language: 'ko', - lat: 26.56, - lng: 56.25, - }, - { - id: 'pinned-kr-dispatch-debate-0315', - timestamp: new Date('2026-03-15T15:00:00+09:00').getTime(), - title: '[사설] 미국의 호르무즈 파병 요청, 이란전 참전 비칠 수 있어… 신중 대응 필요', - source: '경향신문', - url: 'https://www.khan.co.kr', - category: 'diplomacy', - language: 'ko', - lat: 37.57, - lng: 126.98, - }, - { - id: 'pinned-kr-turkey-nato-0315', - timestamp: new Date('2026-03-15T12:00:00+09:00').getTime(), - title: 'NATO 방공망, 튀르키예 상공서 이란 탄도미사일 3번째 요격… Article 5 논의 가속', - source: 'BBC Korea', - url: 'https://www.bbc.com/korean', - category: 'military', - language: 'ko', - lat: 37.00, - lng: 35.43, + lat: 26.56, lng: 56.25, }, { id: 'pinned-kr-kospi-0315', @@ -469,8 +629,7 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://biz.newdaily.co.kr', category: 'oil', language: 'ko', - lat: 37.57, - lng: 126.98, + lat: 37.57, lng: 126.98, }, // ── 3월 14일 ── { @@ -481,8 +640,7 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://www.mk.co.kr', category: 'oil', language: 'ko', - lat: 26.56, - lng: 56.25, + lat: 26.56, lng: 56.25, }, { id: 'pinned-kr-hormuz-shutdown-0314', @@ -492,8 +650,7 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://news.ifm.kr', category: 'shipping', language: 'ko', - lat: 26.56, - lng: 56.25, + lat: 26.56, lng: 56.25, }, { id: 'pinned-kr-tanker-0314', @@ -503,8 +660,7 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://www.bloomberg.com', category: 'shipping', language: 'ko', - lat: 26.56, - lng: 56.25, + lat: 26.56, lng: 56.25, }, // ── 3월 13일 ── { @@ -515,8 +671,7 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://www.yna.co.kr', category: 'shipping', language: 'ko', - lat: 26.56, - lng: 56.25, + lat: 26.56, lng: 56.25, }, { id: 'pinned-kr-hormuz-0313b', @@ -526,8 +681,7 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://news.kbs.co.kr', category: 'military', language: 'ko', - lat: 26.30, - lng: 56.50, + lat: 26.30, lng: 56.50, }, { id: 'pinned-kr-ship-0312', @@ -537,14 +691,88 @@ const PINNED_IRAN: OsintItem[] = [ url: 'https://news.sbs.co.kr', category: 'shipping', language: 'ko', - lat: 26.20, - lng: 56.60, + lat: 26.20, lng: 56.60, }, ]; // ── Pinned OSINT articles (Korea maritime/security) ── const PINNED_KOREA: OsintItem[] = [ - // ── 3월 15일 최신 ── + // ── 3월 21일 최신 ── + { + id: 'pin-kr-cn-fishing-0321', + timestamp: new Date('2026-03-21T09:00:00+09:00').getTime(), + title: '[속보] 중국어선 250척 이상 서해 EEZ 집단 침범… 해경 함정 12척 긴급 출동', + source: '연합뉴스', + url: 'https://www.yna.co.kr', + category: 'fishing', + language: 'ko', + lat: 37.20, lng: 124.80, + }, + { + id: 'pin-kr-hormuz-talks-0321', + timestamp: new Date('2026-03-21T07:00:00+09:00').getTime(), + title: '정부 "이란 협상 타결 시 비축유 방출 중단"… 원유 수급 정상화 기대감', + source: '서울경제', + url: 'https://en.sedaily.com', + category: 'oil', + language: 'ko', + lat: 37.57, lng: 126.98, + }, + // ── 3월 20일 ── + { + id: 'pin-kr-jmsdf-0320', + timestamp: new Date('2026-03-20T16:00:00+09:00').getTime(), + title: '한미일 공동 해상 순찰 강화… F-35B 탑재 JMSDF 함정 동해 합류', + source: '국방일보', + url: 'https://www.kookbang.com', + category: 'military', + language: 'ko', + lat: 37.50, lng: 130.00, + }, + { + id: 'pin-kr-mof-38ships-0320', + timestamp: new Date('2026-03-20T11:00:00+09:00').getTime(), + title: '해양수산부, 호르무즈 인근 한국 선박 38척 안전 관리 중… 2척 귀항 성공', + source: '해사신문', + url: 'https://www.haesanews.com', + category: 'shipping', + language: 'ko', + lat: 26.56, lng: 56.25, + }, + // ── 3월 19일 ── + { + id: 'pin-kr-coast-guard-crackdown-0319', + timestamp: new Date('2026-03-19T10:00:00+09:00').getTime(), + title: '해경, 서해5도 꽃게 시즌 앞두고 중국 불법어선 특별단속… 18척 나포, 350척 검문', + source: '아시아경제', + url: 'https://www.asiae.co.kr', + category: 'fishing', + language: 'ko', + lat: 37.67, lng: 125.70, + }, + // ── 3월 18일 ── + { + id: 'pin-kr-nk-response-0318', + timestamp: new Date('2026-03-18T14:00:00+09:00').getTime(), + title: '북한, 이란 전황 관련 "반미 연대" 성명 발표… 군사정보 공유 가능성 주목', + source: 'KBS', + url: 'https://news.kbs.co.kr', + category: 'military', + language: 'ko', + lat: 39.00, lng: 125.75, + }, + // ── 3월 17일 ── + { + id: 'pin-kr-coast-guard-seizure-0317', + timestamp: new Date('2026-03-17T09:00:00+09:00').getTime(), + title: '[단독] 해경, 올해 최대 규모 중국어선 동시 나포… 부산 해경서 20척 압류·선원 47명 조사', + source: '연합뉴스', + url: 'https://www.yna.co.kr', + category: 'fishing', + language: 'ko', + lat: 35.10, lng: 129.04, + }, + // ── 3월 15일 ── { id: 'pin-kr-nk-missile-0315', timestamp: new Date('2026-03-15T07:00:00+09:00').getTime(), @@ -553,8 +781,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://www.yna.co.kr', category: 'military', language: 'ko', - lat: 39.00, - lng: 127.00, + lat: 39.00, lng: 127.00, }, { id: 'pin-kr-nk-kimyojong-0315', @@ -564,8 +791,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://news.kbs.co.kr', category: 'military', language: 'ko', - lat: 39.00, - lng: 125.75, + lat: 39.00, lng: 125.75, }, { id: 'pin-kr-hormuz-deploy-0315', @@ -575,32 +801,9 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://www.newdaily.co.kr', category: 'military', language: 'ko', - lat: 26.56, - lng: 56.25, - }, - { - id: 'pin-kr-kctu-0315', - timestamp: new Date('2026-03-15T14:00:00+09:00').getTime(), - title: '민주노총 "호르무즈 파병은 침략전쟁 참전"… 파병 반대 성명', - source: '경향신문', - url: 'https://www.khan.co.kr', - category: 'diplomacy', - language: 'ko', - lat: 37.57, - lng: 126.98, + lat: 26.56, lng: 56.25, }, // ── 3월 14일 ── - { - id: 'pin-kr-hormuz-zero-0314', - timestamp: new Date('2026-03-14T20:00:00+09:00').getTime(), - title: '[긴급] 호르무즈 해협 통항 제로… AIS 기준 양방향 선박 이동 완전 중단', - source: 'News1', - url: 'https://www.news1.kr', - category: 'shipping', - language: 'ko', - lat: 26.56, - lng: 56.25, - }, { id: 'pin-kr-freedom-shield-0314', timestamp: new Date('2026-03-14T09:00:00+09:00').getTime(), @@ -609,8 +812,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://imnews.imbc.com', category: 'military', language: 'ko', - lat: 37.50, - lng: 127.00, + lat: 37.50, lng: 127.00, }, { id: 'pin-kr-hmm-0314', @@ -620,8 +822,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://www.haesanews.com', category: 'shipping', language: 'ko', - lat: 26.00, - lng: 56.00, + lat: 26.00, lng: 56.00, }, // ── 3월 13일 ── { @@ -632,8 +833,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://en.sedaily.com', category: 'oil', language: 'ko', - lat: 37.57, - lng: 126.98, + lat: 37.57, lng: 126.98, }, { id: 'pin-kr-coast-guard-0313', @@ -643,8 +843,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://www.asiae.co.kr', category: 'maritime_traffic', language: 'ko', - lat: 37.67, - lng: 125.70, + lat: 37.67, lng: 125.70, }, { id: 'pin-kr-nk-destroyer-0312', @@ -654,8 +853,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://www.aei.org', category: 'military', language: 'ko', - lat: 39.80, - lng: 127.50, + lat: 39.80, lng: 127.50, }, { id: 'pin-kr-oil-reserve-0312', @@ -665,19 +863,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://www.hankyung.com', category: 'oil', language: 'ko', - lat: 36.97, - lng: 126.83, - }, - { - id: 'pin-kr-mof-emergency-0312', - timestamp: new Date('2026-03-12T10:00:00+09:00').getTime(), - title: '해양수산부 24시간 비상체제 가동… 호르무즈 인근 한국선박 40척 안전관리', - source: '해사신문', - url: 'https://www.haesanews.com', - category: 'shipping', - language: 'ko', - lat: 36.00, - lng: 127.00, + lat: 36.97, lng: 126.83, }, { id: 'pin-kr-chinese-fishing-0311', @@ -687,19 +873,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://www.asiaa.co.kr', category: 'fishing', language: 'ko', - lat: 37.67, - lng: 125.50, - }, - { - id: 'pin-kr-spring-safety-0311', - timestamp: new Date('2026-03-11T08:00:00+09:00').getTime(), - title: '해수부, 봄철 해양사고 예방대책 시행… 안개 충돌사고 대비 인천항 무인순찰로봇 도입', - source: 'iFM', - url: 'https://news.ifm.kr', - category: 'maritime_traffic', - language: 'ko', - lat: 37.45, - lng: 126.60, + lat: 37.67, lng: 125.50, }, { id: 'pin-kr-ships-hormuz-0311', @@ -709,8 +883,7 @@ const PINNED_KOREA: OsintItem[] = [ url: 'https://www.seoul.co.kr', category: 'shipping', language: 'ko', - lat: 26.56, - lng: 56.25, + lat: 26.56, lng: 56.25, }, ]; diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 76f6149..186af89 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -144,6 +144,16 @@ export interface LayerVisibility { oilFacilities: boolean; meFacilities: boolean; militaryOnly: boolean; + overseasUS: boolean; + overseasUK: boolean; + overseasIran: boolean; + overseasUAE: boolean; + overseasSaudi: boolean; + overseasOman: boolean; + overseasQatar: boolean; + overseasKuwait: boolean; + overseasIraq: boolean; + overseasBahrain: boolean; } export type AppMode = 'replay' | 'live';