프로젝트

네이버 지도 API를 활용해 보았다 - 지도 띄우기

Meoui 2024. 7. 21. 03:56

교내 동아리에서 약 1년 ~ 1년 반에 걸쳐 진행했던 쩝쩝박사 프로젝트가 마무리되었다. 그중 내가 맡았던 지도 기능에 대한 글이다.

 

우선 지도에 초점을 두어 필요한 기능을 나열하면 아래와 같다.

 

1️⃣ 네이버 지도 띄우기

2️⃣ 마커 표시하기 및 강조하기
3️⃣ 사이드네비와 지도의 이벤트 연동
4️⃣ 마커 클러스터화하기

 

그러면 이제 지도부터 띄워보자.

 

패키지 및 스크립트 추가

1.패키지 설치

타입이 정의된 패키지가 몇 가지 없었는데 그 중 가장 이용자가 많은 패키지로 설치하였다.

yarn add @types/navermaps

 

2.script 태그 주가

발급받은 `client_id`를 환경 변수에 따로 관리하도록 형식을 변형해 index.html의 script 태그에 추가하면 기본 설정은 끝이다.

<script type="text/javascript" src="[https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=%REACT\_APP\_NAVER\_MAPS\_CLIENT\_ID%](https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=%REACT_APP_NAVER_MAPS_CLIENT_ID%)">
</script>

 

지도 구현하기

`useNaverMap` 이라는 커스텀 훅 형식으로 구현하였다. 이때, 사용자의 현재 위치를 기반으로 지도를 나타내기 때문에 현재 위칫값이 들어 있는 `location`을 props값으로 넘겨주었다.

const { location, loading } = useLocation();
const map = useNaverMap(location?.lat, location?.lng);

 

공식 문서를 참고하여 UI 상 필요 없는 옵션들을 제거하였다. 추가로 메모리 누수 방지를 위해 클린업 함수 부분에 지도를 제거하는 `destroy` 메소드를 추가해 주었다.

import { useEffect, useState } from 'react';

function useNaverMap(latitude: number | undefined, longitude: number | undefined) {
  const [map, setMap] = useState<naver.maps.Map | null>(null);

  useEffect(() => {
    if (!map && latitude && longitude) {
      const newMaps = new naver.maps.Map('map', {
        center: new naver.maps.LatLng(latitude, longitude),
        zoomControl: false,
        zoom: 17,
        scaleControl: false,
        mapDataControl: false,
      });
      setMap(newMaps);

      return () => {
        newMaps.destroy();
      };
    }
  }, [latitude, longitude]);

  return map;
}

export default useNaverMap;
import { ReactComponent as LoadingIcon } from 'assets/svg/home/map-loading.svg';
import { useLocation } from 'store/location';
import useNaverMap from 'utils/hooks/useNaverMap';

import styles from './Map.module.scss';

export default function Map(): JSX.Element {
	const { location, loading } = useLocation();
  const map = useNaverMap(location?.lat, location?.lng);

  return (
    <div id="map" className={styles.map}>
      {loading && <div className={styles.loading}><LoadingIcon /></div>}
    </div>
  );
}

이 당시에 팀원들과 함께 커스텀 훅을 통해 로직과 컴포넌트를 분리하는 시도를 많이 했었는데 지금 생각해 보면 재사용성을 고려하지 않고 너무 무지성 커스텀 훅으로 만든 것은 아닐까라는 생각도 든다.🤔(지도, 마커, 마커 클러스터링 모든 게 다 커스텀 훅~)

 

위의 코드를 기반으로 메인 페이지에 사용자의 현재 위칫값에 따라 지도가 렌더링된다.

결과물

 

참고 사이트


벨로그를 썼다가 카테고리 분리가 불편해서 다시 티스토리로 이전했다.(사실 몇 번 써보지도 않음..ㅎ)

이제 진짜 열심히 블로그 운영해 보겠다!!