[React] React에서 네이버 지도 API 사용하기(useRef)

김민재·2025년 8월 5일
0

1. Naver Cloud Console에서 Application 등록

Dynamic MapGeocoding(주소를 위도, 경도로 바꾸는 기능)을 선택하고,

Web 서비스 URL은 포트번호 및 URI를 제외한 호스트 도메인만을 등록한다.

로컬에서 사용하는 경우에도 http://localhost와 같이 포트 번호를 제외하고 등록해도 무방하다.

⚠️ 주의: Static Map은 Web JS를 지원하지 않는다.


2. index.html에 <script> 태그 작성

YOUR_CLIENT_ID에는 등록한 application의 client id를 넣는다. (client secret X)


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

이 스크립트를 불러오면, 브라우저는 내부적으로
window.naver 라는 전역 변수를 만들어서 여기에 네이버 지도 관련 기능들을 담는다.

대략적인 파일의 구성을 추측해보면 다음과 같다.

// 최상위 네임스페이스 생성
window.naver = window.naver || {};

// 지도 관련 네임스페이스
window.naver.maps = (function() {
  
  // 지도 객체 생성자
  function Map(container, options) {
    // 내부 초기화 코드
  }

  // 좌표 객체 생성자
  function LatLng(lat, lng) {
    this.lat = lat;
    this.lng = lng;
  }

  // 마커 객체 생성자
  function Marker(options) {
    // 내부 구현
  }

  // 여러 내부 유틸리티 함수, 이벤트 처리, 렌더링 등 복잡한 코드

  return {
    Map: Map,
    LatLng: LatLng,
    Marker: Marker,
    // 그 외 여러 클래스와 함수들
  };
})();

따라서 JavaScript 안에서 naver.maps.LatLng(...) 와 같은 형태로 여러 기능을 사용할 수 있게 된다.

여기서 naver 는 그냥 변수 이름이 아니라 네이버 지도 API의 모든 클래스, 함수, 설정이 들어 있는 큰 객체이다.

client id는 네이버 클라우드 플랫폼 console > 왼쪽 사이드바 'Maps' > Application > 인증 정보 에서 확인할 수 있다.


3. 코드 작성

먼저 기본적인 지도 생성 코드에 대해 알아보자.

1) 지도 옵션 설정하기

지도 옵션은 지도를 생성할 때 지도의 속성을 초기화하는 데 사용되며, 객체 리터럴로 만든다. 대표적으로 다음과 같이 LatLng 클래스를 통해 위도와 경도를 지정하고, 확대 정도 zoom 을 설정할 수 있다.

const mapOptions = {
    center: new naver.maps.LatLng(37.3595704, 127.105399),
    zoom: 10
}

2) 지도 생성 코드

Map 클래스는 지도를 표현하는 클래스이다. new 연산자를 이용하여 새 인스턴스를 생성한다.

const map = new naver.maps.Map('map', mapOptions);

새 인스턴스를 만들 때 두 가지 인수를 전달한다.

1. 지도를 표현할 컨테이너 요소(필수)
반드시 전달해야 하는 인수이다. 앞서 지도를 표현하기 위해 지정한 DOM 요소의 id 문자열을 직접 전달하거나, document.getElementById 메서드를 이용해 해당 DOM 요소의 참조를 전달 수 있다. 혹은 위 코드처럼 리액트에서 useRef를 활용하여 특정된 DOM 요소를 전달할 수도 있다.


2. 지도의 속성을 초기화하는 데 이용하는 지도 옵션(선택)
반드시 전달할 필요는 없다. 지도 옵션 전달 시 설정한 속성으로 지도를 초기화한다. 그렇지 않으면 NAVER 지도 API v3에서 가지고 있는 기본값으로 지도를 초기화한다.


3) 마커 표시하기

마커를 사용하려면 Marker 클래스의 객체를 생성해야 한다. 생성자에는 MarkerOptions 객체 리터럴을 인수로 넘겨서 마커의 속성을 설정해야 한다.

마커는 지도상의 한 위치를 아이콘으로 표시하는 객체이므로 위치를 나타내는 position 속성을 반드시 입력해야 한다. 그 외의 속성은 기본값을 제공한다.

var marker = new naver.maps.Marker({
    position: new naver.maps.LatLng(37.3595704, 127.105399),
    map: map
});

4) 리액트 코드

지도를 렌더링할 DOM 요소를 참조하기 위해 useRef를 사용하고, 다음과 같이 코드를 작성한다.

⚠️ 유의점

useRefHTMLElement의 타입을 지정해주어야한다. useRef의 기본 타입을 지정하지 않으면 TypeScript가 mapRef.currentnull 혹은 never로 추론하기 때문이다.

import React, { useEffect, useRef } from "react";
import styles from "./PlaceInfo.module.scss";
import locationIcon from "@/assets/filter/location.svg";
import type { TextNode } from "@/models/common.client";

interface PlaceInfoProps {
  data: TextNode;
}

const PlaceInfo: React.FC<PlaceInfoProps> = ({ data }) => {
  const mapRef = useRef<HTMLDivElement>(null);
  const lat = 37;
  const lng = 126;

  useEffect(() => {
    const { naver } = window;
    if (mapRef.current && naver) {
      const location = new naver.maps.LatLng(lat, lng);
      const map = new naver.maps.Map(mapRef.current, {
        center: location,
        zoom: 17,
      });
      new naver.maps.Marker({
        position: location,
        map,
      });
    }
  }, []);

  return (
    <div className={styles["place-info"]}>
      <section className={styles["hall"]}>
        <p className={styles["hall__title"]}>공연장 정보</p>
        <div className={styles["hall__detail"]}>
          <img className={styles["icon"]} src={locationIcon} alt="" />
          <div className={styles["hall__detail-text"]}>
            <div className={styles["hall__detail-name"]}>{data._text}</div>
            <div className={styles["hall__detail-address"]}>주소</div>
          </div>
        </div>
      </section>
      <section className={styles["location"]}>
        <p className={styles["location__title"]}>위치</p>
        <div ref={mapRef} className={styles["location__map"]}></div>
      </section>
    </div>
  );
};

export default PlaceInfo;

useEffect 내에서 naver 객체를 불러오는 부분을 중점적으로 살펴보자.

✔️ const { naver } = window: <script> 태그에서 다양한 naver map api 가 포함된 객체를 포함하는 파일을 불러왔으므로, naver 라는 객체가 전역 객체 window에 등록된 상태이다.

공식 문서에서 다양한 옵션에 대한 정보를 찾아볼 수 있다.


출처

https://inthedev.tistory.com/40
https://navermaps.github.io/maps.js.ncp/docs/tutorial-2-Getting-Started.html

profile
넓이보단 깊이있게

0개의 댓글