leafmap·geemap 같은 파이썬 지리공간 라이브러리로 유명한 개발자다. GeoLibre는 그 계보의 "다음 단계"로, 파이썬 라이브러리가 아니라 누구나 클릭으로 쓰는 완성된 앱을 지향한다.
opengeos/GeoLibre · 라이선스 MIT · 버전 v2.3.0 · TrendShift 데일리 7위 · Tauri v2 + React + TypeScript + MapLibre + DuckDB-WASM + deck.gl · Node ≥22 / Python ≥3.11)
먼저 이름을 풀자. Geo는 지리(땅·지도), Libre는 프랑스어·스페인어로 "자유로운(free)"을 뜻한다. 리브레오피스(LibreOffice)의 "리브레"와 같은 뜻으로, 돈도 안 들고 제약도 없는 자유 소프트웨어임을 이름에 박아 둔 것이다. GeoLibre = "자유로운 지리정보 도구".
왜 필요할까? 기존 GIS는 진입장벽이 높다. 프로그램을 설치해야 하고, 용량이 크고, 초보자에게 어렵다. 반대로 웹 기반 지도 도구는 대개 데이터를 남의 서버(클라우드)에 올려야 해서 프라이버시와 비용 문제가 생긴다. GeoLibre는 이 둘 사이를 노린다 — 브라우저처럼 가볍게 열리지만, 데이터는 내 기기 안에서만 처리한다.
보통 전문 GIS(QGIS)는 포토샵 같다 — 강력하지만 무겁게 설치해야 하고 배우기 어렵다. 반대로 온라인 지도 서비스는 남의 사진관 같다 — 편하지만 내 원본 파일을 맡겨야 한다.
GeoLibre는 "브라우저 탭 하나 열듯 가볍게 시작하되, 무거운 분석 계산까지 그 탭 안에서(WebAssembly로) 끝내는 지도 편집실"이다. 파일을 끌어다 놓으면 브라우저 안의 데이터베이스 엔진(DuckDB)이 곧장 읽고, 계산도 브라우저 안에서 돈다. 서버로 아무것도 안 보내니 오프라인에서도, 민감한 데이터로도 작업할 수 있다.
그리고 이 "편집실"은 한 몸으로 네 곳에서 산다. 같은 React 코드가 브라우저에서는 웹앱으로, Tauri로 감싸면 데스크탑·안드로이드 네이티브 앱으로, 파이썬으로 감싸면 주피터 노트북 안 위젯으로 돈다. "한 번 짜서 어디서나"를 실제로 달성한 드문 사례다.
GeoLibre가 TrendShift 데일리 상위에 오른 이유는 크게 세 가지다.
지리공간 분야 사람들은 오래도록 "QGIS를 웹에서 쓰고 싶다"고 바랐다. GeoLibre는 700개가 넘는 GIS 처리 도구를 브라우저 안에서, 설치 없이 제공한다고 내세운다(공식 영상 제목이 "700+ Free GIS Tools, Zero Install"). 무거운 계산도 서버 없이 브라우저에서 돌아간다는 점이 결정적 차별점이다.
개발자들이 열광하는 지점은 배포 범위다. 하나의 코드베이스가 웹·데스크탑(Win/Mac/Linux)·안드로이드·주피터에서 돈다. 게다가 Microsoft Store, Arch AUR, Flatpak, PyPI, conda-forge까지 거의 모든 배포 채널에 올라 있다. Tauri(가벼운 데스크탑 프레임워크) + WebAssembly를 이렇게 넓게 활용한 실전 사례는 흔치 않다.
기능 목록에 재미 요소가 많다. 달·화성·수성·금성·목성 위성들·명왕성까지 행성 지도(planetary basemap)를 지원하고, 행성마다 반지름을 다르게 잡아 거리·면적 계산까지 맞춘다. CesiumJS 3D 지구본, 시간 슬라이더 애니메이션, 위키피디아 지식 카드 등 "보여주기 좋은" 기능이 스크린샷·영상으로 퍼지기 좋다.
설치 불필요, 브라우저·모바일에서도 동작, 프로젝트 파일이 사람이 읽는 JSON(.geolibre.json). 대신 아직 데스크탑 GIS만큼 도구가 완전하진 않다.
Mapbox Studio / 웹 지도 서비스 대비: 데이터를 서버에 안 올림(로컬·프라이빗), 오프라인 PWA로 작동, 완전 오픈소스(MIT).
GeoLibre의 스택은 "브라우저 하나로 GIS를 다 하겠다"는 목표에 맞춰 선택돼 있다. 큰 덩어리로 나눠 보자.
| 기술 | 역할 |
|---|---|
| React + TypeScript | UI 전체. 패널·다이얼로그·메뉴가 모두 React 컴포넌트다. |
| Zustand | 전역 상태 저장소(store). "지금 지도에 어떤 레이어가 있나"를 한곳에서 관리. 이 스토어가 아키텍처의 심장(4번 섹션 참고). |
| Tauri v2 | 웹앱을 네이티브 데스크탑·안드로이드 앱으로 감싸는 러스트(Rust) 기반 프레임워크. Electron보다 훨씬 가볍다. |
| Vite | 빌드 도구. PWA(오프라인), 청크 분할, 에셋 복사 등을 담당. |
| 기술 | 역할 |
|---|---|
| MapLibre GL JS | 기본 지도 엔진. WebGL로 벡터 타일을 그린다. Mapbox GL의 오픈소스 포크. 2D 지도의 중심. |
| deck.gl | 대용량 포인트·3D·래스터 오버레이 등 고급 시각화 레이어. 수백만 점도 GPU로 그린다. |
| CesiumJS (선택) | 진짜 3D 지구본 뷰. 분할 화면(split pane)으로 켠다. 무거워서(약 4.8MB) 필요할 때만 지연 로딩. |
| 기술 | 역할 |
|---|---|
| DuckDB-WASM + Spatial | 브라우저 안에서 도는 분석용 데이터베이스. GeoParquet·Shapefile·GeoPackage 등을 읽어 GeoJSON으로 변환하고, 공간 SQL을 돌린다. |
| Turf.js | 버퍼·교차 같은 벡터 분석을 브라우저에서 즉시(서버 없이) 수행. |
| Pyodide (선택) | 파이썬(GeoPandas·Shapely)을 브라우저 안에서 돌리는 WebAssembly 런타임. 서버 없이 파이썬 분석. |
| PGlite / Apache Sedona (선택) | 브라우저 안 PostGIS(PGlite), 대용량 공간 SQL 엔진(Sedona/CereusDB). SQL 워크스페이스의 선택지. |
| 기술 | 역할 |
|---|---|
| FastAPI 파이썬 사이드카 | 브라우저에서 못 하는 무거운 처리(Whitebox 툴박스, 포맷 변환)를 로컬 127.0.0.1에서 도와주는 선택적 파이썬 서버. |
| Cloudflare Workers | workers/에 있는 4개 워커(ai-proxy·collab·tiles·viewer) — AI 프록시, 실시간 협업, 타일 재투영, 공유 뷰어. |
| Rust (Tauri src-tauri) | 데스크탑 네이티브 기능 — 파일 시스템, MBTiles 읽기, 네이티브 HTTP(사내 인증서·mTLS 지원). |
| 파이썬 anywidget | 주피터 노트북에서 GeoLibre 앱 전체를 위젯으로 띄우는 geolibre PyPI 패키지. leafmap 스타일 API. |
"React로 만든 화면을, MapLibre가 지도를 그리고, DuckDB-WASM이 데이터를 씹고, Zustand가 상태를 지휘하며, Tauri가 이 모두를 데스크탑·모바일 앱으로 포장한다 — 그리고 무거운 일은 선택적 파이썬 사이드카가 거든다."
GeoLibre 아키텍처를 이해하는 열쇠는 딱 하나다 — 중앙 스토어(Zustand)가 지도 엔진을 전혀 모른다는 것. 스토어는 그냥 "레이어 목록"과 "카메라 상태"라는 평범한 데이터(plain object)만 들고 있다. MapLibre 객체도, Cesium 객체도 스토어 안에 없다. 이 결정 하나가 멀티 엔진·멀티 플랫폼을 가능하게 한다.
실제로 사용자가 GeoJSON 파일 하나를 끌어다 놓으면 다음 순서로 흐른다.
addGeoJsonLayer로 넘긴다.GeoLibreLayer 레코드가 추가된다(소스 정보·스타일 포함). 아직 화면엔 아무 일도 안 일어난다.MapCanvas가 layers를 구독하고 있다가, MapController.syncLayers가 MapLibre의 소스·레이어를 실제로 갱신한다.projectFromStore가 스토어를 .geolibre.json 파일로 쓴다.스토어는 극장의 대본(script)이고, MapLibre·Cesium은 두 명의 배우다. 대본은 "무대에 나무 한 그루, 왼쪽에 집 한 채"라고만 적혀 있을 뿐, 배우가 그걸 어떻게 연기하는지는 모른다. 그래서 배우를 한 명 더(3D 지구본) 데려와 같은 대본을 읽게 하면, 대본을 한 글자도 안 고치고 3D 뷰가 생긴다. 이게 "엔진 독립 스토어"의 힘이다.
CesiumJS 3D 지구본은 플러그인이 아니라 1급 뷰 모드로 붙는다. 이유가 명확하다 — 플러그인 API는 MapLibre 타입에 묶여 있어서, 완전히 다른 엔진인 Cesium을 플러그인으로 만들 수 없다. 대신 Cesium은 2D 보조 패널(SecondaryMapCanvas)과 똑같이 스토어를 구독하는 방식으로 끼어든다. 스토어가 엔진을 모르기 때문에 가능한 일이다.
import()된다. 2D 부팅 경로엔 실리지 않는다.cesium-camera.ts가 MapLibre의 좌표계와 Cesium의 좌표계를 "화면상 1픽셀 = 몇 미터"(ground resolution) 기준으로 맞춰, 2D·3D 패널이 같은 축척으로 움직인다.CesiumLayerSync가 Cesium이 잘 그리는 종류(GeoJSON·래스터·3D Tiles)만 그리고, 나머지(PMTiles·LiDAR 등)는 "2D 전용"으로 표시하고 건너뛴다.
벡터 분석용 파이썬 코드(vector_ops.py)는 프레임워크에 의존하지 않는 순수 모듈로 짜여 있다. 그래서 같은 코드가 세 군데서 돈다.
| 엔진 | 돌아가는 곳 |
|---|---|
| Turf.js | 브라우저(클라이언트) — 서버 불필요, 가장 빠름 |
| Python 사이드카 | 로컬 FastAPI 서버 — GeoPandas/Shapely, 투영 정확 |
| Python (Pyodide) | 브라우저 안 — 같은 GeoPandas 코드를 WASM으로, 서버 없이 |
Vite 플러그인(copy-vector-ops.ts)이 이 파이썬 파일을 앱 번들로 복사하고, 웹 워커가 Pyodide를 CDN에서 불러 run_vector_tool을 호출한다. "진실의 원천이 하나"라서 사이드카와 Pyodide가 똑같은 결과를 낸다.
웹 빌드는 설치 가능한 PWA다. 캐싱을 둘로 쪼갠 게 포인트다.
Pyodide 벡터 엔진과 PGlite/PostGIS는 jsDelivr CDN(외부 도메인)에서 불러오는데, 서비스 워커는 외부 도메인을 캐시하지 않는다. 완전 오프라인으로 쓰려면 VITE_PYODIDE_INDEX_URL을 같은 도메인 미러로 지정하거나, GEOLIBRE_PGLITE_CDN=0으로 빌드에 내장해야 한다(단 Tauri 바이너리가 ~22MB 커진다).
GeoLibre는 모노레포(monorepo)다. package.json의 workspaces가 apps/*·packages/*·workers/*를 묶는다. 한 저장소 안에서 여러 npm 패키지가 서로를 참조한다.
@geolibre/core·@geolibre/map 등을 한 repo에 두고 서로 참조한다. 장점은 코드 공유·일괄 빌드·버전 일치. npm workspaces가 이걸 묶어 준다.
구조에서 읽어야 할 핵심은 의존성 방향이다. core(스토어)는 아무에게도 의존하지 않고, map·plugins·processing이 core를 참조한다. geolibre-desktop이 이 모두를 조립한다. core가 엔진을 모른다는 4번 섹션의 설계가 이 디렉토리 배치에 그대로 드러난다.
"렌더러(뷰)를 상태에서 분리하라"는 원칙의 교과서적 실전 예시. 스토어에 도메인 데이터만 두고, 뷰는 그걸 구독만 하게 하면 → 렌더러를 갈아 끼우거나 추가하기 쉬워진다. GeoLibre는 이 원칙 하나로 2D·3D·멀티맵을 동시에 얻었다.
DuckDB-WASM(데이터베이스), Pyodide(파이썬), CereusDB/PGlite(공간 SQL)를 어떻게 지연 로딩하고 청크를 분리하는지가 통째로 담겨 있다. WASM을 실무에 쓰려는 사람에게 참고서.
같은 React 앱을 Tauri로 감싸 Win/Mac/Linux + 안드로이드까지 내보내는 실제 설정. scripts/tauri-build.mjs, MSIX/portable 빌드 스크립트, native-duckdb 옵션 등 배포 파이프라인 전체를 볼 수 있다.
"첫 방문은 가볍게, 무거운 건 쓸 때만 캐시"를 Workbox로 구현한 예. 해시 파일명으로 CacheFirst를 안전하게 쓰는 법, 자동 업데이트 시 지도 상태가 날아가지 않게 하는 onNeedReload 처리까지 디테일이 살아 있다.
vector_ops.py를 순수 모듈로 짜서 사이드카·Pyodide 양쪽에서 같은 결과를 내는 기법. 로직을 프레임워크에서 떼어내면 여러 실행 환경에 재사용할 수 있다는 원칙의 좋은 예.
web.geolibre.app)을 열고 개발자도구 Network 탭에서 DuckDB·Cesium 청크가 언제 로드되는지 관찰 → 지연 로딩 눈으로 확인..geolibre.json을 텍스트 에디터로 열어 스토어 구조가 그대로 직렬화된 걸 확인.ST_*)을 직접 던져 보기.| 사용 방식 | 요구사항 |
|---|---|
| 웹앱(그냥 쓰기) | WebGL·WebAssembly 지원 최신 브라우저. 설치 불필요. web.geolibre.app 접속. |
| 데스크탑 앱 | Windows·macOS·Linux 설치본(Store·AUR·Flatpak·직접 다운로드). OS 웹뷰 사용. |
| 소스 빌드(개발) | Node ≥22, Rust 툴체인(Tauri), 파이썬 사이드카를 쓰면 Python ≥3.11. |
| 주피터(파이썬) | pip install geolibre 또는 conda install geolibre. anywidget 기반. |
| 3D 지구본(Cesium) | Cesium Ion 토큰 필요(월드 이미지·지형용). 없으면 3D 토글이 숨겨지고 2D로 열림. |
리눅스 데스크탑은 OS 웹뷰로 WebKitGTK를 쓰는데, 이 엔진의 WebGL 파이프라인이 크롬보다 훨씬 느리다. 타일이 로딩되는 동안에는 지도 팬(pan)이 한 자릿수 FPS로 떨어졌다가, 로딩이 멈추면 다시 60FPS로 돌아온다. 타일 하나당 GPU 업로드 비용이 WebKitGTK에서 ~125ms(크롬은 수 ms). GeoLibre의 버그가 아니라 웹뷰 엔진 한계이며, 웹 빌드·맥·윈도우에는 영향이 없다. 저장소는 이 진단 과정과 배제한 원인들까지 문서에 상세히 남겨 뒀다(엔지니어링 태도의 좋은 예).
web.geolibre.app 접속 → 아무 GeoJSON 파일을 드래그&드롭 → 스타일 패널에서 색·투명도를 바꿔 보고, 프로젝트를 저장한다. 저장된 .geolibre.json을 메모장으로 열어 구조를 눈으로 확인. GIS·클라우드네이티브·상태 직렬화를 한 번에 체감.
공개된 COG(클라우드 최적화 GeoTIFF)나 PMTiles URL을 Add Data로 추가 → 지도를 확대/이동하며 Network 탭을 보라. 전체를 안 받고 보이는 범위만 조각조각 요청하는 걸 확인. "왜 클라우드 네이티브가 중요한가"를 체감하는 과제.
SQL 워크스페이스를 열고, 로컬 파일에 SELECT * FROM layer WHERE ST_Area(geom) > 1000 같은 공간 SQL을 실행 → 결과를 지도에 레이어로 추가. 서버 없이 브라우저(DuckDB-WASM)가 SQL을 돌린다는 걸 직접 확인.
저장소를 클론해 npm install → npm run dev로 데스크탑 개발 모드 실행. 이후 3D 지구본 패널을 켜는 순간 Cesium 청크(~4.8MB)가 import()되는 걸 Network에서 확인. manualChunks·지연 로딩 설정을 코드에서 찾아보기.
packages/plugins의 플러그인 인터페이스와 docs/plugin-api.md를 읽고, 스토어를 구독해 지도에 뭔가를 얹는 간단한 내장 플러그인을 하나 흉내 내 본다. "스토어를 구독하는 뷰"라는 아키텍처를 손으로 익히는 최종 과제.
| 주차 | 주제 | 학습 내용 |
|---|---|---|
| 1주차 | 웹 지도 기초 | MapLibre GL JS 튜토리얼 — 소스·레이어·paint 표현식 개념. 벡터 타일이 뭔지, WebGL로 지도를 어떻게 그리는지. |
| 2주차 | 클라우드 네이티브 GIS | COG·PMTiles·GeoParquet·FlatGeobuf가 각각 뭘 해결하는지. "전부 안 받고 조각만 읽기"의 원리. DuckDB Spatial 기초 SQL. |
| 3주차 | 상태관리 + WASM | Zustand로 "뷰와 상태 분리" 실습. DuckDB-WASM·Pyodide를 브라우저에서 띄워 보기. 지연 로딩·청크 분리 개념. |
| 4주차 | 크로스 플랫폼 셸 | Tauri v2로 웹앱을 데스크탑 앱으로 감싸기. 러스트 커맨드로 파일 시스템 접근. PWA·서비스 워커로 오프라인 만들기. |
지도를 그리는 법(1주) → 데이터를 효율적으로 읽는 법(2주) → 상태와 계산을 브라우저에서 다루는 법(3주) → 이 모두를 여러 플랫폼으로 포장하는 법(4주). GeoLibre 아키텍처가 쌓아 올려진 순서 그대로다.
ST_* SQL을 실행.@geolibre/core가 여기에 레이어·카메라 상태를 담는다. 엔진에 독립적인 게 핵심.| 대상 | 위치 |
|---|---|
| 저장소 | github.com/opengeos/GeoLibre |
| 웹앱(바로 실행) | web.geolibre.app |
| 공식 문서 | geolibre.app (Getting Started·Features·Demos·User Guide) |
| 아키텍처 문서 | docs/architecture.md (스토어·Cesium·PWA·성능 진단) |
| 플러그인 API | docs/plugin-api.md, 프로젝트 포맷 docs/project-format.md |
| 파이썬 패키지 | pypi.org/project/geolibre · conda-forge geolibre |
| 영상 튜토리얼 | "GeoLibre 1.0: A Free Cloud-Native GIS That Runs Anywhere" (YouTube) |
| 만든 사람 | Qiusheng Wu (leafmap·geemap 저자) · Zenodo DOI 10.5281/zenodo.20785400 |