Leaflet 완벽 가이드 | 오픈소스 지도·마커·GeoJSON·인터랙션·실전 활용

Leaflet 완벽 가이드 | 오픈소스 지도·마커·GeoJSON·인터랙션·실전 활용

이 글의 핵심

Leaflet으로 인터랙티브 지도를 구현하는 완벽 가이드입니다. 마커, 팝업, GeoJSON, 레이어, React/Vue 통합까지 실전 예제로 정리했습니다.

실무 경험 공유: Google Maps API를 Leaflet으로 전환하면서, 비용이 100% 절감되고 커스터마이징이 자유로워진 경험을 공유합니다.

들어가며: “지도 API가 비싸요”

실무 문제 시나리오

시나리오 1: Google Maps 비용이 높아요
API 호출마다 비용이 듭니다. Leaflet은 무료 오픈소스입니다.

시나리오 2: 커스터마이징이 제한적이에요
Google Maps는 제한적입니다. Leaflet은 완전히 자유롭습니다.

시나리오 3: 오프라인 지도가 필요해요
클라우드 의존적입니다. Leaflet은 로컬 타일을 사용할 수 있습니다.


1. Leaflet이란?

핵심 특징

Leaflet은 오픈소스 JavaScript 지도 라이브러리입니다.

주요 장점:

  • 무료: 오픈소스
  • 가벼움: 42KB
  • 모바일 친화적: 터치 제스처
  • 플러그인: 수백 개의 플러그인
  • 커스터마이징: 완전한 제어

2. 설치 및 기본 사용

설치

npm install leaflet
npm install -D @types/leaflet

기본 지도

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
    <style>
      #map { height: 400px; }
    </style>
  </head>
  <body>
    <div id="map"></div>

    <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
    <script>
      const map = L.map('map').setView([37.5665, 126.9780], 13);

      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '© OpenStreetMap contributors',
      }).addTo(map);
    </script>
  </body>
</html>

3. 마커

기본 마커

import L from 'leaflet';

const map = L.map('map').setView([37.5665, 126.9780], 13);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

// 마커 추가
const marker = L.marker([37.5665, 126.9780]).addTo(map);

// 팝업
marker.bindPopup('서울특별시').openPopup();

// 커스텀 아이콘
const customIcon = L.icon({
  iconUrl: '/marker.png',
  iconSize: [32, 32],
  iconAnchor: [16, 32],
  popupAnchor: [0, -32],
});

L.marker([37.5665, 126.9780], { icon: customIcon }).addTo(map);

4. GeoJSON

const geojsonData = {
  type: 'FeatureCollection',
  features: [
    {
      type: 'Feature',
      properties: {
        name: 'Location 1',
        category: 'restaurant',
      },
      geometry: {
        type: 'Point',
        coordinates: [126.9780, 37.5665],
      },
    },
  ],
};

L.geoJSON(geojsonData, {
  onEachFeature: (feature, layer) => {
    layer.bindPopup(feature.properties.name);
  },
  pointToLayer: (feature, latlng) => {
    return L.circleMarker(latlng, {
      radius: 8,
      fillColor: '#ff7800',
      color: '#000',
      weight: 1,
      opacity: 1,
      fillOpacity: 0.8,
    });
  },
}).addTo(map);

5. React 통합

React Leaflet

npm install react-leaflet
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';

export default function Map() {
  return (
    <MapContainer
      center={[37.5665, 126.9780]}
      zoom={13}
      style={{ height: '400px', width: '100%' }}
    >
      <TileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='© OpenStreetMap contributors'
      />
      <Marker position={[37.5665, 126.9780]}>
        <Popup>서울특별시</Popup>
      </Marker>
    </MapContainer>
  );
}

6. Vue 통합

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';

const mapContainer = ref<HTMLElement>();

onMounted(() => {
  if (!mapContainer.value) return;

  const map = L.map(mapContainer.value).setView([37.5665, 126.9780], 13);

  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

  L.marker([37.5665, 126.9780])
    .addTo(map)
    .bindPopup('서울특별시')
    .openPopup();
});
</script>

<template>
  <div ref="mapContainer" style="height: 400px;"></div>
</template>

7. 이벤트

map.on('click', (e) => {
  console.log('Clicked at:', e.latlng);

  L.marker(e.latlng).addTo(map).bindPopup('You clicked here!').openPopup();
});

marker.on('click', () => {
  console.log('Marker clicked');
});

8. 플러그인

Leaflet.markercluster

npm install leaflet.markercluster
import L from 'leaflet';
import 'leaflet.markercluster';

const markers = L.markerClusterGroup();

locations.forEach((loc) => {
  const marker = L.marker([loc.lat, loc.lng]);
  markers.addLayer(marker);
});

map.addLayer(markers);

정리 및 체크리스트

핵심 요약

  • Leaflet: 오픈소스 지도 라이브러리
  • 무료: 오픈소스
  • 가벼움: 42KB
  • 모바일 친화적: 터치 제스처
  • GeoJSON: 지리 데이터
  • 플러그인: 수백 개

구현 체크리스트

  • Leaflet 설치
  • 기본 지도 구현
  • 마커 추가
  • 팝업 구현
  • GeoJSON 사용
  • React/Vue 통합
  • 플러그인 활용

같이 보면 좋은 글

  • D3.js 완벽 가이드
  • Three.js 완벽 가이드
  • GeoJSON 가이드

이 글에서 다루는 키워드

Leaflet, Maps, GeoJSON, Location, React, Vue, Frontend

자주 묻는 질문 (FAQ)

Q. Google Maps와 비교하면 어떤가요?

A. Leaflet이 무료이고 커스터마이징이 자유롭습니다. Google Maps는 더 많은 기능을 제공하지만 비쌉니다.

Q. 한국 지도를 사용할 수 있나요?

A. 네, Kakao Map, Naver Map 타일을 사용할 수 있습니다.

Q. 모바일에서 잘 작동하나요?

A. 네, 터치 제스처에 최적화되어 있습니다.

Q. 프로덕션에서 사용해도 되나요?

A. 네, 수많은 웹사이트에서 안정적으로 사용하고 있습니다.

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3