개발 프로젝트/[next.js] 지도 서비스 개발
지도에 마커 추가하기📌
jennayeo
2023. 9. 19. 18:03
마커를 그리기위해선 마커가 네이버 'map'객체에 접근할 수 있어야한다. 즉, map컴포넌트에서 만든 'map'이라는 객체를 전역상태로 공유하여 마커에서도 접근할 수 있게 만들어야한다.
// Map.tsx
if (onLoad) {
onLoad(map);
}
map을 만들면 onLoad함수를 이용하여 map객체를 밖으로 보낼 수 있다.
onLoad함수는 Map.tsx의 상위 컴포넌트 MapSection.tsx에서 prop으로 보내준다.
// MapSection.tsx
const MapSection = () => {
const { initializeMap } = useMap();
const onLoadMap = (map: NaverMap) => {
initializeMap(map);
};
return (
<>
<Map onLoad={onLoadMap} />
<Markers />
</>
);
};
export default MapSection;
onLoadMap은 SWR을 이용하여 Map을 전역상태로 관리하도록한다.
initializeMap은 useMap이라는 hook에서 가져온다.
//useMap.ts
export const INITIAL_CENTER: Coordinates = [37.5262411, 126.99289439];
export const INITIAL_ZOOM = 10;
export const MAP_KEY = '/map';
const useMap = () => {
const initializeMap = useCallback((map: NaverMap) => {
mutate(MAP_KEY, map); // SWR의 내장함수 mutate를사용해 MAP_KEY라는 문자열에 네이버 맵 객체를 전역상태로 저장
}, []);
return {
initializeMap,
};
};
export default useMap;
지도가 로드되었을때 initializeMap함수가 실행되면서 map 객체는 전역상태로 저장된다.
이제 지금까지 저장해둔 전역상태를 이용하는 Markers컴포넌트를 만들어보자
//Markers.tsx
const { data: map } = useSWR<NaverMap>(MAP_KEY);
const { data: stores } = useSWR<Store[]>(STORE_KEY);
SWR에서 hook 'useSWR'을 import한다. useSWR의 인자로 MAP_KEY를 주면 전역상태로 관리되고있는 map data를 얻을 수 있다. Store key를 인자로 줬을때 매장 데이터를 얻을 수 있는것도 마찬가지다.
//Markers.tsx
if (!map || !stores) return null;
return (
<>
{stores.map((store) => {
return (
<Marker
map={map}
coordinates={store.coordinates}
key={store.nid}
/>
);
})}
</>
);
매장 데이터를 map돌려서 Marker컴포넌트를 불러온다.
//Marker.tsx
const Marker = ({ map, coordinates, icon, onClick }: Marker): null => {
useEffect(() => {
let marker: naver.maps.Marker | null = null;
if (map) {
marker = new naver.maps.Marker({
map: map,
position: new naver.maps.LatLng(...coordinates),
});
}
if (onClick) {
naver.maps.Event.addListener(marker, 'click', onClick);
}
return () => {
marker?.setMap(null);
};
}, [map]);
return null;
};
그럼 이제 아래와 같이 마커들이 찍힌다 타-단-