본문 바로가기
Next.js

[Next.js + Naver Map API] 보이는 지도 영역의 마커만 표시하기 (Typescript)

by 검소한달걀 2025. 2. 24.

 

표시되지 않는 부분의 마커는 지도에서 제거하여 최적화하기

 

마커 표시/숨김 함수

 

// 마커 표시 함수
const showMarker = (map: naver.maps.Map, marker: naver.maps.Marker) => {
  marker.setMap(map);
};

// 마커 숨김 함수
const hideMarker = (marker: naver.maps.Marker) => {
  marker.setMap(null);
};

 

setMap()으로 마커가 지도 위에 있으면 마커를 표시하고, 없다면 숨기는 함수 작성

 

마커 업데이트 유무 체크 함수

 

// 마커 업데이트 유무 체크
  const updateMarkers = (map: NaverMap, markers: naver.maps.Marker[]) => {
    const mapBounds = map.getBounds() as naver.maps.LatLngBounds;

    if (!mapBounds) return;

    for (let i = 0; i < markers.length; i += 1) {
      const position = markers[i].getPosition();

      if (mapBounds.hasLatLng(position)) {
        showMarker(map, markers[i]);
      } else {
        hideMarker(markers[i]);
      }
    }
  };

 

➭ 지도와 마커를 매개변수로 받음

➭ as naver.maps.LatLngBounds 로 타입 단언 (이유는 아래)

➭  getBounds()가 정확히 반환되지 않는 경우 대비

➭  getPosition() : 각 마커에 대해 마커의 현재 위치(위도, 경도)를 반환

                              반환된 값은 naver.maps.LatLng 객체로, 해당 마커의 위치를 나타냄

➭ mapBounds.hasLatLng(position) : mapBounds 범위 내에 마커 위치(position)가 포함되는지 체크

 

지도 이동 시 호출되도록 이벤트 생성

 

  useEffect(() => {
    // 줌 인아웃 시 마커 업데이트
    naver.maps.Event.addListener(mapRef.current, 'zoom_changed', () => {
      if (mapRef.current !== null) {
        updateMarkers(mapRef.current, markersRef.current);
      }
    });
    // 드래그 시 마커 업데이트
    naver.maps.Event.addListener(mapRef.current, 'dragend', () => {
      if (mapRef.current !== null) {
        updateMarkers(mapRef.current, markersRef.current);
      }
    });
  }, []);

 

결과 화면

 

 


getBounds() 타입 설정

 

// 마커 업데이트 유무 체크
  const updateMarkers = (map: NaverMap, markers: naver.maps.Marker[]) => {
    const mapBounds = map.getBounds() as naver.maps.LatLngBounds;

    if (!mapBounds) return;

    for (let i = 0; i < markers.length; i += 1) {
      const position = markers[i].getPosition();

      if (mapBounds.hasLatLng(position)) {
        showMarker(map, markers[i]);
      } else {
        hideMarker(markers[i]);
      }
    }
  };

 

mapBounds에 타입 설정을 해줘야 하는데 any를 주자니 eslint 에러가 났다.

eslint에서 규칙 off 해주면 되긴 하지만 any 타입은 되도록 지양하는 게 좋기 때문에 다른 방법으로 해결하고 싶었다.

 

const mapBounds:naver.maps.LatLngBounds = map.getBounds();

 

처음엔 naver.maps.LatLngBounds를 해봤는데 아래의 에러가 났다.

'Bounds' 형식은 'LatLngBounds' 형식에 할당할 수 없습니다.

    'PointBounds' 형식에 'LatLngBounds' 형식의 east, getNE, getSW, hasLatLng 외 4개 속성이 없습니다.ts(2322)

 

const mapBounds:naver.maps.PointBounds = map.getBounds();

 

그럼 PointBounds로 해야 되나..? 싶어서 이렇게 변경해 봤는데 이번엔 'hasLatLng'에서 에러가 ㅎㅎ

'PointBounds' 형식에 'hasLatLng' 속성이 없습니다.

 

 

그런데 공식 문서에서

 

'Map 객체는 getBounds 메서드를 제공하여 현재 화면에 표시되고 있는 지도 영역을 LatLngBounds 객체로 반환'한다는 문장이 있고,

현재 hasLatLng 위도/경도 값으로 확인을 하고 있기 때문에

as naver.maps.LatLngBounds 로 타입 단언을 해주는 것으로 처리했다.

 

 

 

* 잘못된 내용이 있다면 알려주세요 ^_^


참고

공식 문서 - 마커

[기능 구현] - 네이버 지도 api를 이용하여 지도 만들기