개발 프로젝트/[next.js] 지도 서비스 개발

지도에 마커 추가하기📌

jennayeo 2023. 9. 19. 18:03

마커를 그리기위해선 마커가 네이버 'map'객체에 접근할 수 있어야한다. 즉, map컴포넌트에서 만든 'map'이라는 객체를 전역상태로 공유하여 마커에서도 접근할 수 있게 만들어야한다. 

// Map.tsx
if (onLoad) {
  onLoad(map);
}

map을 만들면 onLoad함수를 이용하여 map객체를 밖으로 보낼 수 있다.

onLoad함수는 Map.tsx의 상위 컴포넌트 MapSection.tsx에서 prop으로 보내준다.

// MapSection.tsx
const MapSection = () => {
  const { initializeMap } = useMap();
  const onLoadMap = (map: NaverMap) => {
    initializeMap(map);
  };

  return (
    <>
      <Map onLoad={onLoadMap} />
      <Markers />
    </>
  );
};
export default MapSection;

onLoadMap은 SWR을 이용하여 Map을 전역상태로 관리하도록한다. 

initializeMap은 useMap이라는 hook에서 가져온다.

//useMap.ts
export const INITIAL_CENTER: Coordinates = [37.5262411, 126.99289439];
export const INITIAL_ZOOM = 10;

export const MAP_KEY = '/map';

const useMap = () => {
  const initializeMap = useCallback((map: NaverMap) => {
    mutate(MAP_KEY, map); // SWR의 내장함수 mutate를사용해 MAP_KEY라는 문자열에 네이버 맵 객체를 전역상태로 저장
  }, []);

  return {
    initializeMap,
  };
};
export default useMap;

지도가 로드되었을때 initializeMap함수가 실행되면서 map 객체는 전역상태로 저장된다.

이제 지금까지 저장해둔 전역상태를 이용하는 Markers컴포넌트를 만들어보자

//Markers.tsx
const { data: map } = useSWR<NaverMap>(MAP_KEY);
const { data: stores } = useSWR<Store[]>(STORE_KEY);

SWR에서 hook 'useSWR'을 import한다. useSWR의 인자로 MAP_KEY를 주면 전역상태로 관리되고있는 map data를 얻을 수 있다. Store key를 인자로 줬을때 매장 데이터를 얻을 수 있는것도 마찬가지다.

  //Markers.tsx
  if (!map || !stores) return null;
  return (
    <>
      {stores.map((store) => {
        return (
          <Marker
            map={map}
            coordinates={store.coordinates}
            key={store.nid}
          />
        );
      })}
    </>
  );

매장 데이터를 map돌려서 Marker컴포넌트를 불러온다.

//Marker.tsx
const Marker = ({ map, coordinates, icon, onClick }: Marker): null => {
  useEffect(() => {
    let marker: naver.maps.Marker | null = null;
    if (map) {
      marker = new naver.maps.Marker({
        map: map,
        position: new naver.maps.LatLng(...coordinates),
      });
    }

    if (onClick) {
      naver.maps.Event.addListener(marker, 'click', onClick);
    }

    return () => {
      marker?.setMap(null);
    };
  }, [map]);

  return null;
};

그럼 이제 아래와 같이 마커들이 찍힌다 타-단-