[Main-Project] Day 9~10 - Kakao map API 현재 위치 표시, Geolocation API, 지도 확대 축소 불가 기능, 마커, 커스텀 오버레이

fejigu·2022년 11월 18일
3


📗 Pre-Project, Day 9~10

  • 유저의 현재 위치 마커로 표시하기
  • 지도 확대,축소 불가 기능 구현하기
  • 드래깅 이벤트 적용하기
  • 지도 검색창 및 현재 위치 버튼 스타일 구현
  • 주변 상인 여러개의 마커 보여주기
  • 커스텀 오버레이 구현 및 클릭 이벤트 적용하기



📗 현재 위치 가져와서 표시하기(Geolocation API)

가장 먼저, 카카오맵에서 유저의 현재 위치를 가져오고 표시하는 작업을 먼저 해줬다.

구글링을 해보니, Geolocation API이라는 것을 알아야 했다. Geolocation API는 사용자의 현재 위치를 가져오는 API로, 지도에 사용자 위치를 표시하는 등 다양한 용도로 사용할 수 있다고 한다. 또한 getCurrentPosition() 메서드를 호출해서 사용자의 현재 위치를 얻을 수 있었다.

// HTML5의 geolocation으로 사용할 수 있는지 확인합니다
		if (data) {
			ShowMultipleMarkers(map, data);
		}
		if (current) {
			let locPosition = new kakao.maps.LatLng(current.Ma, current.La); // 마커가 표시될 위치를 geolocation으로 얻어온 좌표로 생성합니다
			// 마커를 표시합니다
			displayMarker(locPosition);
			let options = {
				enableHighAccuracy: false,
			};
			navigator.geolocation.getCurrentPosition(
				function (position) {
					let lat = position.coords.latitude; // 위도
					let lon = position.coords.longitude; // 경도
					let locPosition = new kakao.maps.LatLng(lat, lon); // 마커가 표시될 위치를 geolocation으로 얻어온 좌표로 생성합니다
					if (locPosition.La !== current.La && locPosition.Ma !== current.Ma) {
						console.log(locPosition, current);
						console.log('다름');
						setCurrent(locPosition);
						// 마커를 표시합니다
						displayMarker(locPosition);
					}
				},
				null,
				options,
			);
		} else {
			let options = {
				enableHighAccuracy: false,
			};
			navigator.geolocation.getCurrentPosition(
				function (position) {
					let lat = position.coords.latitude; // 위도
					let lon = position.coords.longitude; // 경도
					let locPosition = new kakao.maps.LatLng(lat, lon); // 마커가 표시될 위치를 geolocation으로 얻어온 좌표로 생성합니다
					setCurrent(locPosition);
					// 마커를 표시합니다
					displayMarker(locPosition);
				},
				null,
				options,
			);



📗 지도 확대 축소 기능 막기(setZoomable)

→ 지도에 확대 축소 기능은 기본적으로 적용되어 있으며, 우리 또한 확대 축소 기능이 있으면 좋겠지만 백엔드 측에서 지도가 확대 축소 될때마다 섹터를 나누는 것에 한계가 있을 것 같다고 말하여 우리는 지도를 6개의 섹터로 나누기로 하였고, 확대 축소 기능은 막고 드래그만 가능하게 하기로 하였다.

UX를 고려하면 다소 아쉽지만, 동네에서 중고 책을 개인끼리 거래해주는 서비스이니 유저의 위치를 중심으로 반경 500m 내의 서적이나 상인을 보여주고 없을 경우 드래그를 하여 찾아도 크게 문제가 될 것 같지는 않다.

// 확대 축소 기능을 막습니다
		function setZoomable(zoomable: any) {
			map.setZoomable(zoomable);
		}
		setZoomable(false);

또한, 마우스를 두번 클릭했을때 확대가 되는 기능도 따라 막아줘야 했다

let mapContainer = useRef(null); // 지도를 표시할 div
	let mapOption = {
		center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
		level: 2, // 지도의 확대 레벨
		// 두번 클릭시 확대 기능을 막습니다
		disableDoubleClickZoom: true,
	};



📗 지도 드래깅 이벤트

→ 우리는 드래그로 유저가 위치를 이동시키기에 변경된 위치를 받아오기 위해서 지도 드래깅 이벤트를 구현하였다.

위와 같이 위도와 경도가 콘솔에 찍히게 해두었으며 추후에 API가 구현되면 변경된 유저의 위도와 경도를 보내고, 그 주변의 상인 정보를 받아오게 될 것이다.

// 지도 드래깅 이벤트를 등록한다 (드래그 시작 : dragstart, 드래그 종료 : dragend)
kakao.maps.event.addListener(map, 'dragend', function () {
	let centerCoord = map.getCenter();
	setCenterCoord(centerCoord);
	let message =
				'지도를 드래그 하고 있습니다. ' +
				'지도의 중심 좌표는 ' +
				centerCoord.toString() +
				' 입니다.';
		});



📗 커스텀 마커 적용하기(다른 이미지로 마커 생성하기)

→ 기본으로 제공되는 마커는 잘 보이지 않고, 인포윈도우 또한 필요없다고 생각하여 커스텀 마커를 사용하기로 하였고 인포윈도우는 제거하기로 하였다.

사용자의 현재 위치를 보여주는 마커는 따로 디자인하여 만들었고, 해당 링크를 가지고 와서 아래와 같이 사용하였다. 역시나 구현하는 방법 공식 문서를 따라 진행하였다.

→ 본인이 만든 커스텀 마커가 적용된 모습이다.

신기했던 점은 이미지를 가져올 때 import 방식으로는 되지 않았고, 아래와 같이 src 링크를 작성해야 나타났다는 것이다.

		function displayMarker(locPosition: any) {
			// 마커를 생성합니다
			let icon = new kakao.maps.MarkerImage(
				'https://velog.velcdn.com/images/fejigu/post/ffa9fea3-b632-4d69-aac0-dc807ff55ea7/image.png',
				new kakao.maps.Size(51, 55),
				{
					offset: new kakao.maps.Point(16, 34),
					alt: '현재 위치 마커',
					shape: 'poly',
					coords: '1,20,1,9,5,2,10,0,21,0,27,3,30,9,30,20,17,33,14,33',
				},
			);
			let marker = new kakao.maps.Marker({
				map: map,
				position: locPosition,
				image: icon,
			});
			// 지도 중심좌표를 접속위치로 변경합니다
			map.setCenter(locPosition);
		}
	}, [current, reset]);



