diff --git a/frontend/src/components/google-maps/map/CarFfeineMap.tsx b/frontend/src/components/google-maps/map/CarFfeineMap.tsx
index e2cf86f85..330f4266d 100644
--- a/frontend/src/components/google-maps/map/CarFfeineMap.tsx
+++ b/frontend/src/components/google-maps/map/CarFfeineMap.tsx
@@ -5,7 +5,7 @@ import DataDownloader from '@ui/DataDownloader';
import CarFfeineMapListener from './CarFfeineListener';
const UserFilterListener = lazy(() => import('./UserFilterListener'));
-const MarkersContainers = lazy(() => import('@marker/MarkerContainers'));
+const MarkersContainers = lazy(() => import('@marker/components/MarkerContainers'));
const ToastContainer = lazy(() => import('@ui/ToastContainer'));
const ClientStationFilters = lazy(() => import('@ui/ClientStationFilters'));
const MapController = lazy(() => import('@ui/MapController'));
diff --git a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/LargeDeltaAreaMarkerContainer.tsx b/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/LargeDeltaAreaMarkerContainer.tsx
deleted file mode 100644
index e847de937..000000000
--- a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/LargeDeltaAreaMarkerContainer.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { useEffect } from 'react';
-
-import { markerInstanceStore } from '@stores/google-maps/markerInstanceStore';
-
-import { useClusterMarkers } from './hooks/useClusterMarkers';
-import { useRenderClusterMarkers } from './hooks/useRenderClusterMarker';
-
-const LargeDeltaAreaMarkerContainer = () => {
- const { data: clusterMarkers, isSuccess } = useClusterMarkers();
-
- const {
- createNewMarkerInstances,
- getRemainedMarkerInstances,
- removeMarkersOutsideBounds,
- removeAllMarkers,
- renderClusterMarkers,
- } = useRenderClusterMarkers();
-
- useEffect(() => {
- return () => {
- // MarkerContainers 컴포넌트에서 SmallMediumDeltaAreaMarkerContainer 컴포넌트가 unmount될 때 모든 마커를 지워준다.
- removeAllMarkers(markerInstanceStore.getState());
- };
- }, []);
-
- if (clusterMarkers === undefined || !isSuccess) {
- return <>>;
- }
-
- const newMarkerInstances = createNewMarkerInstances(
- markerInstanceStore.getState(),
- clusterMarkers
- );
-
- const remainedMarkerInstances = getRemainedMarkerInstances(
- markerInstanceStore.getState(),
- clusterMarkers
- );
-
- removeMarkersOutsideBounds(markerInstanceStore.getState(), clusterMarkers);
- renderClusterMarkers(newMarkerInstances, clusterMarkers);
-
- markerInstanceStore.setState([...remainedMarkerInstances, ...newMarkerInstances]);
-
- return <>>;
-};
-
-export default LargeDeltaAreaMarkerContainer;
diff --git a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/hooks/useRenderClusterMarker.tsx b/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/hooks/useRenderClusterMarker.tsx
deleted file mode 100644
index 966d47cce..000000000
--- a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/hooks/useRenderClusterMarker.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import { createRoot } from 'react-dom/client';
-
-import StyledClusterMarker from '@marker/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker';
-
-import { getStoreSnapshot } from '@utils/external-state/tools';
-
-import { getGoogleMapStore, googleMapActions } from '@stores/google-maps/googleMapStore';
-import type { MarkerInstance } from '@stores/google-maps/markerInstanceStore';
-
-import type { ClusterMarker } from '@type';
-
-export const useRenderClusterMarkers = () => {
- const googleMap = getStoreSnapshot(getGoogleMapStore());
-
- const createNewMarkerInstances = (
- prevMarkerInstances: MarkerInstance[],
- markers: ClusterMarker[]
- ) => {
- const newMarkers = markers.filter((marker) =>
- prevMarkerInstances.every((prevMarker) => prevMarker.id !== marker.id)
- );
-
- const newMarkerInstances = newMarkers.map((marker) => {
- const { latitude: lat, longitude: lng, id, count } = marker;
-
- const markerInstance = new google.maps.marker.AdvancedMarkerElement({
- position: { lat, lng },
- title: `영역 내 충전소 개수: ${count}`,
- });
-
- return {
- id,
- instance: markerInstance,
- };
- });
-
- bindMarkerClickHandler(newMarkerInstances, newMarkers);
-
- return newMarkerInstances;
- };
-
- const removeMarkersOutsideBounds = (
- prevMarkerInstances: MarkerInstance[],
- currentMarkers: ClusterMarker[]
- ) => {
- const markersOutOfBounds = prevMarkerInstances.filter((prevMarker) =>
- currentMarkers.every((currentMarker) => currentMarker.id !== prevMarker.id)
- );
-
- markersOutOfBounds.forEach((marker) => {
- marker.instance.map = null;
- });
- };
-
- const removeAllMarkers = (prevMarkerInstances: MarkerInstance[]) => {
- prevMarkerInstances.forEach((marker) => {
- marker.instance.map = null;
- });
- };
-
- const getRemainedMarkerInstances = (
- prevMarkerInstances: MarkerInstance[],
- currentMarkers: ClusterMarker[]
- ) => {
- return prevMarkerInstances.filter((markerInstance) =>
- currentMarkers.some((marker) => marker.id === markerInstance.id)
- );
- };
-
- const renderClusterMarkers = (markerInstances: MarkerInstance[], markers: ClusterMarker[]) => {
- markerInstances.forEach(({ instance: markerInstance, id }) => {
- const container = document.createElement('div');
-
- container.style.opacity = '0';
- container.classList.add('marker-animation');
- container.addEventListener('animationend', () => {
- container.classList.remove('marker-animation');
- container.style.opacity = '1';
- });
-
- markerInstance.content = container;
- markerInstance.map = googleMap;
-
- const markerInformation = markers.find((clusterMarker) => clusterMarker.id === id);
-
- createRoot(container).render();
- });
- };
-
- const bindMarkerClickHandler = (
- markerInstances: MarkerInstance[],
- newMarkers: ClusterMarker[]
- ) => {
- markerInstances.forEach(({ instance: markerInstance, id: stationId }) => {
- markerInstance.addListener('click', () => {
- const targetMarker = newMarkers.find((marker) => marker.id === stationId);
- const currentZoom = googleMap.getZoom();
-
- googleMapActions.moveTo(
- { lat: targetMarker.latitude, lng: targetMarker.longitude },
- currentZoom + 1
- );
- });
- });
- };
-
- return {
- createNewMarkerInstances,
- removeMarkersOutsideBounds,
- getRemainedMarkerInstances,
- renderClusterMarkers,
- removeAllMarkers,
- };
-};
diff --git a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/components/RegionMarkerRenderer.tsx b/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/components/RegionMarkerRenderer.tsx
deleted file mode 100644
index b3233bfda..000000000
--- a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/components/RegionMarkerRenderer.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { useEffect } from 'react';
-
-import { useRenderRegionMarker } from '../hooks/useRenderRegionMarker';
-import type { Region } from '../types';
-
-export interface RegionMarkerProps {
- region: Region;
-}
-
-const RegionMarkerRenderer = ({ region }: RegionMarkerProps) => {
- const { renderRegionMarker } = useRenderRegionMarker();
-
- useEffect(() => {
- const unmountRegionMarker = renderRegionMarker(region);
-
- return unmountRegionMarker;
- }, []);
-
- return <>>;
-};
-
-export default RegionMarkerRenderer;
diff --git a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/hooks/useRenderRegionMarker.tsx b/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/hooks/useRenderRegionMarker.tsx
deleted file mode 100644
index 7e2448542..000000000
--- a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/hooks/useRenderRegionMarker.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { createRoot } from 'react-dom/client';
-
-import { useExternalValue } from '@utils/external-state';
-
-import { getGoogleMapStore, googleMapActions } from '@stores/google-maps/googleMapStore';
-
-import RegionMarker from '../components/RegionMarker';
-import type { Region } from '../types';
-
-export const useRenderRegionMarker = () => {
- const googleMap = useExternalValue(getGoogleMapStore());
-
- const renderRegionMarker = (region: Region) => {
- const { latitude, longitude, count, regionName } = region;
-
- const container = document.createElement('div');
-
- container.style.opacity = '0';
- container.classList.add('marker-animation');
- container.addEventListener('animationend', () => {
- container.classList.remove('marker-animation');
- container.style.opacity = '1';
- });
-
- const markerInstance = new google.maps.marker.AdvancedMarkerElement({
- position: { lat: latitude, lng: longitude },
- map: googleMap,
- title: regionName,
- content: container,
- });
-
- createRoot(container).render();
-
- markerInstance.addListener('click', () => {
- googleMapActions.moveTo({ lat: latitude, lng: longitude }, 12);
- });
-
- return () => {
- markerInstance.map = null;
- };
- };
-
- return { renderRegionMarker };
-};
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/SmallMediumDeltaAreaMarkerContainer.tsx b/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/SmallMediumDeltaAreaMarkerContainer.tsx
deleted file mode 100644
index 05915ecc8..000000000
--- a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/SmallMediumDeltaAreaMarkerContainer.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { useEffect } from 'react';
-
-import { useStationMarkers } from '@marker/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkers';
-
-import { useExternalValue } from '@utils/external-state';
-
-import { deltaAreaStore } from '@stores/google-maps/deltaAreaStore';
-import type { DeltaAreaState } from '@stores/google-maps/deltaAreaStore/types';
-import type { MarkerInstance } from '@stores/google-maps/markerInstanceStore';
-import { markerInstanceStore } from '@stores/google-maps/markerInstanceStore';
-
-import { useRenderStationMarker } from './hooks/useRenderStationMarker';
-
-const SmallMediumDeltaAreaMarkerContainer = () => {
- const { data: stationMarkers, isSuccess } = useStationMarkers();
- const {
- createNewMarkerInstances,
- getRemainedMarkerInstances,
- removeMarkersOutsideBounds,
- removeAllMarkers,
- renderDefaultMarkers,
- renderCarffeineMarkers,
- } = useRenderStationMarker();
- const deltaAreaState = useExternalValue(deltaAreaStore);
-
- const renderMarkerByDeltaAreaState = (
- deltaAreaState: DeltaAreaState,
- markerInstances: MarkerInstance[]
- ) => {
- if (deltaAreaState === 'small') {
- renderCarffeineMarkers(markerInstances, stationMarkers);
- }
- if (deltaAreaState === 'medium') {
- renderDefaultMarkers(markerInstances, stationMarkers);
- }
- };
-
- useEffect(() => {
- if (stationMarkers !== undefined) {
- renderMarkerByDeltaAreaState(deltaAreaState, markerInstanceStore.getState());
- }
- }, [deltaAreaState]);
-
- useEffect(() => {
- return () => {
- // MarkerContainers 컴포넌트에서 HighZoomMarkerContainer 컴포넌트가 unmount될 때 모든 마커를 지워준다.
- removeAllMarkers(markerInstanceStore.getState());
- };
- }, []);
-
- if (stationMarkers === undefined || !isSuccess) {
- return <>>;
- }
-
- const newMarkerInstances = createNewMarkerInstances(
- markerInstanceStore.getState(),
- stationMarkers
- );
-
- const remainedMarkerInstances = getRemainedMarkerInstances(
- markerInstanceStore.getState(),
- stationMarkers
- );
-
- removeMarkersOutsideBounds(markerInstanceStore.getState(), stationMarkers);
- renderMarkerByDeltaAreaState(deltaAreaState, newMarkerInstances);
-
- markerInstanceStore.setState([...remainedMarkerInstances, ...newMarkerInstances]);
-
- return <>>;
-};
-
-export default SmallMediumDeltaAreaMarkerContainer;
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/hooks/useRenderStationMarker.tsx b/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/hooks/useRenderStationMarker.tsx
deleted file mode 100644
index 039cb0d93..000000000
--- a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/hooks/useRenderStationMarker.tsx
+++ /dev/null
@@ -1,171 +0,0 @@
-import { createRoot } from 'react-dom/client';
-
-import { getStoreSnapshot } from '@utils/external-state/tools';
-
-import { getGoogleMapStore } from '@stores/google-maps/googleMapStore';
-import type { MarkerInstance } from '@stores/google-maps/markerInstanceStore';
-
-import { useStationInfoWindow } from '@hooks/google-maps/useStationInfoWindow';
-import useMediaQueries from '@hooks/useMediaQueries';
-
-import { useNavigationBar } from '@ui/Navigator/NavigationBar/hooks/useNavigationBar';
-import StationDetailsWindow from '@ui/StationDetailsWindow';
-
-import type { StationDetails, StationMarker, StationSummary } from '@type';
-
-import CarFfeineMarker from '../components/CarFfeineMarker';
-import { MARKER_COLORS } from '../components/CarFfeineMarker/CarFfeineMarker.style';
-import { DEFAULT_MARKER_SIZE_RATIO } from '../constants';
-
-export const useRenderStationMarker = () => {
- const googleMap = getStoreSnapshot(getGoogleMapStore());
-
- const { openStationInfoWindow } = useStationInfoWindow();
- const { openLastPanel } = useNavigationBar();
- const screen = useMediaQueries();
-
- const createNewMarkerInstance = (marker: StationDetails) => {
- const { latitude: lat, longitude: lng, stationName, stationId } = marker;
-
- const markerInstance = new google.maps.marker.AdvancedMarkerElement({
- position: { lat, lng },
- title: stationName,
- });
-
- bindMarkerClickHandler([{ id: stationId, instance: markerInstance }]);
-
- return markerInstance;
- };
-
- const createNewMarkerInstances = (
- prevMarkerInstances: MarkerInstance[],
- markers: StationMarker[]
- ) => {
- const newMarkers = markers.filter((marker) =>
- prevMarkerInstances.every((prevMarker) => prevMarker.id !== marker.stationId)
- );
-
- const newMarkerInstances = newMarkers.map((marker) => {
- const { latitude: lat, longitude: lng, stationName, stationId: id } = marker;
-
- const markerInstance = new google.maps.marker.AdvancedMarkerElement({
- position: { lat, lng },
- title: stationName,
- });
-
- return {
- id,
- instance: markerInstance,
- };
- });
-
- bindMarkerClickHandler(newMarkerInstances);
-
- return newMarkerInstances;
- };
-
- const removeMarkersOutsideBounds = (
- prevMarkerInstances: MarkerInstance[],
- currentMarkers: StationMarker[]
- ) => {
- const markersOutOfBounds = prevMarkerInstances.filter((prevMarker) =>
- currentMarkers.every((currentMarker) => currentMarker.stationId !== prevMarker.id)
- );
-
- markersOutOfBounds.forEach((marker) => {
- marker.instance.map = null;
- });
- };
-
- const removeAllMarkers = (prevMarkerInstances: MarkerInstance[]) => {
- prevMarkerInstances.forEach((marker) => {
- marker.instance.map = null;
- });
- };
-
- const getRemainedMarkerInstances = (
- prevMarkerInstances: MarkerInstance[],
- currentMarkers: StationMarker[]
- ) => {
- return prevMarkerInstances.filter((markerInstance) =>
- currentMarkers.some((marker) => marker.stationId === markerInstance.id)
- );
- };
-
- const renderDefaultMarkers = (
- markerInstances: MarkerInstance[],
- markers: StationMarker[] | StationSummary[]
- ) => {
- markers.forEach((marker) => {
- const markerInstance = markerInstances.find(
- (markerInstance) => markerInstance.id === marker.stationId
- )?.instance;
-
- const markerColor =
- marker.availableCount > 0 ? MARKER_COLORS.available : MARKER_COLORS.noAvailable;
-
- if (markerInstance) {
- const defaultMarkerDesign = new google.maps.marker.PinElement({
- scale: DEFAULT_MARKER_SIZE_RATIO,
- background: markerColor.background,
- borderColor: markerColor.border,
- glyph: '',
- });
-
- markerInstance.map = googleMap;
- defaultMarkerDesign.element.style.opacity = '0';
- defaultMarkerDesign.element.classList.add('marker-animation');
- defaultMarkerDesign.element.addEventListener('animationend', () => {
- defaultMarkerDesign.element.classList.remove('marker-animation');
- defaultMarkerDesign.element.style.opacity = '1';
- });
- markerInstance.content = defaultMarkerDesign.element;
- }
- });
- };
-
- const renderCarffeineMarkers = (
- markerInstances: MarkerInstance[],
- markers: StationMarker[] | StationSummary[]
- ) => {
- markerInstances.forEach(({ instance: markerInstance, id: stationId }) => {
- const container = document.createElement('div');
- container.style.opacity = '0';
- container.classList.add('marker-animation');
- container.addEventListener('animationend', () => {
- container.classList.remove('marker-animation');
- container.style.opacity = '1';
- });
- markerInstance.content = container;
- markerInstance.map = googleMap;
-
- const markerInformation = markers.find(
- (stationMarker) => stationMarker.stationId === stationId
- );
-
- createRoot(container).render();
- });
- };
-
- const bindMarkerClickHandler = (markerInstances: MarkerInstance[]) => {
- markerInstances.forEach(({ instance: markerInstance, id: stationId }) => {
- markerInstance.addListener('click', () => {
- openStationInfoWindow(stationId, markerInstance);
-
- if (!screen.get('isMobile')) {
- openLastPanel();
- }
- });
- });
- };
-
- return {
- createNewMarkerInstance,
- createNewMarkerInstances,
- removeMarkersOutsideBounds,
- getRemainedMarkerInstances,
- renderDefaultMarkers,
- renderCarffeineMarkers,
- removeAllMarkers,
- };
-};
diff --git a/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/LargeDeltaAreaMarkerContainer.tsx b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/LargeDeltaAreaMarkerContainer.tsx
new file mode 100644
index 000000000..640b5c693
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/LargeDeltaAreaMarkerContainer.tsx
@@ -0,0 +1,20 @@
+import ClusterMarkerRenderer from './components/ClusterMarkerRenderer';
+import { useClusterMarkersQuery } from './hooks/useClusterMarkersQuery';
+
+const LargeDeltaAreaMarkerContainer = () => {
+ const { data: clusterMarkers, isSuccess } = useClusterMarkersQuery();
+
+ if (clusterMarkers === undefined || !isSuccess) {
+ return <>>;
+ }
+
+ return (
+ <>
+ {clusterMarkers.map((cluster) => (
+
+ ))}
+ >
+ );
+};
+
+export default LargeDeltaAreaMarkerContainer;
diff --git a/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/components/ClusterMarkerRenderer.tsx b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/components/ClusterMarkerRenderer.tsx
new file mode 100644
index 000000000..bb88db6fa
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/components/ClusterMarkerRenderer.tsx
@@ -0,0 +1,23 @@
+import { useLayoutEffect } from 'react';
+
+import { useMarker } from '@marker/hooks/useMarker';
+
+import type { ClusterMarker } from '@type';
+
+interface Props {
+ cluster: ClusterMarker;
+}
+
+const ClusterMarkerRenderer = ({ cluster }: Props) => {
+ const { renderClusterMarker } = useMarker();
+
+ useLayoutEffect(() => {
+ const unmount = renderClusterMarker(cluster);
+
+ return unmount;
+ }, []);
+
+ return <>>;
+};
+
+export default ClusterMarkerRenderer;
diff --git a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker.stories.tsx b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker.stories.tsx
similarity index 100%
rename from frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker.stories.tsx
rename to frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker.stories.tsx
diff --git a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker.tsx b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker.tsx
similarity index 100%
rename from frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker.tsx
rename to frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker.tsx
diff --git a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/hooks/useClusterMarkers.ts b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/hooks/useClusterMarkersQuery.ts
similarity index 98%
rename from frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/hooks/useClusterMarkers.ts
rename to frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/hooks/useClusterMarkersQuery.ts
index 5805ee557..167c43342 100644
--- a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/hooks/useClusterMarkers.ts
+++ b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/hooks/useClusterMarkersQuery.ts
@@ -64,7 +64,7 @@ export const fetchClusterMarkers = async () => {
return clusterMarkers;
};
-export const useClusterMarkers = () => {
+export const useClusterMarkersQuery = () => {
return useQuery({
queryKey: [QUERY_KEY_CLUSTER_MARKERS],
queryFn: fetchClusterMarkers,
diff --git a/frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/index.ts b/frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/index.ts
similarity index 100%
rename from frontend/src/components/google-maps/marker/LargeDeltaAreaMarkerContainer/index.ts
rename to frontend/src/components/google-maps/marker/components/LargeDeltaAreaMarkerContainer/index.ts
diff --git a/frontend/src/components/google-maps/marker/MarkerContainers.tsx b/frontend/src/components/google-maps/marker/components/MarkerContainers/MarkerContainers.tsx
similarity index 62%
rename from frontend/src/components/google-maps/marker/MarkerContainers.tsx
rename to frontend/src/components/google-maps/marker/components/MarkerContainers/MarkerContainers.tsx
index 90e1389d8..15321f940 100644
--- a/frontend/src/components/google-maps/marker/MarkerContainers.tsx
+++ b/frontend/src/components/google-maps/marker/components/MarkerContainers/MarkerContainers.tsx
@@ -2,9 +2,9 @@ import { useExternalValue } from '@utils/external-state';
import { deltaAreaStore } from '@stores/google-maps/deltaAreaStore';
-import LargeDeltaAreaMarkerContainer from './LargeDeltaAreaMarkerContainer';
-import MaxDeltaAreaMarkerContainer from './MaxDeltaAreaMarkerContainer';
-import SmallMediumDeltaAreaMarkerContainer from './SmallMediumDeltaAreaMarkerContainer';
+import LargeDeltaAreaMarkerContainer from '../LargeDeltaAreaMarkerContainer';
+import MaxDeltaAreaMarkerContainer from '../MaxDeltaAreaMarkerContainer';
+import SmallMediumDeltaAreaMarkerContainer from '../SmallMediumDeltaAreaMarkerContainer/SmallMediumDeltaAreaContainer';
const MarkerContainers = () => {
const deltaAreaState = useExternalValue(deltaAreaStore);
@@ -14,7 +14,6 @@ const MarkerContainers = () => {
{(deltaAreaState === 'medium' || deltaAreaState === 'small') && (
)}
- {/* 이 아래는 앞으로 추가될 기능을 미리 대응하는 컴포넌트 */}
{deltaAreaState === 'large' && }
{deltaAreaState === 'max' && }
>
diff --git a/frontend/src/components/google-maps/marker/components/MarkerContainers/index.ts b/frontend/src/components/google-maps/marker/components/MarkerContainers/index.ts
new file mode 100644
index 000000000..441fb451f
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/components/MarkerContainers/index.ts
@@ -0,0 +1,3 @@
+import MarkerContainers from './MarkerContainers';
+
+export default MarkerContainers;
diff --git a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/MaxDeltaAreaMarkerContainer.tsx b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/MaxDeltaAreaMarkerContainer.tsx
similarity index 83%
rename from frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/MaxDeltaAreaMarkerContainer.tsx
rename to frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/MaxDeltaAreaMarkerContainer.tsx
index 4bc5adc1a..f8c668f9d 100644
--- a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/MaxDeltaAreaMarkerContainer.tsx
+++ b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/MaxDeltaAreaMarkerContainer.tsx
@@ -1,8 +1,8 @@
import RegionMarkerRenderer from './components/RegionMarkerRenderer';
-import { useRegionMarkers } from './hooks/useRegionMarkers';
+import { useRegionMarkersQuery } from './hooks/useRegionMarkersQuery';
const MaxDeltaAreaMarkerContainer = () => {
- const { data: regions, isSuccess, isError } = useRegionMarkers();
+ const { data: regions, isSuccess, isError } = useRegionMarkersQuery();
if (!regions || !isSuccess || isError) {
return <>>;
}
diff --git a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/components/RegionMarker.stories.tsx b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/components/RegionMarker.stories.tsx
similarity index 100%
rename from frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/components/RegionMarker.stories.tsx
rename to frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/components/RegionMarker.stories.tsx
diff --git a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/components/RegionMarker.tsx b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/components/RegionMarker.tsx
similarity index 100%
rename from frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/components/RegionMarker.tsx
rename to frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/components/RegionMarker.tsx
diff --git a/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/components/RegionMarkerRenderer.tsx b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/components/RegionMarkerRenderer.tsx
new file mode 100644
index 000000000..01d3ef12a
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/components/RegionMarkerRenderer.tsx
@@ -0,0 +1,23 @@
+import { useLayoutEffect } from 'react';
+
+import { useMarker } from '@marker/hooks/useMarker';
+
+import type { Region } from '../types';
+
+export interface RegionMarkerProps {
+ region: Region;
+}
+
+const RegionMarkerRenderer = ({ region }: RegionMarkerProps) => {
+ const { renderRegionMarker } = useMarker();
+
+ useLayoutEffect(() => {
+ const unmount = renderRegionMarker(region);
+
+ return unmount;
+ }, []);
+
+ return <>>;
+};
+
+export default RegionMarkerRenderer;
diff --git a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/hooks/useRegionMarkers.ts b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/hooks/useRegionMarkersQuery.ts
similarity index 94%
rename from frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/hooks/useRegionMarkers.ts
rename to frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/hooks/useRegionMarkersQuery.ts
index df81c25f6..97c9f49b9 100644
--- a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/hooks/useRegionMarkers.ts
+++ b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/hooks/useRegionMarkersQuery.ts
@@ -20,7 +20,7 @@ export const fetchRegionMarkers = async () => {
return stationMarkers;
};
-export const useRegionMarkers = () => {
+export const useRegionMarkersQuery = () => {
return useQuery({
queryKey: [QUERY_KEY_REGION_MARKERS],
queryFn: fetchRegionMarkers,
diff --git a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/index.ts b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/index.ts
similarity index 100%
rename from frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/index.ts
rename to frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/index.ts
diff --git a/frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/types/index.ts b/frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/types/index.ts
similarity index 100%
rename from frontend/src/components/google-maps/marker/MaxDeltaAreaMarkerContainer/types/index.ts
rename to frontend/src/components/google-maps/marker/components/MaxDeltaAreaMarkerContainer/types/index.ts
diff --git a/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/SmallMediumDeltaAreaContainer.tsx b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/SmallMediumDeltaAreaContainer.tsx
new file mode 100644
index 000000000..d11f6e0cb
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/SmallMediumDeltaAreaContainer.tsx
@@ -0,0 +1,31 @@
+import { useExternalValue } from '@utils/external-state';
+
+import { deltaAreaStore } from '@stores/google-maps/deltaAreaStore';
+
+import CarffeineMarkerRenderer from './components/marker/CarffeineMarkerRenderer';
+import DefaultMarkerRenderer from './components/marker/DefaultMarkerRenderer';
+import { useStationMarkersQuery } from './hooks/useStationMarkersQuery';
+
+const SmallMediumDeltaAreaMarkerContainer = () => {
+ const { data: stationMarkers, isSuccess } = useStationMarkersQuery();
+ const deltaAreaState = useExternalValue(deltaAreaStore);
+
+ if (!isSuccess) {
+ return <>>;
+ }
+
+ return (
+ <>
+ {stationMarkers.map((stationMarker) => {
+ if (deltaAreaState === 'small') {
+ return ;
+ }
+ if (deltaAreaState === 'medium') {
+ return ;
+ }
+ })}
+ >
+ );
+};
+
+export default SmallMediumDeltaAreaMarkerContainer;
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeine.stories.tsx b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeine.stories.tsx
similarity index 100%
rename from frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeine.stories.tsx
rename to frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeine.stories.tsx
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.style.ts b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.style.ts
similarity index 100%
rename from frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.style.ts
rename to frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.style.ts
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.test.tsx b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.test.tsx
similarity index 100%
rename from frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.test.tsx
rename to frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.test.tsx
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.tsx b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.tsx
similarity index 100%
rename from frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.tsx
rename to frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.tsx
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/index.ts b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/index.ts
similarity index 100%
rename from frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/index.ts
rename to frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/index.ts
diff --git a/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/marker/CarffeineMarkerRenderer.tsx b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/marker/CarffeineMarkerRenderer.tsx
new file mode 100644
index 000000000..9f5e50160
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/marker/CarffeineMarkerRenderer.tsx
@@ -0,0 +1,23 @@
+import { useLayoutEffect } from 'react';
+
+import { useMarker } from '@marker/hooks/useMarker';
+
+import type { StationMarker } from '@type';
+
+interface Props {
+ station: StationMarker;
+}
+
+const CarffeineMarkerRenderer = ({ station }: Props) => {
+ const { renderCarffeineMarker } = useMarker();
+
+ useLayoutEffect(() => {
+ const unmount = renderCarffeineMarker(station);
+
+ return unmount;
+ }, []);
+
+ return <>>;
+};
+
+export default CarffeineMarkerRenderer;
diff --git a/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/marker/DefaultMarkerRenderer.tsx b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/marker/DefaultMarkerRenderer.tsx
new file mode 100644
index 000000000..8672e2401
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/components/marker/DefaultMarkerRenderer.tsx
@@ -0,0 +1,28 @@
+import { useLayoutEffect } from 'react';
+
+import { useMarker } from '@marker/hooks/useMarker';
+
+import { markerInstanceStore } from '@stores/google-maps/markerInstanceStore';
+
+import type { StationMarker } from '@type';
+
+interface Props {
+ station: StationMarker;
+}
+
+const DefaultMarkerRenderer = ({ station }: Props) => {
+ const { renderDefaultMarker } = useMarker();
+
+ useLayoutEffect(() => {
+ // 검색 결과로 강제 생성한 마커에 대해선 새로운 마커 생성을 시도하지 않도록 한다.
+ if (markerInstanceStore.getState().every(({ id }) => id !== station.stationId)) {
+ const unmount = renderDefaultMarker(station);
+
+ return unmount;
+ }
+ }, []);
+
+ return <>>;
+};
+
+export default DefaultMarkerRenderer;
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/constants/index.ts b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/constants/index.ts
similarity index 100%
rename from frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/constants/index.ts
rename to frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/constants/index.ts
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkers.ts b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkersQuery.ts
similarity index 98%
rename from frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkers.ts
rename to frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkersQuery.ts
index e95f9277c..0adfb295b 100644
--- a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkers.ts
+++ b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkersQuery.ts
@@ -90,7 +90,7 @@ export const fetchStationMarkers = async () => {
return stationMarkers;
};
-export const useStationMarkers = () => {
+export const useStationMarkersQuery = () => {
const {
fastChargeStationFilter,
privateStationFilter,
diff --git a/frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/index.ts b/frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/index.ts
similarity index 100%
rename from frontend/src/components/google-maps/marker/SmallMediumDeltaAreaMarkerContainer/index.ts
rename to frontend/src/components/google-maps/marker/components/SmallMediumDeltaAreaMarkerContainer/index.ts
diff --git a/frontend/src/components/google-maps/marker/hooks/useMarker.tsx b/frontend/src/components/google-maps/marker/hooks/useMarker.tsx
new file mode 100644
index 000000000..5611a8df4
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/hooks/useMarker.tsx
@@ -0,0 +1,141 @@
+import { createRoot } from 'react-dom/client';
+
+import StyledClusterMarker from '@marker/components/LargeDeltaAreaMarkerContainer/components/StyledClusterMarker';
+import RegionMarker from '@marker/components/MaxDeltaAreaMarkerContainer/components/RegionMarker';
+import type { Region } from '@marker/components/MaxDeltaAreaMarkerContainer/types';
+import CarFfeineMarker from '@marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker';
+import {
+ addMarkerInstanceToExternalStore,
+ createMarkerDomElement,
+ createMarkerInstance,
+ getDefaultMarkerDesign,
+ removeMarkerInstanceFromExternalStore,
+} from '@marker/tools';
+
+import { getGoogleMapStore, googleMapActions } from '@stores/google-maps/googleMapStore';
+
+import { useStationInfoWindow } from '@hooks/google-maps/useStationInfoWindow';
+import useMediaQueries from '@hooks/useMediaQueries';
+
+import { useNavigationBar } from '@ui/Navigator/NavigationBar/hooks/useNavigationBar';
+import StationDetailsWindow from '@ui/StationDetailsWindow';
+
+import type { ClusterMarker, StationMarker } from '@type';
+
+export const useMarker = () => {
+ const screen = useMediaQueries();
+ const { openLastPanel } = useNavigationBar();
+ const { openStationInfoWindow } = useStationInfoWindow();
+
+ const renderDefaultMarker = (station: StationMarker) => {
+ const { latitude, longitude, stationId } = station;
+
+ const defaultMarkerDesign = getDefaultMarkerDesign(station.availableCount > 0);
+ const markerInstance = createMarkerInstance(latitude, longitude);
+
+ markerInstance.content = defaultMarkerDesign.element;
+
+ bindStationMarkerClickEvent(markerInstance, stationId);
+ addMarkerInstanceToExternalStore(markerInstance, stationId);
+
+ return () => {
+ markerInstance.map = null;
+ removeMarkerInstanceFromExternalStore(stationId);
+ };
+ };
+
+ const renderCarffeineMarker = (station: StationMarker) => {
+ const { latitude, longitude, stationId } = station;
+ const markerInstance = createMarkerInstance(latitude, longitude);
+ const container = createMarkerDomElement();
+
+ markerInstance.content = container;
+
+ bindStationMarkerClickEvent(markerInstance, stationId);
+ addMarkerInstanceToExternalStore(markerInstance, stationId);
+
+ createRoot(container).render();
+
+ return () => {
+ markerInstance.map = null;
+ removeMarkerInstanceFromExternalStore(stationId);
+ };
+ };
+
+ const renderClusterMarker = (cluster: ClusterMarker) => {
+ const { latitude, longitude, count } = cluster;
+
+ const markerInstance = createMarkerInstance(latitude, longitude);
+ const container = createMarkerDomElement();
+
+ markerInstance.content = container;
+
+ bindClusterMarkerClickEvent(markerInstance, cluster);
+ createRoot(container).render();
+
+ return () => {
+ markerInstance.map = null;
+ };
+ };
+
+ const renderRegionMarker = (region: Region) => {
+ const { latitude, longitude, count, regionName } = region;
+
+ const markerInstance = createMarkerInstance(latitude, longitude);
+ const container = createMarkerDomElement();
+
+ markerInstance.title = regionName;
+ markerInstance.content = container;
+
+ bindRegionMarkerClickEvent(markerInstance, region);
+ createRoot(container).render();
+
+ return () => {
+ markerInstance.map = null;
+ };
+ };
+
+ const bindStationMarkerClickEvent = (
+ markerInstance: google.maps.marker.AdvancedMarkerElement,
+ stationId: string
+ ) => {
+ markerInstance.addListener('click', () => {
+ openStationInfoWindow(stationId, markerInstance);
+
+ if (!screen.get('isMobile')) {
+ openLastPanel();
+ }
+ });
+ };
+
+ const bindClusterMarkerClickEvent = (
+ markerInstance: google.maps.marker.AdvancedMarkerElement,
+ cluster: ClusterMarker
+ ) => {
+ const { latitude, longitude } = cluster;
+
+ markerInstance.addListener('click', () => {
+ const currentZoom = getGoogleMapStore().getState().getZoom();
+
+ googleMapActions.moveTo({ lat: latitude, lng: longitude }, currentZoom + 1);
+ });
+ };
+
+ const bindRegionMarkerClickEvent = (
+ markerInstance: google.maps.marker.AdvancedMarkerElement,
+ region: Region
+ ) => {
+ const { latitude, longitude } = region;
+
+ markerInstance.addListener('click', () => {
+ googleMapActions.moveTo({ lat: latitude, lng: longitude }, 12);
+ });
+ };
+
+ return {
+ renderDefaultMarker,
+ renderCarffeineMarker,
+ renderClusterMarker,
+ renderRegionMarker,
+ };
+};
diff --git a/frontend/src/components/google-maps/marker/tools/index.ts b/frontend/src/components/google-maps/marker/tools/index.ts
new file mode 100644
index 000000000..65eadd767
--- /dev/null
+++ b/frontend/src/components/google-maps/marker/tools/index.ts
@@ -0,0 +1,58 @@
+import { MARKER_COLORS } from '@marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.style';
+import { DEFAULT_MARKER_SIZE_RATIO } from '@marker/components/SmallMediumDeltaAreaMarkerContainer/constants';
+
+import { getGoogleMapStore } from '@stores/google-maps/googleMapStore';
+import { markerInstanceStore } from '@stores/google-maps/markerInstanceStore';
+
+const animateMarkers = (marker: HTMLElement) => {
+ marker.style.opacity = '0';
+ marker.classList.add('marker-animation');
+
+ marker.addEventListener('animationend', () => {
+ marker.classList.remove('marker-animation');
+ marker.style.opacity = '1';
+ });
+};
+
+export const getDefaultMarkerDesign = (isAvailable: boolean) => {
+ const markerColor = isAvailable ? MARKER_COLORS.available : MARKER_COLORS.noAvailable;
+
+ const defaultMarkerDesign = new google.maps.marker.PinElement({
+ scale: DEFAULT_MARKER_SIZE_RATIO,
+ background: markerColor.background,
+ borderColor: markerColor.border,
+ glyph: '',
+ });
+
+ animateMarkers(defaultMarkerDesign.element);
+
+ return defaultMarkerDesign;
+};
+
+export const createMarkerDomElement = () => {
+ const container = document.createElement('div');
+
+ animateMarkers(container);
+
+ return container;
+};
+
+export const createMarkerInstance = (latitude: number, longitude: number) => {
+ const markerInstance = new google.maps.marker.AdvancedMarkerElement({
+ position: new google.maps.LatLng(latitude, longitude),
+ map: getGoogleMapStore().getState(),
+ });
+
+ return markerInstance;
+};
+
+export const addMarkerInstanceToExternalStore = (
+ instance: google.maps.marker.AdvancedMarkerElement,
+ id: string
+) => {
+ markerInstanceStore.setState((prev) => [...prev, { id, instance }]);
+};
+
+export const removeMarkerInstanceFromExternalStore = (id: string) => {
+ markerInstanceStore.setState((prev) => prev.filter((markerInstance) => markerInstance.id !== id));
+};
diff --git a/frontend/src/components/ui/MapController.tsx b/frontend/src/components/ui/MapController.tsx
index 6b19f454c..055378cee 100644
--- a/frontend/src/components/ui/MapController.tsx
+++ b/frontend/src/components/ui/MapController.tsx
@@ -3,8 +3,8 @@ import { css } from 'styled-components';
import { BiCurrentLocation } from 'react-icons/bi';
-import { useClusterMarkers } from '@marker/LargeDeltaAreaMarkerContainer/hooks/useClusterMarkers';
-import { useStationMarkers } from '@marker/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkers';
+import { useClusterMarkersQuery } from '@marker/components/LargeDeltaAreaMarkerContainer/hooks/useClusterMarkersQuery';
+import { useStationMarkersQuery } from '@marker/components/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkersQuery';
import { googleMapActions } from '@stores/google-maps/googleMapStore';
@@ -15,8 +15,8 @@ import Loader from '@common/Loader';
import { MOBILE_BREAKPOINT } from '@constants';
const MapController = () => {
- const { isFetching: isStationMarkerFetching } = useStationMarkers();
- const { isFetching: isClusterMarkerFetching } = useClusterMarkers();
+ const { isFetching: isStationMarkerFetching } = useStationMarkersQuery();
+ const { isFetching: isClusterMarkerFetching } = useClusterMarkersQuery();
const isMarkerFetching = isStationMarkerFetching || isClusterMarkerFetching;
diff --git a/frontend/src/components/ui/StationInfoWindow/StationInfo.tsx b/frontend/src/components/ui/StationInfoWindow/StationInfo.tsx
index cf8a569dd..61abc25ea 100644
--- a/frontend/src/components/ui/StationInfoWindow/StationInfo.tsx
+++ b/frontend/src/components/ui/StationInfoWindow/StationInfo.tsx
@@ -4,7 +4,7 @@ import { getChargerCountsAndAvailability } from '@tools/getChargerCountsAndAvail
import type { MouseEvent } from 'react';
import { HiChevronRight } from 'react-icons/hi2';
-import { MARKER_COLORS } from '@marker/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.style';
+import { MARKER_COLORS } from '@marker/components/SmallMediumDeltaAreaMarkerContainer/components/CarFfeineMarker/CarFfeineMarker.style';
import Box from '@common/Box';
import Button from '@common/Button';
diff --git a/frontend/src/components/ui/StationListWindow/StationList.tsx b/frontend/src/components/ui/StationListWindow/StationList.tsx
index fe329d473..1834ae1ac 100644
--- a/frontend/src/components/ui/StationListWindow/StationList.tsx
+++ b/frontend/src/components/ui/StationListWindow/StationList.tsx
@@ -2,7 +2,7 @@ import { css } from 'styled-components';
import { useEffect, useRef } from 'react';
-import { useStationMarkers } from '@marker/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkers';
+import { useStationMarkersQuery } from '@marker/components/SmallMediumDeltaAreaMarkerContainer/hooks/useStationMarkersQuery';
import List from '@common/List';
import Text from '@common/Text';
@@ -18,7 +18,7 @@ import { useInfiniteStationSummaries } from './hooks/useInfiniteStationSummaries
import { cachedStationSummariesActions } from './tools/cachedStationSummaries';
const StationList = () => {
- const { data: filteredMarkers } = useStationMarkers();
+ const { data: filteredMarkers } = useStationMarkersQuery();
const { data, isLoading, isError, isFetchingNextPage, fetchNextPage, hasNextPage, error } =
useInfiniteStationSummaries(filteredMarkers ?? []);
diff --git a/frontend/src/components/ui/StationSearchWindow/hooks/useStationSearchWindow.tsx b/frontend/src/components/ui/StationSearchWindow/hooks/useStationSearchWindow.tsx
index e4f0b5b67..a10871607 100644
--- a/frontend/src/components/ui/StationSearchWindow/hooks/useStationSearchWindow.tsx
+++ b/frontend/src/components/ui/StationSearchWindow/hooks/useStationSearchWindow.tsx
@@ -1,11 +1,11 @@
+import { getChargerCountsAndAvailability } from '@tools/getChargerCountsAndAvailability';
+
import type { ChangeEvent, FocusEvent, FormEvent, MouseEvent } from 'react';
import { useState } from 'react';
import { useQueryClient } from '@tanstack/react-query';
-import { useRenderStationMarker } from '@marker/SmallMediumDeltaAreaMarkerContainer/hooks/useRenderStationMarker';
-
-import { useSetExternalState } from '@utils/external-state';
+import { useMarker } from '@marker/hooks/useMarker';
import { googleMapActions } from '@stores/google-maps/googleMapStore';
import { markerInstanceStore } from '@stores/google-maps/markerInstanceStore';
@@ -16,17 +16,12 @@ import useMediaQueries from '@hooks/useMediaQueries';
import { useNavigationBar } from '@ui/Navigator/NavigationBar/hooks/useNavigationBar';
-import {
- QUERY_KEY_SEARCHED_STATION,
- QUERY_KEY_STATION_DETAILS,
- QUERY_KEY_STATION_MARKERS,
-} from '@constants/queryKeys';
+import { QUERY_KEY_SEARCHED_STATION } from '@constants/queryKeys';
import { SERVER_URL } from '@constants/server';
import type { StationDetails, StationPosition } from '@type';
import StationDetailsWindow from '../../StationDetailsWindow/index';
-import { convertStationDetailsToSummary } from '../tools/convertStationDetailsToSummary';
export const useStationSearchWindow = () => {
const queryClient = useQueryClient();
@@ -34,11 +29,10 @@ export const useStationSearchWindow = () => {
const [isFocused, setIsFocused] = useState(false);
const [searchWord, setSearchWord] = useState('');
- const setMarkerInstances = useSetExternalState(markerInstanceStore);
+ const { renderDefaultMarker } = useMarker();
const { openLastPanel } = useNavigationBar();
const { openStationInfoWindow } = useStationInfoWindow();
- const { createNewMarkerInstance, renderDefaultMarkers } = useRenderStationMarker();
const screen = useMediaQueries();
@@ -67,7 +61,6 @@ export const useStationSearchWindow = () => {
const showStationDetails = async ({ stationId, latitude, longitude }: StationPosition) => {
googleMapActions.moveTo({ lat: latitude, lng: longitude });
- queryClient.invalidateQueries({ queryKey: [QUERY_KEY_STATION_MARKERS] });
if (!screen.get('isMobile')) {
openLastPanel();
@@ -84,19 +77,23 @@ export const useStationSearchWindow = () => {
const stationDetails = await fetch(
`${SERVER_URL}/stations/${stationId}`
).then((response) => response.json());
-
- const markerInstance = createNewMarkerInstance(stationDetails);
-
- setMarkerInstances((prev) => [...prev, { id: stationId, instance: markerInstance }]);
-
- renderDefaultMarkers(
- [{ id: stationId, instance: markerInstance }],
- [convertStationDetailsToSummary(stationDetails)]
+ const { quickChargerCount, availableCount } = getChargerCountsAndAvailability(
+ stationDetails.chargers
);
+ const { stationName, latitude, longitude, isParkingFree, isPrivate } = stationDetails;
+
+ renderDefaultMarker({
+ stationId,
+ stationName,
+ latitude,
+ longitude,
+ isParkingFree,
+ isPrivate,
+ availableCount,
+ quickChargerCount,
+ });
- openStationInfoWindow(stationId, markerInstance);
-
- queryClient.setQueryData([QUERY_KEY_STATION_DETAILS, stationId], stationDetails);
+ openStationInfoWindow(stationId);
}
};
diff --git a/frontend/src/mocks/data/regions.ts b/frontend/src/mocks/data/regions.ts
index 5dc59d42b..cdf37ed42 100644
--- a/frontend/src/mocks/data/regions.ts
+++ b/frontend/src/mocks/data/regions.ts
@@ -1,4 +1,4 @@
-import type { Region, RegionName } from '@marker/MaxDeltaAreaMarkerContainer/types';
+import type { Region, RegionName } from '@marker/components/MaxDeltaAreaMarkerContainer/types';
export const regions: Region[] = [
{
diff --git a/frontend/src/mocks/handlers/station-markers/stationMarkerHandlers.ts b/frontend/src/mocks/handlers/station-markers/stationMarkerHandlers.ts
index 0e0f42618..8ac994b81 100644
--- a/frontend/src/mocks/handlers/station-markers/stationMarkerHandlers.ts
+++ b/frontend/src/mocks/handlers/station-markers/stationMarkerHandlers.ts
@@ -101,7 +101,7 @@ export const stationMarkerHandlers = [
console.log('찾은 충전소 갯수: ' + foundStations.length);
return res(
- // ctx.delay(1000),
+ ctx.delay(1000),
ctx.status(200),
ctx.json({
stations: foundStations,
diff --git a/frontend/src/tools/getChargerCountsAndAvailability.ts b/frontend/src/tools/getChargerCountsAndAvailability.ts
index 1026cda26..9d6748471 100644
--- a/frontend/src/tools/getChargerCountsAndAvailability.ts
+++ b/frontend/src/tools/getChargerCountsAndAvailability.ts
@@ -18,6 +18,7 @@ export const getChargerCountsAndAvailability = (chargers: Charger[]) => {
const availableQuickChargerCount = quickChargers.filter(
({ state }) => state === 'STANDBY'
).length;
+ const availableCount = availableStandardChargerCount + availableQuickChargerCount;
const standardChargerCount = standardChargers.length;
const quickChargerCount = quickChargers.length;
@@ -28,5 +29,6 @@ export const getChargerCountsAndAvailability = (chargers: Charger[]) => {
availableQuickChargerCount,
standardChargerCount,
quickChargerCount,
+ availableCount,
};
};