Skip to content

마커 표시하기

이 페이지에서는 다양한 마커 사용법을 예제와 함께 설명합니다.

라이브 데모

기본 마커

가장 간단한 마커 표시 방법입니다:

tsx
import { NaverMap, Marker, NaverMapProvider } from "react-naver-maps-kit";

function BasicMarker() {
  return (
    <NaverMapProvider ncpKeyId={import.meta.env.VITE_NCP_KEY_ID}>
      <NaverMap
        center={{ lat: 37.5665, lng: 126.978 }}
        zoom={14}
        style={{ width: "100%", height: "500px" }}
      >
        <Marker position={{ lat: 37.5665, lng: 126.978 }} title="서울시청" />
      </NaverMap>
    </NaverMapProvider>
  );
}

필수 Props

Prop타입설명
position{ lat, lng }마커 위치 (필수)

자주 사용하는 Props

tsx
<Marker
  position={{ lat: 37.5665, lng: 126.978 }}
  title="툴팁 텍스트"
  clickable={true}
  draggable={true}
  visible={true}
  zIndex={100}
/>

마커 이벤트

마커 클릭, 드래그 등의 이벤트를 처리합니다:

tsx
import { useState } from "react";
import { NaverMap, Marker, NaverMapProvider } from "react-naver-maps-kit";

function MarkerWithEvents() {
  const [selectedPosition, setSelectedPosition] = useState(null);

  return (
    <div>
      <NaverMapProvider ncpKeyId={import.meta.env.VITE_NCP_KEY_ID}>
        <NaverMap
          center={{ lat: 37.5665, lng: 126.978 }}
          zoom={14}
          style={{ width: "100%", height: "400px" }}
        >
          <Marker
            position={{ lat: 37.5665, lng: 126.978 }}
            draggable
            onClick={(e) => {
              console.log("마커 클릭!", e.coord);
              setSelectedPosition(e.coord);
            }}
            onDragEnd={(e) => {
              console.log("새 위치:", e.coord);
              setSelectedPosition(e.coord);
            }}
          />
        </NaverMap>
      </NaverMapProvider>

      {selectedPosition && (
        <p>
          선택된 위치: {selectedPosition.lat.toFixed(4)}, {selectedPosition.lng.toFixed(4)}
        </p>
      )}
    </div>
  );
}

사용 가능한 이벤트

이벤트설명
onClick클릭
onDblClick더블 클릭
onRightClick우클릭
onMouseDown / onMouseUp마우스 누름/뗌
onMouseOver / onMouseOut마우스 오버/아웃
onDragStart / onDrag / onDragEnd드래그 시작/진행/종료

커스텀 마커 (React 컴포넌트)

children으로 React 컴포넌트를 마커 아이콘으로 사용합니다:

tsx
import { NaverMap, Marker, NaverMapProvider } from "react-naver-maps-kit";

function CustomMarkerExample() {
  return (
    <NaverMapProvider ncpKeyId={import.meta.env.VITE_NCP_KEY_ID}>
      <NaverMap
        center={{ lat: 37.5665, lng: 126.978 }}
        zoom={14}
        style={{ width: "100%", height: "500px" }}
      >
        {/* 커스텀 스타일 마커 */}
        <Marker position={{ lat: 37.5665, lng: 126.978 }}>
          <div
            style={{
              padding: "8px 16px",
              background: "#03C75A",
              color: "white",
              borderRadius: "20px",
              fontWeight: "bold",
              boxShadow: "0 2px 6px rgba(0,0,0,0.3)"
            }}
          >
            네이버
          </div>
        </Marker>

        {/* 이모지 마커 */}
        <Marker position={{ lat: 37.568, lng: 126.978 }}>
          <div style={{ fontSize: "32px" }}>📍</div>
        </Marker>

        {/* 이미지 마커 */}
        <Marker position={{ lat: 37.565, lng: 126.978 }}>
          <img src="/marker-icon.png" alt="마커" style={{ width: 40, height: 40 }} />
        </Marker>
      </NaverMap>
    </NaverMapProvider>
  );
}

앵커 포인트 설정

커스텀 마커의 중심점을 조정합니다:

tsx
<Marker
  position={{ lat: 37.5665, lng: 126.978 }}
  icon={{
    content: `<div style="font-size: 32px">📍</div>`,
    anchor: new naver.maps.Point(16, 32) // 하단 중앙
  }}
/>

여러 마커 표시

배열 데이터로 여러 마커를 렌더링합니다:

tsx
import { useState } from "react";
import { NaverMap, Marker, NaverMapProvider } from "react-naver-maps-kit";

const locations = [
  { id: 1, name: "서울역", lat: 37.5547, lng: 126.9707 },
  { id: 2, name: "강남역", lat: 37.4981, lng: 127.0276 },
  { id: 3, name: "잠실역", lat: 37.5133, lng: 127.1 },
  { id: 4, name: "홍대입구역", lat: 37.5572, lng: 126.9245 },
  { id: 5, name: "신촌역", lat: 37.5551, lng: 126.9368 }
];

