gocamp - naver map api(1) / 지도 생성

ryan·2022년 8월 15일
0

지도를 얼마나 잘 활용하는지가 이번 프로젝트에서의 핵심이다. 흔히 알려진 api로는 구글맵,kakao map, naver map이 있다. 이번에는 비교적 친숙한 naver map을 사용하기로 했다.

naver map api는 html과 javascript를 바탕으로 안내가 되어 있어, react에 적용해야 하는 것도 함께 고려하면서 api 문서를 활용해야 했다.

index.html

  • 먼저 index.html에 naver cloud platform에서 앱을 등록받고 부여받은 clientId를 script에 넣어서 등록해줬다.
<html lang="en">
  <head>
    <script
      type="text/javascript"
      src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=########"
    ></script>
    <title>Go Camp</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

Map.jsx

  • Map과 관련된 정보(참조해야 할 데이터 등)를 useRef로 관리한다.
    • map api를 활용하기 위해 DOM에 접근해야 하므로, useRef를 쓴다.

  • map이라는 id에 접근한 뒤, mapOption(두 번째 인자)에 따라 다양한 설정을 해줄 수 있다.
  • 내 코드에서는 변수로 분리하지 않고 두 번째 인자에 직접 map option을 작성했다.
  • useEffect를 통해 최초 렌더링 시에 map을 생성할 수 있도록 했다.
import { useEffect, useRef } from "react";
const { naver } = window;

const Map = () => {
  const mapRef = useRef(null);
  const initialZoomLevel = 10;

  useEffect(() => {
    if (mapRef.current === null) {
      // map 생성
      mapRef.current = new naver.maps.Map("map", {
        // 맵 로드 시 최초 위치(위,경도 순으로 작성)
        center: new naver.maps.LatLng(latitude, longitude),
        // 축소할 수 있는 최대 zoom level
        minZoom: 9,
        // 맵 로드 시의 zoom level
        zoom: initialZoomLevel,
      });

  }, []);
    
  return (
    <>
      <div id="map" style={{ width: "100vw", height: "100vh" }}></div>
    </>
  );
};

export default Map;

  • 만약 내 위치를 기준으로 map을 로드하고 싶은 경우, state로 간단하게 해결할 수 있다.
  • 나의 경우 recoil을 사용했기 때문에 recoil을 기준으로 작성했다.

mapApis.js

// 위치 초기화 함수.
const setInitialLocation = (set, zoomLevel) => {
  // 브라우저에서 위치 공유를 허용한 경우, 전달 받은 setState 함수를 통해 내 위치 정보를 state에 넣는다.
  const success = (position) => {
    set({
      lat: position.coords.latitude,
      lng: position.coords.longitude,
      zoom: zoomLevel,
    });
  };
// 실패할 경우, 특정 위치의 위경도를 직접 넣어준다. 
  const failed = () => {
    set({
      lat: 37.579838,
      lng: 126.9770517,
      zoom: zoomLevel,
    });
  };
  // 브라우저 위치 공유 기능 설정
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(success, failed);
  }
};

map.jsx

  • 가독성을 위해 useEffect를 분리해줬고, mount됐을 때 작성해놓은 setInitialLocation을 통해 현재 내 위치를 초기화시킨다.
  • map을 로드하는 useEffect에서는 myLocation이라는 내 위치 state를 dependency로 넣어준 뒤, 내 위치가 설정되어 있고 map이 로드되지 않은 상황일 때 맵을 로드하는 if문을 추가했다.
  • mapOption의 center에 myLocation state 값을 넣어준다.
  • 이후 추가할 마커 관리를 위해 useRef의 값을 객체형식으로 변환해서 useRef.current.map을 통해 DOM을 관리한다.

순서
렌더링 > useEffect : setIntialLocation (내 위치 초기화) > myLocation 상태값 변경 > useEffect : 맵 로드

import { useRecoilState } from "recoil";

const Map = () => {
  const mapRef = useRef({ map: null, markerList: [], marker: null });
  const [myLocation, setMyLocation] = useRecoilState(myLocationState);
  const initialZoomLevel = 10;

  // 현재 위치 초기화
  useEffect(() => {
    setInitialLocation(setMyLocation, initialZoomLevel);
  }, []);
  
  //
  useEffect(() => {
    if (!myLocation.lat) return;
    if (mapRef.current.map === null) {
      mapRef.current.map = new naver.maps.Map("map", {
        // 내 위치 설정
        center: new naver.maps.LatLng(myLocation.lat, myLocation.lng),
        minZoom: 9,
        zoom: initialZoomLevel,
      });
    }
  }, [myLocation]);

참고자료

profile
프론트엔드 개발자

0개의 댓글