Leaflet 주소 자동완성 with Geoapify (MapLibre 예제의 부록)

발행: (2025년 12월 25일 오후 02:58 GMT+9)
15 min read
원문: Dev.to

Source: Dev.to

Leaflet 주소 자동완성 (Autocomplete) – Geoapify Companion을 이용한 MapLibre 예제

개요

이 튜토리얼에서는 Leaflet 지도에 Geoapify Companion 라이브러리를 사용해 주소 자동완성 기능을 구현하고, 그 결과를 MapLibre GL JS와 연동하는 방법을 단계별로 살펴봅니다.
Geoapify의 주소 검색 API와 Companion 플러그인을 활용하면 최소한의 코드로 강력한 검색 UI를 만들 수 있습니다.

사전 준비

  1. Geoapify API 키 – Geoapify 계정에 로그인 후 대시보드에서 키를 복사합니다.
  2. Node.js (버전 14 이상)와 npm이 설치된 환경.
  3. MapLibre GL JSLeaflet을 포함한 기본 HTML 파일.

프로젝트 구조

my-map-project/
├─ index.html
├─ style.css
├─ main.js
└─ package.json

1. 의존성 설치

npm init -y
npm install leaflet maplibre-gl @geoapify/leaflet-geocoder

2. HTML 기본 틀

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Leaflet + MapLibre 주소 자동완성</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <div id="map"></div>

  <!-- 검색 입력창 -->
  <input type="text" id="address-search" placeholder="주소를 입력하세요..." />

  <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
  <script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
  <script src="https://unpkg.com/@geoapify/leaflet-geocoder"></script>
  <script src="main.js"></script>
</body>
</html>

3. CSS 스타일링

#map { width: 100%; height: 100vh; }
#address-search {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  width: 300px;
  padding: 8px;
  z-index: 1000;
}

4. JavaScript 로직 (main.js)

// 1️⃣ Leaflet 지도 초기화
const leafletMap = L.map('map').setView([37.5665, 126.9780], 13); // 서울 중심

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; OpenStreetMap contributors'
}).addTo(leafletMap);

// 2️⃣ Geoapify Companion 설정
const geocoder = new Geoapify.Geocoder({
  apiKey: 'YOUR_GEOAPIFY_API_KEY', // ← 여기서 API 키를 입력하세요
  container: document.getElementById('address-search')
});

// 3️⃣ 검색 결과를 클릭했을 때 동작 정의
geocoder.on('select', (result) => {
  const { lat, lon } = result.properties;
  // Leaflet에 마커 추가
  L.marker([lat, lon]).addTo(leafletMap);
  // 지도 중심 이동
  leafletMap.setView([lat, lon], 15);
});

// 4️⃣ MapLibre GL JS와 연동 (선택 사항)
const mapLibre = new maplibregl.Map({
  container: 'map', // 동일한 div를 사용
  style: 'https://demotiles.maplibre.org/style.json',
  center: [126.9780, 37.5665],
  zoom: 13
});

// Leaflet과 MapLibre를 동기화 (필요 시)
leafletMap.on('move', () => {
  const center = leafletMap.getCenter();
  mapLibre.setCenter([center.lng, center.lat]);
});

5. 동작 확인

  1. npm run start 혹은 간단히 Live Server 확장 프로그램을 이용해 index.html을 브라우저에서 열어 주세요.
  2. 검색창에 주소를 입력하면 Geoapify가 자동완성 제안을 표시합니다.
  3. 원하는 결과를 클릭하면 Leaflet 지도에 마커가 표시되고, 동시에 MapLibre 지도도 같은 위치로 이동합니다.

팁 & 트러블슈팅

상황해결 방법
검색 결과가 나타나지 않음API 키가 올바른지, 그리고 CORS 설정이 허용되어 있는지 확인합니다.
마커가 중복 표시기존 마커를 저장한 뒤, 새 검색이 들어올 때 remove() 메서드로 삭제하고 다시 추가합니다.
MapLibre와 Leaflet이 서로 다른 좌표 체계를 사용두 라이브러리 모두 WGS84(위도/경도) 좌표를 사용하므로, lat, lng 순서에 주의합니다.
모바일에서 입력창이 가려짐CSS z-indexposition 값을 조정해 입력창이 최상위에 오도록 합니다.

마무리

Geoapify Companion 플러그인을 활용하면 LeafletMapLibre 사이에서 매끄러운 주소 검색 경험을 손쉽게 구현할 수 있습니다.
필요에 따라 결과를 GeoJSON 형태로 받아와 커스텀 레이어에 표시하거나, 거리 계산 등 추가 기능을 확장해 보세요.

추가 자료

즐거운 코딩 되세요! 🚀

주소 자동완성 예제의 Leaflet 버전

MapLibre GL 튜토리얼을 보셨다면, 이 예제는 동일한 UX 패턴을 따릅니다: 사용자가 주소를 검색하고 마커가 있는 인터랙티브 지도에서 확인할 수 있습니다.