📗 여러개의 마커 표시하기

→ 여러개의 마커를 표시하는 기능을 구현하는 것은 코드를 작성하는 것보다 코드를 작성하기 전까지 이해를 하고, 로직을 생각하는데 시간이 상당히 많이 걸렸던 부분이다.

"우리는 사용자의 현재 위치를 중심으로 500m 반경을 지도를 6개의 섹터로 나눠서 마커를 찍고, 각각 구역의 총 상인의 개수를 오버레이에서 숫자로 보여주는 것이다. 그리고 해당 오버레이를 클리하면 해당 상인 리스트를 보여주게 된다."

👉🏻 우리의 기능이 동작하는 방식이 헷갈리고 어떻게 로직을 짜야할 지 어려웠는데, 이 부분은 같은 팀원분과 피그마에 그려보고, 수도 코드를 작성해보며 극복하였다.
👉🏻 이 부분에서 왜 user flow를 작성해야하는지 필요성을 느꼈다. 우리 팀은 시간적은 제한도 있고 피그마에 있는 프로토타입으로 user flow를 대체할 수 있겠다고 생각했는데 한계가 있음을 느낀 것이다. 다음에는 user flow 꼼꼼하게 작성하고 들어가야겠다.


//여러개의 마커 표시하기(이 마커는 주변 상인 마커)
const ShowMultipleMarkers = (map: any, data: MarkerProps[]) => {
		let imageSrc =
			'https://velog.velcdn.com/images/fejigu/post/3917d7b1-130c-4bc8-88df-b665386adbdd/image.png';
		for (let i = 0; i < data.length; i++) {
			let view = false;
			let imageSize = new kakao.maps.Size(30, 35);
			let markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize);
			let marker = new kakao.maps.Marker({
				map: map,
				position: new kakao.maps.LatLng(
					data[i].representativeLocation.lat,
					data[i].representativeLocation.lon,
				),
				title: data[i].merchantCount,
				image: markerImage,
			});
			if (reset) {
				marker.setMap(null);
			}
			kakao.maps.event.addListener(marker, 'click', function () {
				alert('마커를 클릭했습니다!');
			});

→ 위 코드에서는 API가 아직 구현되지 않아, 프론트 측에서 임의로 작성한 더미 데이터에서 가져온 위도와 경도이다.



📗 커스텀 오버레이, 클릭 이벤트

→ 클러스터러는 지도 확대 축소가 가능할 때 더 용이하고, 우리의 상황에서는 맞지 않는다고 팀원 모두 생각하여, 커스텀 오버레이를 사용하여 클러스터러와 같은 느낌을 주고자 하였다.

커스텀 오버레이를 구현할 때 바닐라 JS로 각각의 스타일을 지정해줘야한다는 것을 헤매다가 알았다. 리액트의 소중함을 여기서 느꼈다...

유저의 주변에 있는 상인(중고서적 대여를 해주는 사람)이 얼마나 있는지 보여주는 것으로 추후에 커스텀 오버레이를 누르면 해당 상인 리스트를 보여줄 것이다. 현재는 API가 나오지 않아 커스텀 오버레이를 클릭하면 색이 변하는 클릭 이벤트만 주었다.

//커스텀 오버레이
			//커스텀 오버레이 클릭 이벤트
			let content = document.createElement('div');
			content.style.width = '100px';
			content.style.height = '100px';
			content.style.backgroundColor = '#26795D';
			content.style.opacity = '0.8';
			content.style.borderRadius = '1000px';
			content.style.fontSize = '3rem';
			content.style.color = 'white';
			content.style.display = 'flex';
			content.style.alignItems = 'center';
			content.style.justifyContent = 'center';
			content.innerText = String(data[i].merchantCount);
			content.onclick = () => {
				console.log('click');
				view = !view;
				console.log(view);
				setA(data[i]);
				//클릭시 색상 변경 일부만 안 되는 중
				content.style.backgroundColor =
					data[i].sector === A?.sector ? '#26795D' : '#124B38';
				// content.style.backgroundColor = !view ? '#124B38' : '#26795D';
			};
			let customOverlay = new kakao.maps.CustomOverlay({
				map: map,
				clickable: true, // 커스텀 오버레이 클릭 시 지도에 이벤트를 전파하지 않도록 설정한다
				content: content,
				position: new kakao.maps.LatLng(
					data[i].representativeLocation.lat,
					data[i].representativeLocation.lon,
				),
				// 커스텀 오버레이를 표시할 좌표
				xAnchor: 0.5, // 컨텐츠의 x 위치
				yAnchor: 0.7, // 컨텐츠의 y 위치
			});
			if (reset) {
				customOverlay.setMap(null);
			}
			kakao.maps.event.addListener(customOverlay, 'click', function () {
				alert('오버레이를 클릭했습니다!');
			});
		}
	};



✍🏻 회고


→ 이틀 간 시간이 어떻게 갔을 지 모를 정도로 정신 없었다. 수많은 에러와 마주하고 모두 새롭게 접하는 것이기에 검색을 하며 하나씩 구현한 것 같다.

무엇보다 카카오맵에 이벤트나 스타일을 지정하는 것이 우리가 사용하는 타입스크립트와 차이가 있어 이 부분에 있어 힘들고 해결하기 위해 많은 시간을 보냈다..

다행히 팀원들 모두 ZEP에 상주해 있으니 문제를 해결하기 위해 바로바로 소통이 가능했다. 협업에 있어 이렇게 항상 연락이 가능한 플랫폼 하나정도는 정해두는 것이 좋은 것 같다고 느꼈다.

profile
console.log(frontendjigu( ☕️, 📱); // true

0개의 댓글