nextjs,react 카카오맵, 클러스터 구현하기

Jin·2022년 5월 27일
1

next.js

목록 보기
1/1
post-thumbnail

구현 배경

이번 프로젝트 주제로 부동산관련 웹서비스를 만들기로 결정을 하면서, 지도 구현이 필요하였고 그 부분을 내가 맡게 되었다. 네이버맵과 카카오맵 중 어떤것으로 할 까 고민하다 조금도 레퍼런스가 많은 카카오맵으로 선택을 하게되었다.

1. API키 발급

먼저 https://apis.map.kakao.com 에 들어가서 API키를 발급받았다.

2. 스크립트 삽입 및 지도 구현

이 부분이 생각보다 수훨히 진행되지 않았다. next.js를 처음 사용하면서 next.js 문법을 사용하고 싶었는데, script를 불러오기전에 kakao 코드들이 실행이되면서 에러가 계속 났다. 그리하여 다른 블로그를 찾아보고 아래 코드와 같이 useEffectuseState를 사용하여 로드를 해주었다.

	const [mapLoaded, setMapLoaded] = useState<boolean>(false);

	useEffect(() => {
		const $script = document.createElement("script");
		$script.async = true;
		$script.src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID}&autoload=false&libraries=services,clusterer,drawing`;
		$script.addEventListener("load", () => setMapLoaded(true));
		document.head.appendChild($script);
	}, []);

	useEffect(() => {
		if (!mapLoaded) return;
		kakao.maps.load(() => {
			const container = document.getElementById("map") as HTMLElement;
			const options = {
				center: new kakao.maps.LatLng(37.555078, 126.970702),
				level: 8,
			};
			kakaoMap.current = new kakao.maps.Map(container, options);
			const zoomControl = new kakao.maps.ZoomControl();
			kakaoMap.current.addControl(zoomControl, kakao.maps.ControlPosition.RIGHT);
			kakao.maps.event.addListener(kakaoMap.current, "idle", setCoodinate);
			setLoadMap(true);
		});
	}, [mapLoaded]);

첫번째 useEffect에서 script를 불러온 다음 setMapLoadaed를 true처리를 해주었고 mapLoad가 true가 되면 두 번째 useEffect에서 map을 불러오는 함수를 실행시킨다.
또한 지도의 좌표가 바뀔때마다 그 위치의 매물 정보를 불러오기 위해 kakao.maps.event.addListener(kakaoMap.current, "idle", setCoodinate)setCoordinate 함수를 실행시켰다.

10.17.22
pages 폴더안에 _document 파일을 만들고 여기서 script를 import 하면 간편히 해결 가능하다.

3. 클러스터 구현

https://apis.map.kakao.com/web/sample/addClustererClickEvent/ 설명을 참고하며 구현을 하였습니다.

지도위에 부동산 매물 갯수를 보여줘야하므로 클러스터를 구현하였다.

처음에는 cluster 변수를 createmakres 함수안에 넣어줬었는데, 이렇게 되버리니 createmakers 함수가 실행이 될 때 마다 클러스터가 중복으로 새롭게 생성되는 현상이 발생되었다. 그런 이유 때문에 useRef를 사용하여 cluster 변수를 최상단에서 만들어주었다.

갯수마다 클러스터의 스타일을 다르게 해주기위해 calculatorstyles 코드를 구현하였다.

const cluster = useRef<kakao.maps.MarkerClusterer>();


const createmakers = (sale: House[]) => {
		const markers = sale.map(
			(item) =>
				new kakao.maps.Marker({
					position: new kakao.maps.LatLng(item.latitude, item.longitude),
				}),
		);
		if (cluster.current !== undefined && cluster !== undefined) {
			cluster.current.setMinClusterSize(1);
			cluster.current.clear();
			cluster.current.addMarkers(markers);
		}
	};


useEffect(() => {
		if (!loadMap) return;
		cluster.current = new kakao.maps.MarkerClusterer({
			map: kakaoMap.current,
			averageCenter: true,
			calculator: [10, 30, 100, 1000],
			styles: [
				{
					background: "rgba(255, 80, 80, .8)",
					width: "3rem",
					height: "3rem",
					color: "#fff",
					borderRadius: "3rem",
					textAlign: "center",
					lineHeight: "3.3rem",
					fontSize: "1.5rem",
				},
				{
					background: "rgba(255, 80, 80, .8)",
					width: "3.5rem",
					height: "3.5rem",
					color: "#fff",
					borderRadius: "3rem",
					textAlign: "center",
					lineHeight: "4.1rem",
					fontSize: "2rem",
				},
				{
					background: "rgba(255, 80, 80, .8)",
					width: "5rem",
					height: "5rem",
					color: "#fff",
					borderRadius: "3rem",
					textAlign: "center",
					lineHeight: "5rem",
					fontSize: "2rem",
				},
				{
					background: "rgba(255, 80, 80, .8)",
					width: "6rem",
					height: "6rem",
					color: "#fff",
					borderRadius: "3rem",
					textAlign: "center",
					lineHeight: "6rem",
					fontSize: "2rem",
				},
			],
		});
		getSaleList();
	}, [loadMap]);

4. 기타

타입스크립트를 사용했기 때문에 처음에 type error가 났었다. 다른곳에서는 global interface를 선언하여 사용을 하는것을 봤는데, 처음에 그렇게 했다가 찾아보니 감사하게도 카카오맵 타입정의를 만드신분이 계셨다.
https://github.com/JaeSeoKim/kakao.maps.d.ts 여기서 설치를 한뒤 내가 필요한 부분만 조금 변경을 하여 사용하였다.

profile
내가 다시 볼려고 작성하는 블로그. 아직 열심히 공부중입니다 잘못된 내용이 있으면 댓글로 지적 부탁드립니다.

0개의 댓글