사용된 API

🧭 목차

Step 1: Leaflet 지도 설정

Leaflet을 로드하고 Geoapify 래스터 타일을 사용해 지도를 초기화합니다.

Leaflet 포함

CDN에서 CSS와 JavaScript를 추가합니다:

지도 컨테이너 만들기

컨테이너 스타일 지정

html, body, #map {
  width: 100%;
  height: 100%;
  margin: 0;
}

지도 초기화

const myAPIKey = "YOUR_API_KEY";

const map = L.map("map", { zoomControl: false }).setView(
  [38.908838755401035, -77.02346458179596], // 워싱턴 DC
  12
);

// Retina 디스플레이는 다른 타일 품질이 필요합니다
const isRetina = L.Browser.retina;

const baseUrl   = "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}.png?apiKey={apiKey}";
const retinaUrl = "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}@2x.png?apiKey={apiKey}";

L.tileLayer(isRetina ? retinaUrl : baseUrl, {
  attribution: 'Powered by [Geoapify](https://www.geoapify.com/) | © OpenMapTiles © OpenStreetMap contributors',
  apiKey: myAPIKey,
  maxZoom: 20
}).addTo(map);

// 오른쪽 하단에 줌 컨트롤 추가
L.control.zoom({ position: "bottomright" }).addTo(map);

Note: Leaflet은 래스터(PNG) 타일을 사용하고, MapLibre는 벡터 타일을 사용합니다. Geoapify는 두 형식 모두 제공합니다. @2x 타일은 Retina 디스플레이용입니다.

🔑 API Key: 무료 API 키를 받으려면 가입하세요.

Leaflet map centered on Washington DC with zoom controls
Geoapify 래스터 타일을 사용해 초기화된 Leaflet 지도.

2단계: 주소 자동완성 필드 추가

자동완성 설정은 MapLibre 예제와 동일합니다.

Geocoder Autocomplete 라이브러리 포함

자동완성 컨테이너 만들기


  
.autocomplete-panel {
  position: absolute;
  top: 10px;
  left: 10px;
  width: 400px;
  z-index: 1002;
}

자동완성 위젯 초기화

const autocompleteInput = new autocomplete.GeocoderAutocomplete(
  document.getElementById("autocomplete"),
  myAPIKey,
  { /* options */ }
);

GeocoderAutocomplete 위젯은 사용 중인 지도 라이브러리에 관계없이 동일하게 작동합니다.

Leaflet 지도 위에 제안이 표시된 주소 자동완성 드롭다운
사용자가 입력할 때 자동완성 드롭다운이 표시됩니다.

Step 3: Leaflet 지도와 선택 동기화

사용자가 주소를 선택하면 지도를 이동(pan)하고 마커를 표시합니다.

사용자 정의 마커 아이콘 만들기

Geoapify Map Marker Icon API를 사용하여 사용자 정의 핀을 생성합니다:

const markerIcon = L.icon({
  iconUrl: `https://api.geoapify.com/v1/icon/?type=awesome&color=%232ea2ff&size=large&scaleFactor=2&apiKey=${myAPIKey}`,
  iconSize: [38, 56],
  iconAnchor: [19, 51],
  popupAnchor: [0, -60]
});

iconAnchor는 아이콘의 어느 지점이 마커 좌표에 해당하는지를 정의합니다.

선택 시 마커 추가

let marker; // will hold the current marker

autocompleteInput.on("select", (place) => {
  const { lat, lon } = place.properties;

  // Pan the map to the selected location
  map.setView([lat, lon], 15);

  // Remove previous marker, if any
  if (marker) {
    map.removeLayer(marker);
  }

  // Add new marker
  marker = L.marker([lat, lon], { icon: markerIcon }).addTo(map);
});

이제 지도는 선택한 주소를 자동으로 중심에 맞추고 사용자 정의 마커를 표시합니다.

Step 4: 데모 살펴보기

전체 HTML/JS 코드를 파일(예: leaflet-autocomplete.html)에 복사하고 브라우저에서 엽니다.
다음이 표시됩니다:

  1. 전체 화면 Leaflet 지도.
  2. 왼쪽 상단에 자동완성 입력창.
  3. 실시간 주소 제안.
  4. 주소를 선택하면 자동으로 팬 이동하고 사용자 지정 마커가 표시됩니다.

Summary

  • Leaflet + Geoapify raster tiles → 간단하고 가벼운 지도.
  • Address Autocomplete API는 즉각적인 제안을 제공합니다.
  • Map Marker Icon API를 사용하면 디자인에 맞게 마커 스타일을 지정할 수 있습니다.
  • 동일한 자동완성 위젯이 다양한 지도 라이브러리에서 작동하므로 Leaflet, MapLibre, Mapbox GL 등으로 쉽게 전환할 수 있습니다.

FAQ

Q: 래스터 타일에 유료 플랜이 필요합니까?
A: 아니요. 무료 티어에는 월별로 충분히 많은 래스터 타일 요청이 포함됩니다.

