diff --git a/backend/package-lock.json b/backend/package-lock.json
index e5e0aed..a3d5138 100755
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -558,7 +558,6 @@
"integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^5.0.0",
@@ -1992,7 +1991,6 @@
"resolved": "https://registry.npmjs.org/pg/-/pg-8.19.0.tgz",
"integrity": "sha512-QIcLGi508BAHkQ3pJNptsFz5WQMlpGbuBGBaIaXsWK8mel2kQ/rThYI+DbgjUvZrIr7MiuEuc9LcChJoEZK1xQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"pg-connection-string": "^2.11.0",
"pg-pool": "^3.12.0",
diff --git a/frontend/src/tabs/weather/components/WeatherMapControls.tsx b/frontend/src/tabs/weather/components/WeatherMapControls.tsx
new file mode 100644
index 0000000..56173c6
--- /dev/null
+++ b/frontend/src/tabs/weather/components/WeatherMapControls.tsx
@@ -0,0 +1,48 @@
+import { useMap } from '@vis.gl/react-maplibre'
+
+interface WeatherMapControlsProps {
+ center: [number, number]
+ zoom: number
+}
+
+export function WeatherMapControls({ center, zoom }: WeatherMapControlsProps) {
+ const { current: map } = useMap()
+
+ const buttons = [
+ {
+ label: '+',
+ tooltip: '확대',
+ onClick: () => map?.zoomIn(),
+ },
+ {
+ label: '−',
+ tooltip: '축소',
+ onClick: () => map?.zoomOut(),
+ },
+ {
+ label: '🎯',
+ tooltip: '한국 해역 초기화',
+ onClick: () => map?.flyTo({ center, zoom, duration: 1000 }),
+ },
+ ]
+
+ return (
+
+
+ {buttons.map(({ label, tooltip, onClick }) => (
+
+
+
+ {tooltip}
+
+
+ ))}
+
+
+ )
+}
diff --git a/frontend/src/tabs/weather/components/WeatherView.tsx b/frontend/src/tabs/weather/components/WeatherView.tsx
index c626b27..d3b9bb1 100755
--- a/frontend/src/tabs/weather/components/WeatherView.tsx
+++ b/frontend/src/tabs/weather/components/WeatherView.tsx
@@ -1,5 +1,5 @@
import { useState, useMemo, useCallback } from 'react'
-import { Map, useControl, useMap } from '@vis.gl/react-maplibre'
+import { Map, Marker, useControl } from '@vis.gl/react-maplibre'
import { MapboxOverlay } from '@deck.gl/mapbox'
import type { Layer } from '@deck.gl/core'
import type { StyleSpecification, MapLayerMouseEvent } from 'maplibre-gl'
@@ -12,6 +12,7 @@ import { useWaterTemperatureLayers } from './WaterTemperatureLayer'
import { WindParticleLayer } from './WindParticleLayer'
import { useWeatherData } from '../hooks/useWeatherData'
import { useOceanForecast } from '../hooks/useOceanForecast'
+import { WeatherMapControls } from './WeatherMapControls'
type TimeOffset = '0' | '3' | '6' | '9'
@@ -117,38 +118,6 @@ function DeckGLOverlay({ layers }: { layers: Layer[] }) {
return null
}
-// 줌 컨트롤
-function WeatherMapControls() {
- const { current: map } = useMap()
-
- return (
-
-
-
-
-
-
-
- )
-}
-
/**
* WeatherMapInner — Map 컴포넌트 내부 (useMap / useControl 사용 가능 영역)
*/
@@ -159,6 +128,9 @@ interface WeatherMapInnerProps {
oceanForecastOpacity: number
selectedForecast: ReturnType['selectedForecast']
onStationClick: (station: WeatherStation) => void
+ mapCenter: [number, number]
+ mapZoom: number
+ clickedLocation: { lat: number; lon: number } | null
}
function WeatherMapInner({
@@ -168,6 +140,9 @@ function WeatherMapInner({
oceanForecastOpacity,
selectedForecast,
onStationClick,
+ mapCenter,
+ mapZoom,
+ clickedLocation,
}: WeatherMapInnerProps) {
// deck.gl layers 조합
const weatherDeckLayers = useWeatherDeckLayers(
@@ -216,8 +191,31 @@ function WeatherMapInner({
stations={weatherStations}
/>
+ {/* 클릭 위치 마커 */}
+ {clickedLocation && (
+
+
+ {/* 펄스 링 */}
+
+ {/* 핀 꼬리 */}
+
+ {/* 좌표 라벨 */}
+
+ {clickedLocation.lat.toFixed(3)}°N {clickedLocation.lon.toFixed(3)}°E
+
+
+
+ )}
+
{/* 줌 컨트롤 */}
-
+
>
)
}
@@ -225,6 +223,8 @@ function WeatherMapInner({
export function WeatherView() {
const { weatherStations, loading, error, lastUpdate } = useWeatherData(BASE_STATIONS)
+ console.log(weatherStations,'날씨');
+
const {
selectedForecast,
availableTimes,
@@ -343,12 +343,6 @@ export function WeatherView() {
-
-
-
-
{/* Map */}
@@ -371,6 +365,9 @@ export function WeatherView() {
oceanForecastOpacity={oceanForecastOpacity}
selectedForecast={selectedForecast}
onStationClick={handleStationClick}
+ mapCenter={WEATHER_MAP_CENTER}
+ mapZoom={WEATHER_MAP_ZOOM}
+ clickedLocation={selectedLocation}
/>
diff --git a/frontend/src/tabs/weather/hooks/useWeatherData.ts b/frontend/src/tabs/weather/hooks/useWeatherData.ts
index 37eb2df..909face 100755
--- a/frontend/src/tabs/weather/hooks/useWeatherData.ts
+++ b/frontend/src/tabs/weather/hooks/useWeatherData.ts
@@ -87,6 +87,7 @@ export function useWeatherData(stations: WeatherStation[]) {
}
const obs = await getRecentObservation(obsCode)
+
if (obs) {
const r = (n: number) => Math.round(n * 10) / 10
diff --git a/frontend/src/tabs/weather/services/khoaApi.ts b/frontend/src/tabs/weather/services/khoaApi.ts
index 5a01d36..cd20ee7 100755
--- a/frontend/src/tabs/weather/services/khoaApi.ts
+++ b/frontend/src/tabs/weather/services/khoaApi.ts
@@ -157,6 +157,8 @@ export async function getRecentObservation(obsCode: string): Promise