function MultipleMarkers() {
  const [selected, setSelected] = useState(null);

  return (
    <div>
      <NaverMapProvider ncpKeyId={import.meta.env.VITE_NCP_KEY_ID}>
        <NaverMap
          center={{ lat: 37.54, lng: 126.98 }}
          zoom={12}
          style={{ width: "100%", height: "500px" }}
        >
          {locations.map((loc) => (
            <Marker
              key={loc.id}
              position={{ lat: loc.lat, lng: loc.lng }}
              title={loc.name}
              onClick={() => setSelected(loc)}
            />
          ))}
        </NaverMap>
      </NaverMapProvider>

      {selected && (
        <div className="info-panel">
          <h3>{selected.name}</h3>
          <p>위도: {selected.lat}</p>
          <p>경도: {selected.lng}</p>
        </div>
      )}
    </div>
  );
}

마커 애니메이션

마커에 애니메이션을 적용합니다:

tsx
import { NaverMap, Marker, NaverMapProvider } from "react-naver-maps-kit";

function AnimatedMarker() {
  return (
    <NaverMapProvider ncpKeyId={import.meta.env.VITE_NCP_KEY_ID}>
      <NaverMap
        center={{ lat: 37.5665, lng: 126.978 }}
        zoom={14}
        style={{ width: "100%", height: "500px" }}
      >
        <Marker position={{ lat: 37.5665, lng: 126.978 }} animation={naver.maps.Animation.BOUNCE} />

        <Marker position={{ lat: 37.568, lng: 126.978 }} animation={naver.maps.Animation.DROP} />
      </NaverMap>
    </NaverMapProvider>
  );
}

애니메이션 타입

애니메이션설명
BOUNCE계속 통통 튐
DROP위에서 떨어짐 (1회)

Ref로 마커 제어

Ref를 통해 마커를 직접 제어합니다:

tsx
import { useRef, useState } from "react";
import { NaverMap, Marker, NaverMapProvider, type MarkerRef } from "react-naver-maps-kit";

function MarkerWithRef() {
  const markerRef = useRef<MarkerRef>(null);
  const [position, setPosition] = useState({ lat: 37.5665, lng: 126.978 });

  const moveMarker = () => {
    const newPos = {
      lat: 37.5665 + (Math.random() - 0.5) * 0.01,
      lng: 126.978 + (Math.random() - 0.5) * 0.01
    };
    markerRef.current?.setPosition(newPos);
    setPosition(newPos);
  };

  const getMarkerInfo = () => {
    const pos = markerRef.current?.getPosition();
    console.log("현재 위치:", pos);
  };

  return (
    <div>
      <NaverMapProvider ncpKeyId={import.meta.env.VITE_NCP_KEY_ID}>
        <NaverMap center={position} zoom={14} style={{ width: "100%", height: "400px" }}>
          <Marker ref={markerRef} position={position} draggable />
        </NaverMap>
      </NaverMapProvider>

      <div style={{ marginTop: "1rem" }}>
        <button onClick={moveMarker}>랜덤 이동</button>
        <button onClick={getMarkerInfo}>위치 확인</button>
      </div>
    </div>
  );
}

대량 마커와 클러스터링

수십 개 이상의 마커는 MarkerClusterer를 사용하세요. 자세한 내용은 마커 클러스터링을 참조하세요.

tsx
import { NaverMap, Marker, MarkerClusterer, NaverMapProvider } from "react-naver-maps-kit";

// 100개의 랜덤 마커
const markers = Array.from({ length: 100 }, (_, i) => ({
  id: i,
  lat: 37.5 + Math.random() * 0.1,
  lng: 126.9 + Math.random() * 0.1
}));

function ClusteredMarkers() {
  return (
    <NaverMapProvider ncpKeyId={import.meta.env.VITE_NCP_KEY_ID}>
      <NaverMap
        center={{ lat: 37.55, lng: 126.95 }}
        zoom={12}
        style={{ width: "100%", height: "500px" }}
      >
        <MarkerClusterer>
          {markers.map((m) => (
            <Marker key={m.id} clustererItemId={m.id} position={{ lat: m.lat, lng: m.lng }} />
          ))}
        </MarkerClusterer>
      </NaverMap>
    </NaverMapProvider>
  );
}

마커와 InfoWindow 연동

마커 클릭 시 정보 창을 표시합니다:

tsx
import { useState } from "react";
import { NaverMap, Marker, InfoWindow, NaverMapProvider } from "react-naver-maps-kit";

const places = [
  { id: 1, name: "서울역", lat: 37.5547, lng: 126.9707, desc: "서울의 중심 역" },
  { id: 2, name: "강남역", lat: 37.4981, lng: 127.0276, desc: "유동인구 최다 역" }
];

function MarkerWithInfoWindow() {
  const [selected, setSelected] = useState(null);

  return (
    <NaverMapProvider ncpKeyId={import.meta.env.VITE_NCP_KEY_ID}>
      <NaverMap
        center={{ lat: 37.52, lng: 127.0 }}
        zoom={12}
        style={{ width: "100%", height: "500px" }}
      >
        {places.map((place) => (
          <Marker
            key={place.id}
            position={{ lat: place.lat, lng: place.lng }}
            onClick={() => setSelected(place)}
          />
        ))}

        {selected && (
          <InfoWindow
            position={{ lat: selected.lat, lng: selected.lng }}
            visible
            onCloseClick={() => setSelected(null)}
          >
            <div style={{ padding: "10px" }}>
              <strong>{selected.name}</strong>
              <p>{selected.desc}</p>
            </div>
          </InfoWindow>
        )}
      </NaverMap>
    </NaverMapProvider>
  );
}

다음 단계

Released under the MIT License.