Dandy Now!
  • [React.js] 네이버 지도 API 마커 클러스터 튜터리얼 따라하기!
    2024년 02월 21일 16시 52분 44초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    [그림 1] 마커 클러스터 적용 결과

     

    1. 네이버 지도 API 설치

    npm install react-naver-maps --save

     

    2. App.js에 NavermapsProvider 적용

    NavermapsProvider의 경우-이 글을 작성하는 시점에-공식 문서에는 NaverMapsProvider로 되어 있었고 따라서 로딩 에러가 발생했다. 따라서 NavermapsProvider라고 import 해야 한다.

    // src/App.js
    import { NavermapsProvider } from "react-naver-maps";
    import NaverMapsMarkerCluster from "./components/NaverMapsMarkerCluster";
    
    function App() {
      // ncpClientId에 네이버 지도 API 클라이언트 키를 넣으면 된다.
      // npx create-react-app으로 프로젝트를 생성했다면-별도의 의존성 설치 없이-프로젝트 최상위 폴더에 .env 파일을 생성하고 키를 기입하면 된다.
      // .env에는 REACT_APP_NAVER_KEY의 값으로 키를 기입하면 되는데, REACT_APP_라는 prefix에 유의 하자!
      const naverKey = process.env.REACT_APP_NAVER_KEY;
    
      return (
        <NavermapsProvider
          ncpClientId={naverKey} // 지도서비스 Client ID
          error={<p>error</p>}
          loading={<p>Maps Loading</p>}
        >
          <div style={{ display: "flex", width: "100dvw", height: "100dvh" }}>
            <NaverMapsMarkerCluster />
          </div>
        </NavermapsProvider>
      );
    }
    
    export default App;

     

    3. 마커 클러스터 기능을 포함한 지도 컴포넌트 작성

    // src/components/NaverMapsMarkerCluster.js
    
    import {
      Container as MapDiv,
      NaverMap,
      useNavermaps,
      Overlay,
      useMap,
    } from "react-naver-maps";
    import { useState } from "react";
    import { makeMarkerClustering } from "./marker-cluster";
    import { accidentDeath } from "./data/accidentdeath.js";
    
    function MarkerCluster() {
      const navermaps = useNavermaps();
      const map = useMap();
    
      // 아래 링크에서 marker-cluster.js를 다운로드한 후 이 컴포넌트와 동일 경로에 두고 import 하였다.
      // https://github.com/zeakd/react-naver-maps/blob/main/website/src/samples/marker-cluster.js
      const MarkerClustering = makeMarkerClustering(window.naver);
    
      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),
      };
      const htmlMarker2 = {
        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-2.png);background-size:contain;"></div>',
        size: navermaps.Size(40, 40),
        anchor: navermaps.Point(20, 20),
      };
      const htmlMarker3 = {
        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-3.png);background-size:contain;"></div>',
        size: navermaps.Size(40, 40),
        anchor: navermaps.Point(20, 20),
      };
      const htmlMarker4 = {
        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-4.png);background-size:contain;"></div>',
        size: navermaps.Size(40, 40),
        anchor: navermaps.Point(20, 20),
      };
      const htmlMarker5 = {
        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-5.png);background-size:contain;"></div>',
        size: navermaps.Size(40, 40), // naver.maps를 navermaps로 수정
        anchor: navermaps.Point(20, 20), // (상동)
      };
    
      // 아래 링크에서 데이터가 든 js 파일 다운로드
      // https://github.com/navermaps/marker-tools.js/blob/master/marker-clustering/data/accidentdeath.js
      const data = accidentDeath.searchResult.accidentDeath;
    
      console.log(data);
    
      const [cluster] = useState(() => {
        const markers = [];
    
        for (var i = 0, ii = data.length; i < ii; i++) {
          var spot = data[i],
            latlng = new navermaps.LatLng(spot.grd_la, spot.grd_lo),
            marker = new navermaps.Marker({
              position: latlng,
              draggable: true,
            });
    
          markers.push(marker);
        }
    
        const cluster = new MarkerClustering({
          minClusterSize: 2,
          maxZoom: 8,
          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;
          },
        });
    
        return cluster;
      });
    
      return <Overlay element={cluster} />;
    }
    
    function NaverMapsMarkerCluster() {
      const navermaps = useNavermaps();
    
      return (
        <MapDiv
          style={{
            width: "100%",
            height: "100%",
          }}
        >
          <NaverMap
            zoom={6}
            center={new navermaps.LatLng(36.2253017, 127.6460516)}
            zoomControl={true}
            zoomControlOptions={{
              position: navermaps.Position.TOP_LEFT,
              style: navermaps.ZoomControlStyle.SMALL,
            }}
          >
            <MarkerCluster />
          </NaverMap>
        </MapDiv>
      );
    }
    
    export default NaverMapsMarkerCluster;

     

     

    4. 위경도 데이터 추가

    아래 코드는 위경도 데이터가 포함된 js 파일이다. navermaps 깃허브 링크를 통해 다운로드하면 된다.

    // src/components/data/accidentdeath.js
    
    // 다른 컴포넌트에서 import하기 위해 export 키워드 추가
    export var accidentDeath = {
    // (생략)
    // 데이터가 너무 크면 렌더링 부담이 컸으므로 데이터를 일부 제거하고 테스트 해보는 것을 권한다.
    }

    😉 깃허브 링크 : https://github.com/navermaps/marker-tools.js/blob/master/marker-clustering/data/accidentdeath.js

     

    📌 튜터리얼 진행 중 이슈

    1) 'babel-parser', '.eslintrc' 관련  

    [eslint] Failed to load parser 'babel-parser' declared in '.eslintrc': Cannot find module 'babel-parser'

    위 와 같은 에러가 발생했고 아래와 같이 의존성 설치하여 해결했다.

    npm install eslint @babel/core @babel/eslint-parser --save-dev
    출처 : https://www.appsloveworld.com/reactjs/100/29/error-failed-to-load-parser-babel-eslint-parser-declared-in-eslintrc-js-c

     

    2) 브라우저 렌더링 버벅거림

    accidentdeath.js의 위경도 데이터가 너무 많아서 렌더링이 너무 오래 걸리거나 클릭, 스크롤 등 이벤트 발생 시 멈춰 버리기도 했다. 그래서 accidentdeath.js 코드를 약 5000줄 정도로 대폭 줄여 버렸다.

     

    📌 공식 문서

    아래 공식 문서와 공식 문서에 안내된 깃허브 자료를 활용하면 쉽게 따라 해 볼 수 있는데, marker-cluster.js와 위경도 데이터가 들어 있는 accidentdeath.js는 깃허브에서 찾으면 된다.

    728x90
    반응형
    댓글