Leaflet 주소 자동완성 with Geoapify (MapLibre 예제의 부록)
Source: Dev.to
Leaflet 주소 자동완성 (Autocomplete) – Geoapify Companion을 이용한 MapLibre 예제
개요
이 튜토리얼에서는 Leaflet 지도에 Geoapify Companion 라이브러리를 사용해 주소 자동완성 기능을 구현하고, 그 결과를 MapLibre GL JS와 연동하는 방법을 단계별로 살펴봅니다.
Geoapify의 주소 검색 API와 Companion 플러그인을 활용하면 최소한의 코드로 강력한 검색 UI를 만들 수 있습니다.
사전 준비
- Geoapify API 키 – Geoapify 계정에 로그인 후 대시보드에서 키를 복사합니다.
- Node.js (버전 14 이상)와 npm이 설치된 환경.
- MapLibre GL JS와 Leaflet을 포함한 기본 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: '© 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. 동작 확인
npm run start혹은 간단히 Live Server 확장 프로그램을 이용해index.html을 브라우저에서 열어 주세요.- 검색창에 주소를 입력하면 Geoapify가 자동완성 제안을 표시합니다.
- 원하는 결과를 클릭하면 Leaflet 지도에 마커가 표시되고, 동시에 MapLibre 지도도 같은 위치로 이동합니다.
팁 & 트러블슈팅
| 상황 | 해결 방법 |
|---|---|
| 검색 결과가 나타나지 않음 | API 키가 올바른지, 그리고 CORS 설정이 허용되어 있는지 확인합니다. |
| 마커가 중복 표시 | 기존 마커를 저장한 뒤, 새 검색이 들어올 때 remove() 메서드로 삭제하고 다시 추가합니다. |
| MapLibre와 Leaflet이 서로 다른 좌표 체계를 사용 | 두 라이브러리 모두 WGS84(위도/경도) 좌표를 사용하므로, lat, lng 순서에 주의합니다. |
| 모바일에서 입력창이 가려짐 | CSS z-index와 position 값을 조정해 입력창이 최상위에 오도록 합니다. |
마무리
Geoapify Companion 플러그인을 활용하면 Leaflet과 MapLibre 사이에서 매끄러운 주소 검색 경험을 손쉽게 구현할 수 있습니다.
필요에 따라 결과를 GeoJSON 형태로 받아와 커스텀 레이어에 표시하거나, 거리 계산 등 추가 기능을 확장해 보세요.
추가 자료
즐거운 코딩 되세요! 🚀
주소 자동완성 예제의 Leaflet 버전
MapLibre GL 튜토리얼을 보셨다면, 이 예제는 동일한 UX 패턴을 따릅니다: 사용자가 주소를 검색하고 마커가 있는 인터랙티브 지도에서 확인할 수 있습니다.
사용된 API
- Address Autocomplete API – 사용자가 입력할 때 실시간 제안 제공
- Map Tiles – Leaflet용 래스터 지도 타일
- Map Marker Icon 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 키를 받으려면 가입하세요.

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 위젯은 사용 중인 지도 라이브러리에 관계없이 동일하게 작동합니다.

사용자가 입력할 때 자동완성 드롭다운이 표시됩니다.
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)에 복사하고 브라우저에서 엽니다.
다음이 표시됩니다:
- 전체 화면 Leaflet 지도.
- 왼쪽 상단에 자동완성 입력창.
- 실시간 주소 제안.
- 주소를 선택하면 자동으로 팬 이동하고 사용자 지정 마커가 표시됩니다.
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]을 사용합니다.

주소를 선택하면 지도는 해당 위치로 이동하고 마커를 표시합니다.
단계 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: 인터랙티브 플레이그라운드를 이용하세요:
- Map Tiles Playground – 다양한 지도 스타일을 시도해볼 수 있습니다.
- Marker Icon Playground – 커스텀 마커를 디자인합니다.
- Autocomplete Playground – 주소 검색을 테스트합니다.
지금 사용해 보세요
geoapify.com에 가입하고 무료 API 키를 받아 주소 자동완성이 포함된 Leaflet 지도 만들기를 시작하세요.