네이버 마커 클러스터링을 적용해보자 - 1. react naver map 문서 따라가기

sumi-0011·2023년 6월 11일
1
post-thumbnail

Next.js 환경에서 네이버 맵을 이용하여 구현하고 있었는데,
마커들이 일정 이상 겹치면 합쳐서 보일 수 있게 클러스터링 기능 추가 요청사항을 받았다.
마커 클러스터링 기능을 프로젝트에 바로 구현하기 전, 먼저 문서를 따라 예시를 구현해보았다.

구현 환경

 "next": "13.1.2",
 "react": "18.2.0",
 "react-naver-maps": "^0.1.2",
 "typescript": "4.9.4",

네이버 '마커 클러스터화하기' 문서 따라가기

1. '마커 클러스터화'예시를 react 환경에 맞게 구현해보기

react-naver-maps 라이브러리 문서에서
'마커 클러스터화하기' 문서를 참고하여 따라가 보았다.

1.MarkerClustering.js을 로컬에 복사 붙여넣기

const MarkerClustering = makeMarkerClustering(window.naver);

문서 예시를 보면 위와 같은 코드가 존재하는데, makeMarkerClustering 함수를 불러오기 위해 MarkerClustering.js파일이 필요하다.
MarkerClustering.js 파일은 아래 링크에서 가져오면 된다.
MarkerClustering.js

2. 클러스터링 아이콘 생성

문서에서 아래의 htmlMarker 들은 클러스터링 아이콘을 생성하는 부분이다.

 const htmlMarker1 = {
    content: '<div style="cursor:pointer;width:40px;height:40px;line-height:42px;font-size:10px;color:white;text-align:center;font-weight:bold;background:url(https://navermaps.github.io/maps.js.ncp/docs/img/cluster-marker-1.png);background-size:contain;"></div>',
    size: navermaps.Size(40, 40),
    anchor: navermaps.Point(20, 20),
 }
 ...

나는 한 컴포넌트에서 마커를 생성해주는 것 까지 있으면 너무 복잡할 것 이라고 생각해서,
custom hook을 만들어 분리하였다.

navermaps객체를 가지고 만들어주어야 해서 hook을 만들어서 분리하였다.

useGetClusterIcon 사용

  const { htmlMarker1, htmlMarker2, htmlMarker3, htmlMarker4, htmlMarker5 } =
    useGetClusterIcon(navermaps);

useGetClusterIcon 구현

const useGetClusterIcon = (navermaps: typeof naver.maps) => {
	const htmlMarker1 = {
    content: '<div style="cursor:pointer;width:40px;height:40px;line-height:42px;font-size:10px;color:white;text-align:center;font-weight:bold;background:url(https://navermaps.github.io/maps.js.ncp/docs/img/cluster-marker-1.png);background-size:contain;"></div>',
    size: navermaps.Size(40, 40),
    anchor: navermaps.Point(20, 20),
 }
 ...

  return { htmlMarker1, htmlMarker2, htmlMarker3, htmlMarker4, htmlMarker5 };
};

3. 클러스터화 할 마커 생성하기

 const markers = []

 for (var i = 0, ii = data.length; i < ii; i++) {
   var spot = data[i],
       latlng = new naver.maps.LatLng(spot.grd_la, spot.grd_lo),
       marker = new naver.maps.Marker({
         position: latlng, // 마커의 위치
         draggable: true, // 마커 이동 가능하게
       })

   markers.push(marker)
 }

4. 생성한 마커들을 클러스트화 한 클러스트 객체 생성하기

 const cluster = new MarkerClustering({
      minClusterSize: 2, 
      maxZoom: 8, // 조절하면 클러스터링이 되는 기준이 달라짐 (map zoom level)
      map: map, 
      markers: markers, // 클러스터화 할 마커들
      disableClickZoom: false,
      gridSize: 120,
      icons: [  // 클러스터 아이콘 세팅
        htmlMarker1,
        htmlMarker2,
        htmlMarker3,
        htmlMarker4,
        htmlMarker5,
      ],
      indexGenerator: [10, 100, 200, 500, 1000], // 클러스터링 기준 세팅
      stylingFunction: function (clusterMarker, count) {
        clusterMarker
          .getElement()
          .querySelector('div:first-child').innerText = count
      },
    })

5. 생성한 클러스트 객체를 state로 관리

클러스트 객체를 state로 관리하는 이유는, 클러스트 마커를 한번만 생성하기 위해서이다.
참고 링크

위에서 생성한 마커 리스트 markerscluster객체를 이용하여 cluster state를 생성한다.

const [cluster] = useState(() => {
    const markers = []

    // ... 마커 생성

    const cluster = new MarkerClustering({
 		...
    })

    return cluster
})

6. 클러스터링 객체를 overlay 객체에 넘겨 지도에 띄운다.

return <Overlay element={cluster} />

마커 클러스터링 기능을 구현하는데 필요한 파일을 다운받고,
실제로 프로젝트에서 실행해보았다.

예제에서는 마커를 생성하고, 클러스터링 하는 방법을 보여주었다.
예제를 프로젝트에 구현해보면서 예제가 마커 클러스터링을 어떻게 구현하고 있는지 알아 낼 수 있었다.

요구사항을 충족 하려면, 이미 생성되어 있는 커스텀 마커를 클러스터링 해야하기 때문에
이미 생성되어있는 마커를 props로 넘기고, 클러스터링 하는 법을 찾아보았다.

다음 글 =>

전체 코드 확인

=> 링크

참고 링크

profile
안녕하세요 😚

0개의 댓글