인프런 커뮤니티 질문&답변

윌럄님의 프로필 이미지

작성한 질문수

Next.js 시작하기(feat. 지도 서비스 개발)

DetailSection placeholder UI 구현하기

마커 클러스터링 도입

해결된 질문

23.02.23 23:18 작성

·

2.5K

2

안녕하세요, 강의 보면서 많은 도움 받았습니다.

제가 추가로 마커클러스터링을 도입하려고 하는데 네이버에서 제공하는 깃헙 예제 코드를 봐도 도무지 이해가 안가서요.. 혹시 어떤식으로 풀어나가면 될지 궁금합니다... ㅠㅠ

 

답변 2

1

윌럄님의 프로필 이미지
윌럄
질문자

2023. 02. 24. 21:02

감사합니다 튜터님 ! 지금 당장 적용해보겠습니다 !

1

박용주님의 프로필 이미지
박용주
지식공유자

2023. 02. 24. 14:40

좋은 질문 감사합니다! 덕분에 저도 네이버 클러스터링 예제를 알게 되었습니다ㅎㅎ

네이버 문서를 보니 윌럄님께서 보신 github 예제 코드가 아래 링크 같은데 맞을까요?
https://github.com/navermaps/marker-tools.js/tree/master/marker-clustering
위의 예제 코드를 토대로 'Markers.tsx' 컴포넌트를 대강 재구성해보았습니다.

  1. 예제 코드에 있는 'MarkerClustering.js' 파일을 복사하여 가져옵니다.
    코드: https://github.com/navermaps/marker-tools.js/blob/master/marker-clustering/src/MarkerClustering.js
    image위의 사진처럼 cluster.js를 만들어 소스를 그대로 복사해왔습니다.
    파일 위치와 파일명은 답변을 위해 임의로 작성한 것이니 질문자님의 기호에 맞는 위치와 파일명을 변경해주시면 될 것 같습니다ㅎㅎ

  2. 기존의 Markers.tsx 코드는 지우고, github 예제 코드를 복사합니다.
    아래의 코드는 제가 임의로 작성한 코드입니다. MarkerClustering Class를 완전히 이해한 뒤 작성한 것이 아니라, 답변을 위해 예제 코드를 대부분 그대로 복사해온 것입니다. 답변을 통해 큰 틀만 잡고, 질문자님이 구현하고 싶은 기획에 맞게 코드와 MarkerClustering option 값들을 바꾸시면 될 것 같습니다.

// Markers.tsx
import React, { useEffect } from 'react';
import useSWR from 'swr';
import { MAP_KEY } from '../../hooks/useMap';
import { STORE_KEY } from '../../hooks/useStores';
import type { NaverMap } from '../../types/map';
import type { Store } from '../../types/store';

const Markers = () => {
  const { data: map } = useSWR<NaverMap>(MAP_KEY);
  const { data: stores } = useSWR<Store[]>(STORE_KEY);

  useEffect(() => {
    if (map) {
      import('./cluster').then(({ MarkerClustering }) => { // NOTE: 'naver is not defined' 오류를 피하기 위한 hack 코드. 빠른 답변을 위해 대충 dynamic import를 사용했습니다..!
        var htmlMarker1 = {
            content: [
              `<div style='width: 40px; height: 40px; border-radius: 50%;  background: #b08fc5;
                           display: flex; align-items: center; justify-content: center'>`,
              `<span style='color: white; font-size: 0.875rem'>1</span>`,
              `</div>`,
            ].join(''),
            size: new naver.maps.Size(40, 40),
            anchor: new naver.maps.Point(20, 20),
          },
          htmlMarker2 = {
            content: [
              `<div style='width: 40px; height: 40px; border-radius: 50%;  background: #cdbdd7;
                           display: flex; align-items: center; justify-content: center'>`,
              `<span style='color: white; font-size: 0.875rem'>2</span>`,
              `</div>`,
            ].join(''),
            size: new naver.maps.Size(40, 40),
            anchor: new naver.maps.Point(20, 20),
          };

        // NOTE: stores 데이터를 이용하여 markers 배열 생성
        const markers: naver.maps.Marker[] = [];
        stores?.forEach((store) => {
          const marker = new naver.maps.Marker({
            map: map,
            position: new naver.maps.LatLng(...store.coordinates),
          });
          markers.push(marker);
        });

        // NOTE: MarkerClustering 생성. option을 하나하나 살펴보지는 않았습니다. 자유롭게 변경해주세요!
        var markerClustering = new MarkerClustering({
          minClusterSize: 2,
          maxZoom: 13,
          map: map,
          markers: markers,
          disableClickZoom: false,
          gridSize: 120,
          icons: [htmlMarker1, htmlMarker2],
          indexGenerator: [10, 100, 200, 500, 1000],
          stylingFunction: function (clusterMarker: any, count: number) { // NOTE: MarkerClustering.js가 자바스크립트라 임시로 any 적용
            clusterMarker.getElement().querySelector('span').textContent =
              count;
          },
        });
      });
    }
  }, [map, stores]);

  return null;
};
export default Markers;

github 예제와 다른 부분이 몇 가지 있는데, 아래에 나열해두겠습니다.
1) jquery를 쓰지 않기 위해서, stylingFunction 함수의 내용을 querySelector를 이용하여 바꿨습니다.
2) htmlMarker는 2개만 사용했습니다. content 값도 예제의 image를 사용하지 않고 div tag를 이용하여 동그라미 UI를 새롭게 만들었습니다.
3) 그 외 'NOTE' 주석 참고

그 외에는 최대한 예제 코드를 그대로 가져왔습니다. 그래서 var 등의 레거시도 그대로 남아있는데, 자유롭게 리팩토링하시면 더 좋은 코드가 될 것 같습니다ㅎㅎ

  1. 위의 과정을 따라하시면 아래와 같이 클러스터링이 적용된 모습을 보실 수 있을 것입니다.
    image


    예제 코드를 통해 전체적인 가닥을 잡고 싶은게 질문 내용인 것 같아, 한 줄 한 줄 완벽하게 구현하기보단 예제 코드를 빠르게 Markers.tsx 파일로 옮기는 것을 목표로 했습니다.
    Next.js 환경으로 클러스터링 코드를 옮겼으니, 이제 MarkerClustering.js 클래스를 뜯어보면서 원하시는 구현을 위해 고도화해 나가면 될 것 같습니다!
    잘 안 되시거나 더 고도화하기 힘든 부분이 있다면 질문 남겨주시길 바랍니다. 감사합니다 :)

윌럄님의 프로필 이미지

작성한 질문수

질문하기