Naver Map API (feat. 리액트 타입스크립트)

HYUK·2023년 6월 6일
1

1. 구현내용

1-1 data POST

  • 게시물 포스팅시 지도위에 마커버튼을 찍어 공유하고자 하는 위치의 위도, 경도값을 데이터베이스로 전송한다.

  • 마커버튼은 하나만 찍을 수 있다.

1-2 data GET

  • 작성된 게시물에서 위도, 경도 데이터를 받아와 지도상에 마커버튼이 표시 될 수 있도록 구현 하였다.

2. 구현과정

2-1. 공통사항

2-1-1. 클라이언트 아이디 발급

먼저 네이버 지도 api를 구현하기 위해서는 클라이언트 아이디를 발급받아야 하는데 클라이언트 아이디 발급까지는 전혀 어려울게 없었다 참고자료도 많고 과정자체가 어려울게 없었다.

2-1-2. 라이브러리 설치

그리고 라이브러리 설치를 해야하는데 타입스크립트를 쓰고있기 때문에 라이이브러리 설치는 npm install --save @types/navermaps를 설치하였다.

2-1-3. index.html

indext.html 파일에 script단을 하나 추가를 해줘야 하며 내용은 아래와 같다.

<script
      type="text/javascript"
      src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId=%REACT_APP_NAVER_CLIENT_ID%"
    ></script>

위 내용에서 보면 네이버에서 src 부분에 clientId가 추가되는걸 볼수가 있을것이다. 추가된 내용은 보이는 내용처럼 .env파일로 관리되고 있다. clientId는 보안 이슈로 .env 파일로 관리해주는것을 권장한다.
그리고 여기서 네이버 공식문서를 보고서 html에 js코드를 그대로 따라 작성하는 경우가 있는데 React는 SPA이다 그렇기 때문에 index.html에 작성하게되면 모든 페이지에서 지도가 딸려오기 때문에 이렇게 구현해서는 안된다.

2-2. 페이지에 지도 렌더링 및 마커버튼 찍기

2-2-1. 지도 렌더링 및 마커버튼

위의 내용까지 모두 준비되었다면 네이버 지도 API를 이용하기위한 모든 준비과정은 끝났다. 이제 특정컴포넌트에서 지도를 렌더링 시킬것이다.

import { useEffect, useRef } from 'react';
import * as S from './NaverMap.styles';

interface Props {
  setMarkerPosition: React.Dispatch<
    React.SetStateAction<{ x: number; y: number }>
  >;
}

export default function NaverMap({ setMarkerPosition }: Props) {
  const mapElement = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const { naver } = window;
    // Naver 지도 API를 로드하지 못한 경우 해당 함수의 실행을 중지하고 종료함으로서 에러방지
    if (!naver) return;

    // 현재 위치 가져오기
    navigator.geolocation.getCurrentPosition(
      position => {
        const { latitude, longitude } = position.coords;
     //position.coords 객체에서 latitude와 longitude 속성을 추출하여 latitude와 longitude 변수에 할당
        const currentPosition = new naver.maps.LatLng(latitude, longitude);

        const mapOptions = {
          center: currentPosition, // 현재 위치를 중심으로 설정
          zoom: 17,
          zoomControl: true,
          zoomControlOptions: {
            position: naver.maps.Position.TOP_RIGHT,
          },
        };

        const map = new naver.maps.Map(mapElement.current!, mapOptions);
        let marker: naver.maps.Marker | null = null;

        // 클릭 이벤트 리스너 추가
        naver.maps.Event.addListener(map, 'click', e => {
          const clickedLocation = e.coord;

          // 기존 마커가 존재하는 경우 위치를 업데이트
          if (marker) {
            marker.setPosition(clickedLocation);
          } else {
            // 클릭된 위치에 새로운 마커 생성
            marker = new naver.maps.Marker({
              position: clickedLocation,
              map: map,
            });
          }

          setMarkerPosition(clickedLocation);
        // state 값으로 관리되고 있는 위도, 경도값이 클릭이벤트 작동시 변경
        });
      },
      error => {
        console.error(error);
      }
    );
  }, []);

  return <S.Map ref={mapElement} /> // 사이즈 스타일 적용을 해줘야 페이지에서 보임
}

2-3 위도, 경도값을 받아와 새로운 위치정보 표시

2-3-1. 새로운 위치정보 반영

이번에는 위에서 작성된 위도, 경도값을 이용하여 새로운 페이지에서 새로운 위치정보를 반영시켜 보여줄것이다.
위에 과정과 크게 다를게 없고 오히려 더 간단하다.


import { useEffect, useRef } from 'react';
import * as S from './Map.style';

interface PostingData {
  feedContent: string;
  feedCreateTime: string;
  feedImages: { imageId: number; imageUrl: string }[];
  feedLikeCount: string;
  feedScrapCount: string;
  feedTitle: string;
  postId: number;
  userFeedLike: boolean;
  userFeedScrap: boolean;
  userName: string;
  userProfileImage: string;
  x: string;
  y: string;
}

interface CommentListProps {
  postingData: PostingData[];
}

export default function Map({ postingData }: CommentListProps) {
  const x = Number(postingData[0].x);
  const y = Number(postingData[0].y);
  // 데이터베이스에서 받아온 위치정보를 변수에 저장

  const mapElement = useRef(null);
  useEffect(() => {
    const { naver } = window;
    if (!mapElement.current || !naver) return;
    // 지도에 표시할 위치의 위도와 경도 좌표를 파라미터로 넣어준다.
    const location = new naver.maps.LatLng(y, x);
    const mapOptions: naver.maps.MapOptions = {
      center: location,
      zoom: 17,
      zoomControl: true,
      zoomControlOptions: {
        position: naver.maps.Position.TOP_RIGHT,
      },
    };
    const map = new naver.maps.Map(mapElement.current, mapOptions);
    new naver.maps.Marker({
      position: location,
      map,
    });
  }, []);
  return <S.Map ref={mapElement} />;
}

3. 정리

지금까지 Naver Map API를 이용하여 지도 표현및 한개의 마커를 찍어 특정 위도, 경도를 가져오는 기능을 구현해 보았다. 네이버 공식문서를 보면 당장 이러한 기능말고도 다양한 기능들이 많다. 다음번에는 입력한 주소를 위도,경도로 변환하여 지도에 마커버튼으로 구현(Reverse Geocoding API)하는 기능을 도전해 보려한다.

profile
step by step

0개의 댓글