1. 문제의 발단
- 평소에 매우 자주 사용하는 지도 API다. (... 였다) 전투적으로 약 8달 이상은 사용했던 네이버 지도에서 쉽고도 어렵게 사용했던 Marker 시스템을 정리해 보려고 한다.
2. 기본적인 사용법
const loadScript = () => {
return new Promise((resolve) => {
if (document && document.querySelectorAll('#naver-map-sdk').length === 0) {
const script = document.createElement('script');
script.id = 'naver-map-sdk';
script.src = `https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=${NCP_CLIENT_ID}&submodules=geocoder,panorama`;
script.onload = () => {
resolve(true);
};
document.head.appendChild(script);
} else {
resolve(true);
console.log('script already loaded');
}
});
};
- 위와 같이 script를 심어준다. await로 지도 init시 호출하게 된다.
const initMap = async (containerId: string, isActiveDistance: number) => {
// 스크립트 로드
await loadScript();
// 지도 생성시 설정해 줄 옵션이다.
const initialMapOptions = {
center: [point.longitude, point.latitude],
zoom: 16,
minZoom: 12,
maxZoom: 22,
zoomOrigin: [point.longitude, point.latitude],
pinchZoom: false,
mapDataControl: false,
disableDoubleClickZoom: false,
disableDoubleTapZoom: false,
logoControlOptions: {
position: naver?.maps?.Position?.BOTTOM_LEFT,
},
mapDataControlOptions: {
position: naver?.maps?.Position?.BOTTOM_CENTER,
},
scaleControlOptions: {
position: naver?.maps?.Position?.BOTTOM_LEFT,
},
};
const map = new naver.maps.Map(containerId, initialMapOptions) as any;
new naver.maps.Circle({
map: map,
center: [point.longitude, point.latitude],
radius: isActiveDistance + 100,
fillColor: '#ffffff',
fillOpacity: 0.2,
strokeOpacity: 0,
});
// 마커생성은 함수로 만들어서 쓰고 있다.
const pinMarker = makeIconMarker(map, [point.longitude, point.latitude], 'pin');
// 지도 옵션 (마커나 지도에 커서를 바꿔줌)
pinMarker.setCursor('default');
map.setCursor('default');
return map;
};
useEffect(() => {
initMap('mainMap');
}, []);
- 이런 식으로 지도를 생성해 주고, map이 들어갈 div에 id 값을 알맞게 준다.
- 각종 지도 옵션 및 마커, 도형 등의 옵션은 docs를 참고한다. (https://navermaps.github.io/maps.js.ncp/docs/)
3. Marker에 대한 고찰
- 지도에서 특정 마커를 지우거나 선택등을 하려면 그 특정 마커 요소 자체를 정확히 알고 가지고 있어야 한다.
- 이때, state로 마커를 가지도 다닐 수는 없다.
- 예를 들어, maker.setMap(null)로 특정 마커를 지울 수 있다. 이때, state에 마커를 넣어놓고 지우려고 하면 올바르게 동작하지 않는다.
- 이때는 useRef를 사용한다.
const markerRef = useRef<naver.maps.Marker>();
const marker = makeMarker(map, point, {
value: 100
});
markerRef.current = marker;
useEffect(() => {
markerRef.current?.setMap(null);
const marker = makeMarker(map, point, {
value: 200
});
marker.setMap(mapRef.current);
markerRef.current = marker;
}
}, [isActive]);
- isActive가 변경될 때마다, 기존의 value 100의 마커는 사라지고, value 200을 가진 마커가 생성된다. (isActive가 단 한 번만 바뀐다는 전제 하에 이렇게 만들 수 있지만 급조한 코드라 어색하다)
- 마찬가지로 마커 뿐 아니라 map 객체 자체나 도형들과 같은 지도 위 요소들도 다 useRef로 관리가 가능하고, 이를 list형태로 저장하여 사용할 수 도 있다.
'Coding > Today I Learned' 카테고리의 다른 글
2023.06.06(Tue.) <Jest를 이용한 프론트엔드 테스트 코드> (0) | 2023.06.06 |
---|---|
2023.05.31(Wed.) tailwindcss를 알아보자 (0) | 2023.05.31 |
2023.05.29(Mon.) useMemo에 관한 고찰 (0) | 2023.05.29 |
2022.02.21(Mon.)<프로그래머스 짝지어 제거하기 문제 풀이> (0) | 2022.02.21 |
2022.02.20(Sun.) <프로그래머스 구명보트 문제 풀이> (0) | 2022.02.20 |