안녕하세요! 구글 SEO와 사용자 경험(UX) 최적화에 정통한 기술 블로그 전문 에디터입니다. 오늘은 Python의 강력한 지도 시각화 라이브러리인 Folium을 사용하여 오프라인에서도 동작하는 인터랙티브 지도를 만드는 방법에 대해 자세히 알아보겠습니다. 많은 개발자분들이 Folium으로 지도를 만들었을 때, 오프라인 환경에서 지도가 보이지 않는 문제와 이를 ‘애플리케이션’ 형태로 배포하려는 시도에서 겪는 혼란에 대한 해결책을 제시합니다.
1. 에러 발생 상황
한 개발자분이 Folium으로 인터랙티브 지도를 성공적으로 생성했지만, 오프라인 환경에서 사용 불가능하다는 문제를 제기했습니다. 지도를 독립적인 ‘애플리케이션’ 형태로 내보내려 했으나, 원하는 대로 작동하지 않았다고 합니다. 아래는 개발자분이 사용했던 원본 코드입니다.
import folium
from folium.plugins import GeoMan
from folium.plugins import Geocoder
from folium.plugins import MeasureControl
from folium.features import Control
Map = folium.Map(location=[-35.434826, 149.802856],
zoom_start=14, tiles= 'OpenStreetMap')
GeoMan().add_to(Map)
Geocoder().add_to(Map)
MeasureControl().add_to(Map)
Control("Scale", position="bottomleft").add_to(Map)
folium.TileLayer(tiles='https://tiles.stadiamaps.com/tiles/alidade_satellite/{z}/{x}/{y}{r}.jpg?api_key=fefc1c84-505f-4a5b-bb0e-ba9de6e77ca2',
attr='© CNES, Distribution Airbus DS, © Airbus DS, © PlanetObserver (Contains Copernicus Data) | © <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> © <a href="https://openmaptiles.org/" target="&blank">OpenMapTiles</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
name='Stadia_AlidadeSatellite').add_to(Map)
folium.LayerControl().add_to(Map)
Map.save('output.application')
2. 명확한 발생 원인
개발자분이 겪은 문제는 Folium의 작동 방식에 대한 오해에서 비롯됩니다.
2.1. Folium 지도의 본질: HTML 파일
Folium은 Python 코드를 통해 웹 브라우저에서 렌더링 가능한 HTML 파일을 생성하는 라이브러리입니다. `Map.save(‘output.application’)` 코드는 단순히 생성된 HTML 콘텐츠를 `output.application`이라는 파일명으로 저장할 뿐이며, 이 파일이 특별한 실행 권한을 가진 ‘애플리케이션’으로 변환되는 것은 아닙니다. 확장자를 `.application`으로 지정해도, 여전히 웹 브라우저로 열어야 하는 일반적인 HTML 파일입니다.
2.2. 오프라인 사용의 제약: 온라인 타일 의존성
생성된 HTML 파일은 Folium의 핵심 기능과 플러그인(GeoMan, Geocoder 등)에 필요한 JavaScript 및 CSS 자원들을 대부분 내부에 포함하고 있습니다. 따라서 이 부분은 오프라인에서도 잘 작동할 가능성이 높습니다. 그러나 지도의 배경이 되는 지도 타일(Map Tiles)은 다릅니다. 원본 코드에서 사용된 `OpenStreetMap`과 `Stadia Maps` 타일은 다음과 같은 외부 URL에서 불러옵니다.
tiles='OpenStreetMap': OpenStreetMap 서버에서 타일을 불러옵니다.tiles='https://tiles.stadiamaps.com/...': Stadia Maps 서버에서 타일을 불러옵니다.
이러한 외부 서버에서 이미지를 불러와야 지도가 완성되기 때문에, 인터넷 연결이 없는 오프라인 환경에서는 지도 타일이 로드되지 않아 지도가 비어 보이게 됩니다. 따라서, 오프라인에서 Folium 지도를 사용하려면 지도 타일을 로컬 환경에서 제공하는 방법이 필요합니다.
3. 해결 방법 및 코드 예시
Folium 지도를 오프라인에서 사용하려면, 핵심적으로 지도 타일을 로컬 환경에서 제공해야 합니다. 또한, ‘애플리케이션’ 확장자 사용에 대한 오해도 바로잡아야 합니다.
3.1. 해결 방법: 로컬 타일 서버 구축
인터넷 연결 없이 지도 타일을 표시하려면, 사용하고자 하는 지역의 지도 타일을 미리 다운로드하여 로컬 컴퓨터의 웹 서버를 통해 제공해야 합니다.
- 타일 데이터 준비:
- QGIS와 같은 GIS 소프트웨어를 사용하거나, Mobile Atlas Creator와 같은 도구를 이용해 원하는 지역의 지도 타일을 `Z/X/Y.png` 또는 `Z/X/Y.jpg`와 같은 폴더 구조로 다운로드합니다.
- 예시: `local_tiles/14/13600/6000.png`
- 로컬 웹 서버 구축:
- 다운로드한 타일이 있는 디렉토리를 서비스할 간단한 HTTP 서버를 Python으로 구축할 수 있습니다.
- 예시 (Python `http.server` 사용):
먼저, 다운로드한 타일들을 담을 `local_tiles`라는 이름의 디렉토리를 생성하고, 그 안에 `Z/X/Y.png` 구조로 타일을 저장합니다. 그리고 `local_tile_server.py` 파일을 생성하여 아래 코드를 작성합니다.
# local_tile_server.py import http.server import socketserver import os # 타일이 저장된 디렉토리 (예: local_tiles/14/13600/6000.png) TILE_DIRECTORY = "local_tiles" PORT = 8000 # SimpleHTTPRequestHandler가 특정 디렉토리를 서비스하도록 설정 class TileServerHandler(http.server.SimpleHTTPRequestHandler): def __init__(self, *args, **kwargs): # 현재 스크립트가 있는 경로를 기준으로 TILE_DIRECTORY를 찾습니다. super().__init__(*args, directory=os.path.join(os.path.dirname(__file__), TILE_DIRECTORY), **kwargs) if not os.path.exists(TILE_DIRECTORY): print(f"경고: '{TILE_DIRECTORY}' 디렉토리가 존재하지 않습니다. 타일을 다운로드하여 이 디렉토리에 넣어주세요.") print("예: local_tiles/Z/X/Y.png") exit() print(f"로컬 타일 서버 시작: http://127.0.0.1:{PORT}") print(f"'{TILE_DIRECTORY}' 디렉토리에서 타일을 서비스합니다. 이 창을 닫지 마세요.") with socketserver.TCPServer(("", PORT), TileServerHandler) as httpd: try: httpd.serve_forever() except KeyboardInterrupt: print("\n로컬 타일 서버를 종료합니다.") httpd.shutdown()이 스크립트를 실행한 후 웹 브라우저에서 `http://127.0.0.1:8000/`에 접속하여 타일이 제대로 서비스되는지 확인할 수 있습니다. 이제 Folium 코드에서 이 로컬 서버의 URL을 타일 소스로 지정합니다.
- Folium 코드 수정:
수정된 Folium 코드는 다음과 같습니다. `tiles` 인수에 로컬 타일 서버의 URL을 입력하고, `Map.save()` 함수로 `.html` 확장자를 사용하는 것이 좋습니다.
import folium from folium.plugins import GeoMan, Geocoder, MeasureControl from folium.features import Control # 로컬 타일 서버가 'http://127.0.0.1:8000'에서 실행 중이고, # 'local_tiles' 디렉토리 아래에 Z/X/Y.png 형태로 타일이 있다고 가정합니다. # (예: local_tiles/14/13600/6000.png) local_tiles_url = 'http://127.0.0.1:8000/{z}/{x}/{y}.png' local_tiles_attr = 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors (Local Tiles)' local_tiles_name = 'Local OpenStreetMap' # 지도를 생성할 때, 기본 타일셋을 사용하지 않도록 tiles=None으로 설정합니다. Map = folium.Map(location=[-35.434826, 149.802856], zoom_start=14, tiles=None) # 기본 타일셋 비활성화 # 로컬 타일 레이어를 추가합니다. folium.TileLayer( tiles=local_tiles_url, attr=local_tiles_attr, name=local_tiles_name ).add_to(Map) # 기존에 사용하던 플러그인들은 여전히 추가할 수 있습니다. # 이들은 대부분 Folium HTML에 직접 임베드되므로 오프라인에서 작동합니다. GeoMan().add_to(Map) Geocoder().add_to(Map) MeasureControl().add_to(Map) Control("Scale", position="bottomleft").add_to(Map) folium.LayerControl().add_to(Map) # HTML 파일로 저장합니다. 확장자를 '.html'로 명확히 하는 것이 좋습니다. output_filename = 'offline_folium_map.html' Map.save(output_filename) print(f"오프라인 Folium 지도가 '{output_filename}'으로 저장되었습니다.") print("이 HTML 파일을 열기 전에, 'local_tile_server.py'를 실행하여 로컬 타일 서버를 시작해야 합니다.") print("local_tiles 디렉토리에 타일이 준비되어 있는지 확인해주세요.")실행 순서:
- 타일 데이터를 `local_tiles` 디렉토리에 준비합니다.
- 터미널에서 `local_tile_server.py`를 실행하여 로컬 타일 서버를 시작합니다. (이 창은 닫지 마세요.)
- 다른 터미널에서 수정된 Folium 코드를 실행하여 `offline_folium_map.html` 파일을 생성합니다.
- 생성된 `offline_folium_map.html` 파일을 웹 브라우저(Chrome, Firefox 등)로 열면 오프라인에서도 지도가 정상적으로 표시됩니다.
3.2. ‘application’ 확장자 문제 해결
`Map.save(‘output.application’)`은 기술적으로 문제가 없지만, 사용자가 기대하는 ‘독립적인 애플리케이션’과는 거리가 있습니다. HTML 파일은 웹 브라우저가 해석하는 문서이므로, 파일 확장자를 `.html`로 명확히 지정하여 혼동을 피하는 것이 좋습니다.
# HTML 파일로 저장합니다. Map.save('my_offline_map.html')3.3. (선택 사항) 데스크톱 애플리케이션으로의 확장
만약 단순히 HTML 파일을 넘어, 완전한 독립형 데스크톱 애플리케이션을 원하신다면 Folium만으로는 부족합니다. 웹 기술을 사용하여 데스크톱 앱을 만드는 Electron이나 Python GUI 라이브러리인 PyQtWebEngine 등을 고려해 볼 수 있습니다. 이러한 프레임워크는 HTML, CSS, JavaScript로 만든 웹 페이지를 데스크톱 애플리케이션 내부에 띄우고, 로컬 타일 서버와 연동하여 진정한 오프라인 앱을 구축할 수 있도록 돕습니다.
4. 향후 예방을 위한 팁
- Folium의 본질 이해: Folium은 HTML 파일을 생성하는 도구임을 명확히 인지하고, ‘애플리케이션’ 배포에 대한 기대치를 조절하는 것이 중요합니다.
- 오프라인 지도 계획: 오프라인 지도를 구현해야 할 경우, 지도 타일 데이터를 어떻게 확보하고 서비스할 것인지 초기 단계부터 계획하세요. MBTiles와 같은 오프라인 지도 포맷과 이를 서비스할 로컬 서버 도구(예: `tileserver-gl`)를 학습하는 것도 좋은 방법입니다.
- 확장자 명확화: 생성된 파일은 HTML 문서이므로, `Map.save(‘my_map.html’)`과 같이 `.html` 확장자를 사용하는 것이 가장 직관적이고 표준적인 방법입니다.
- 목표 명확화: 단순히 웹 브라우저에서 오프라인으로 지도를 보고 싶은 것인지, 아니면 독립 실행형 데스크톱 애플리케이션을 만들고 싶은 것인지 목표를 명확히 하면 적절한 기술 스택을 선택하는 데 도움이 됩니다.
이 가이드가 Folium을 이용한 오프라인 지도 구현에 대한 궁금증을 해소하고, 더 나아가 여러분의 프로젝트에 실질적인 도움이 되기를 바랍니다. 궁금한 점이 있다면 언제든지 댓글로 문의해주세요!
![[에러 해결] [Selenium] Reddit 봇 탐지(401 Unauthorized) 우회 및 로그인 실패 원인과 해결 방법 [에러 해결] [Selenium] Reddit 봇 탐지(401 Unauthorized) 우회 및 로그인 실패 원인과 해결 방법](https://dev-error.com/wp-content/plugins/contextual-related-posts/default.png)