[React/Typescript] 네이버 지도 API (2편) - 검색어 기반 지도 생성, 여러개의 마커 찍기, 마커 이벤트 핸들링

bible_k_·2023년 10월 31일
3

네이버 Map API

목록 보기
2/5
post-thumbnail

이 글은 React, Typescript 기반의 프로젝트에 네이버 지도 api를 적용하는 방법에 대한 포스팅입니다. api 서비스 신청/프로젝트에 연동 과정은 1편을 보고오시길 추천드립니다.

1. 타입스크립트용 navermaps 패키지 설치

https://www.npmjs.com/package/@types/navermaps

npm install --save @types/navermaps
타입스크립트에서 naver map 을 사용하기 위해 패키지를 설치해줍니다.

2. 지도 DOM 요소 지정하기

<div id="map" style="width:100%;height:400px;"></div>

웹 페이지에 지도를 삽입할 DOM 요소를 지정하고 useRef 훅을 사용하여 지도 엘리먼트를 참조합니다. 일반적으로 div요소를 사용하므로 div요소로 생성 후 HTMLDivElement로 ref 타입 정의합니다.

const mapElement = useRef<HTMLDivElement | null>(null);
...

  return (
		...
      <StyledMap id="map" ref={mapElement}></StyledMap>
		...
  );
};

3. Geocoder 서브모듈 사용

검색된 주소를 바탕으로 해당 주소의 좌표를 변환하는 과정입니다.
만약 정해진 좌표로 지도를 그린다면 이 과정은 패스하시면 됩니다.

네이버 클라우드 플랫폼 - 주소와 좌표 검색 API 사용하기

  const [AddressX, setAddressX] = useState<number>(0);
  const [AddressY, setAddressY] = useState<number>(0);
  ...
  
  useEffect(() => {
    if (searchKeyword) {
      naver.maps.Service.geocode(
        { query: searchKeyword },
        function (status, res) {
          if (res.v2.addresses.length === 0) {
            // 요청실패 (searchKeyword에 대한 응답이 없을 경우) 에러 핸들링
          } else {
            // 요청 성공에 대한 핸들링
            // 검색된 주소에 해당하는 위도, 경도를 숫자로 변환후 상태 저장
            const resAddress = res.v2.addresses[0];
            const x = parseFloat(resAddress.x);
            const y = parseFloat(resAddress.y);
            setAddressX(x);
            setAddressY(y);
          }
        }
      );
    }
  }, [searchKeyword]);

4. 지도 생성 & 마커 생성 함수 호출

지도 생성 예제

var map = new naver.maps.Map('map', {
    center: new naver.maps.LatLng(37.3595704, 127.105399),
    zoom: 10
});

3번에서 변환하여 얻은 위경도 값을 기준으로 지도를 생성해보겠습니다.

  const { naver } = window;
  let map: naver.maps.Map;
  // 지도가 이동하였을 때 가려진 부분의 마커는 숨기고 
  // 노출된 부분의 마커를 표시하는 작업을 하기 위해 map 인스턴스를 state로 관리
  const [newMap, setNewMap] = useState<naver.maps.Map | null>(null);

  ...
  
  // 중심이 될 위경도 값이 변경되면 지도를 새로 그려야하므로 
  // useEffect를 사용하고, 좌표값 +a (필요한 상태)를 의존성 배열에 추가합니다.
  
  useEffect(() => {
    if (!mapElement.current || !naver) return;

	// Map 클래스는 지도를 표현하는 클래스
    // new 연산자를 이용하여 새 인스턴스를 생성
    // 변환해놓은 좌표값을 이용하여 지도 중심 인스턴스 생성
    const center = new naver.maps.LatLng(AddressY, AddressX);
    //지도 옵션 설정
    const mapOptions: naver.maps.MapOptions = {
      //center 옵션에 생성한 지도 중심 인스턴스 넣기
      center: center,
      zoom: 12,
      minZoom: 11,
      maxZoom: 19,
      zoomControl: true,
      zoomControlOptions: {
        style: naver.maps.ZoomControlStyle.SMALL,
        position: naver.maps.Position.TOP_RIGHT,
      },
      mapDataControl: false,
      scaleControl: false,
    };
    //설정해놓은 옵션을 바탕으로 지도 생성
    map = new naver.maps.Map(mapElement.current, mapOptions);
    setNewMap(map);
    //마커 생성 함수 호출
    addMarkers();
    //검색 결과 거리순으로 재정렬하는 함수 호출
    resetListHandler();
  }, [AddressX, AddressY, totalDomData, viewportWidth]);

5. 다수의 마커 생성 및 이벤트 핸들러 등록

마커 1개 생성 예제
네이버 클라우드 플랫폼 - 마커 가이드

var marker = new naver.maps.Marker({
    position: new naver.maps.LatLng(37.3595704, 127.105399),
  	//4번에서 생성한 지도 세팅
    map: map
});

아래는 여러개의 마커를 찍는 예제입니다.
totalDataArray는 마커를 생성할 데이터 배열이며, 배열의 각 요소는 위도와 경도 값을 갖고 있다고 가정합니다.

  //마커를 담을 배열
  const createMarkerList: naver.maps.Marker[] = [];

  //반복문을 통해 데이터 배열 순회하면서 마커 생성 진행!
  const addMarkers = () => {
    for (let i = 0; i < totalDataArray.length; i++) {
      let markerObj = totalDataArray[i];
      const { dom_id, title, lat, lng } = markerObj;
      addMarker(dom_id, title, lat, lng);
    }
  };
  //마커 생성 하고 createMarkerList에 추가!!
  const addMarker = (id: string, name: string, lat: number, lng: number) => {
    try {
      let newMarker = new naver.maps.Marker({
        position: new naver.maps.LatLng(lng, lat),
        map,
        title: name,
        clickable: true,
        // icon: {
        // 커스텀 마커 생성 방법은 3편에서 계속!
        //},
      });
      newMarker.setTitle(name);
      //마커리스트에 추가
      createMarkerList.push(newMarker);
      //마커에 이벤트 핸들러 등록
      naver.maps.Event.addListener(newMarker, 'click', () =>
        markerClickHandler(id)
      );
    } catch (e) {}
  };

  //마커를 클릭했을 때 실행할 이벤트 핸들러
  const markerClickHandler = (id: string) => {
    navigate(`/ground/${id}`);
  };

⬇️ 싸커퀵 ⬇️
https://soccerquick.kr/

profile
후론트엔드 개발자

2개의 댓글

comment-user-thumbnail
2024년 4월 5일

totalDataArray는 api통해서 받아온 객체를 정리한 데이터인가요??
저도 지도에 특정 장소들을 마커로 띄우고 싶은데 어떤 api를 통해서 받아와야 하는지 어떻게 받아야하는지 구글링하는중인데 아무리 찾아도 안나오네요 ㅠㅠ
네이버 지도 api 어디서 장소에 대한 객체들을 제공하는지 알 수 있을까요?? ㅠㅠ

1개의 답글