Q: 마커 색상을 변경할 수 있나요?
A: 예. 아이콘 URL의 color 파라미터를 조정하세요 (16진수 값, 예: 빨간색은 %23ff0000).

Q: 자동완성 결과를 특정 국가로 제한하려면 어떻게 해야 하나요?
A: 위젯을 초기화할 때 filter 옵션을 전달하세요, 예: { filter: "countrycode:us" }.

Q: 다른 지도 스타일을 사용하고 싶다면 어떻게 해야 하나요?
A: baseUrl/retinaUrl을 다른 Geoapify 스타일로 교체하세요 (예: osm-dark, osm-light).

Feel free to experiment and adapt the code to your own project!

Note: 핀 아이콘의 경우, 이것은 하단 끝부분 근처에 있어야 합니다.

선택 이벤트 처리

let marker;

autocompleteInput.on("select", (location) => {
  // Remove existing marker
  if (marker) {
    marker.remove();
  }

  if (location) {
    // Add marker at the selected location
    marker = L.marker([location.properties.lat, location.properties.lon], {
      icon: markerIcon
    }).addTo(map);

    // Pan to the selected location
    map.panTo([location.properties.lat, location.properties.lon]);
  }
});

참고: Leaflet은 [lat, lon]을 사용하고 MapLibre는 [lon, lat]을 사용합니다.

선택된 주소 위치에 마커가 표시된 Leaflet 지도

주소를 선택하면 지도는 해당 위치로 이동하고 마커를 표시합니다.

단계 4: 데모 탐색

The live CodePen demo shows the complete implementation.

다음 흐름을 시도해 보세요

  • 주소 입력 → 드롭다운에서 선택 → 지도 이동 및 마커 표시
  • 다른 테마 시도 → 테마 선택기를 사용해 라이트/다크 모드 전환

테마 전환기

데모에는 자동완성 스타일과 지도 타일을 모두 전환하는 테마 선택기가 포함되어 있습니다:

const mapTiles = {
  light: {
    baseUrl: "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}.png?apiKey={apiKey}",
    retinaUrl: "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}@2x.png?apiKey={apiKey}"
  },
  dark: {
    baseUrl: "https://maps.geoapify.com/v1/tile/dark-matter-brown/{z}/{x}/{y}.png?apiKey={apiKey}",
    retinaUrl: "https://maps.geoapify.com/v1/tile/dark-matter-brown/{z}/{x}/{y}@2x.png?apiKey={apiKey}"
  }
};

역지오코딩이 필요하신가요?

지도에서 클릭하여 주소를 얻는 클릭‑투‑주소 기능은 MapLibre GL 튜토리얼을 참고하세요.
같은 Reverse Geocoding API 호출을 Leaflet에서도 사용할 수 있습니다—MapLibre 마커 코드를 Leaflet의 L.marker()로 교체하면 됩니다.

👉 인터랙티브 데모에서 직접 사용해 보세요.

요약

Leaflet 지도와 주소 자동완성을 구축했습니다:

  • Leaflet 지도 – 레티나 지원이 포함된 래스터 타일
  • 주소 자동완성 – MapLibre와 동일한 Geoapify 위젯
  • 맞춤 마커 – Marker Icon API 사용

MapLibre와의 주요 차이점

  • Leaflet은 래스터(PNG) 타일을 사용하고, MapLibre는 벡터 타일을 사용합니다.
  • 좌표 순서: Leaflet은 [lat, lon], MapLibre는 [lon, lat]입니다.
  • 마커 생성 방식: L.marker() vs. maplibregl.Marker().

유용한 링크

FAQ

Q: Leaflet과 MapLibre의 차이점은 무엇인가요?
A: Leaflet은 래스터(PNG) 타일을 사용하고 가볍습니다. MapLibre는 벡터 타일을 사용하며 3D를 지원하고 부드러운 줌을 제공합니다. 두 라이브러리 모두 Geoapify API와 잘 작동합니다.

Q: 자동완성 결과를 특정 국가로 제한하려면 어떻게 해야 하나요?
A: filter 옵션에 countrycode, rect(바운딩 박스), circle 파라미터를 사용합니다. 예시:

filter: { countrycode: ["us", "ca"] }

미국과 캐나다로 결과를 제한합니다. 자세한 내용은 Address Autocomplete API docs를 참고하세요.

Q: React나 Angular에서 자동완성을 사용할 수 있나요?
A: 네. 전용 래퍼 라이브러리가 제공됩니다:

Q: 코딩하기 전에 API를 직접 시험해볼 수 있나요?
A: 인터랙티브 플레이그라운드를 이용하세요:

지금 사용해 보세요

👉 라이브 데모 열기

geoapify.com에 가입하고 무료 API 키를 받아 주소 자동완성이 포함된 Leaflet 지도 만들기를 시작하세요.

Back to Blog

관련 글

더 보기 »