언어·프레임워크/React.js
[React.js] 네이버 지도 API 마커 클러스터 튜터리얼 따라하기!
DandyNow
2024. 2. 21. 16:52
728x90
반응형
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는 깃허브에서 찾으면 된다.
- React Naver Maps 공식 문서 마커 클러스터화 하기 : https://zeakd.github.io/react-naver-maps/examples/marker-cluster-tutorial
- 네이버 지도 API 공식 문서 마커 클러스터화 하기 : https://navermaps.github.io/maps.js.ncp/docs/tutorial-marker-cluster.example.html
728x90
반응형