지도 타일 방식 쉽게 이해하기: Raster, Vector, MVT, MLT, PMTiles 차이
지도를 확대하고 움직일 때 화면 전체를 매번 새로 내려받는다면 지도는 매우 느려진다. 그래서 웹 지도는 보통 화면을 작은 정사각형 조각으로 나눠 필요한 조각만 받아온다. 이 조각이 바로 `타일`이다.
지도 타일을 이해하면 네이버지도, 카카오맵, 구글맵 같은 지도 SDK를 쓸 때도 더 쉽게 판단할 수 있다. "왜 지도는 확대하면 새로 그려질까?", "벡터 타일은 이미지 타일보다 무조건 좋은 걸까?", "PMTiles와 MVT는 뭐가 다를까?" 같은 질문이 한 번에 정리된다.
이 글은 지도 개발을 처음 보는 사람도 읽을 수 있게, 타일 방식을 역할별로 나눠 설명한다.

먼저 전체 지형도 — 용어 한 장 정리
아래 표로 큰 그림을 잡고 본문을 읽으면 헷갈리지 않는다. 핵심은 "담는 내용 / 포맷 / 묶음·배포"가 서로 다른 층위라는 점이다.
| 용어 | 층위 | 한 줄 설명 |
|---|---|---|
| Raster tile | 담는 내용 | 이미 그려진 이미지 조각(PNG·WebP) |
| Vector tile | 담는 내용 | 점·선·면 데이터, 클라이언트가 직접 그림 |
| GeoJSON | 담는 내용 | 소규모 지리 데이터 JSON |
| MVT | 포맷 | 가장 널리 쓰는 벡터 타일 포맷 |
| MLT | 포맷 | MapLibre 차세대 벡터 타일 |
| MBTiles | 묶음·배포 | SQLite 기반, 서버가 읽어 서빙 |
| PMTiles | 묶음·배포 | 단일 archive 파일, S3/CDN Range Request |
지도 타일은 왜 필요한가
지도는 데이터가 매우 크다. 전 세계 도로, 건물, 행정구역, 지명, POI를 한 번에 내려받을 수는 없다. 그래서 지도는 보통 확대 레벨과 위치에 따라 작은 조각으로 나뉜다.
/{z}/{x}/{y}
여기서 `z`는 확대 레벨, `x`와 `y`는 해당 확대 레벨에서의 가로·세로 위치다. 사용자가 지도를 움직이면 현재 화면에 필요한 타일만 새로 요청한다.
이 구조 덕분에 지도는 다음처럼 동작한다.
| 상황 | 실제 동작 |
|---|---|
| 지도를 조금 옆으로 이동 | 새로 보이는 쪽 타일만 추가 요청 |
| 확대 | 더 자세한 확대 레벨의 타일 요청 |
| 축소 | 더 넓은 범위의 낮은 확대 레벨 타일 요청 |
| 같은 지역 재방문 | 브라우저·CDN 캐시에서 재사용 가능 |
즉 지도 타일은 "큰 지도를 작게 쪼개서 필요한 만큼만 받는 방식"이다.
Raster tile: 이미 그려진 이미지 조각
`Raster tile`은 지도 서버가 미리 그려둔 이미지 조각이다. PNG, JPEG, WebP 같은 이미지라고 생각하면 된다.
서버는 도로, 건물, 지명, 색상, 라벨을 모두 그린 뒤 이미지로 내려준다. 클라이언트는 이미지를 붙여서 보여주기만 하면 된다.
| 장점 | 단점 |
|---|---|
| 구현이 단순하다 | 스타일을 바꾸려면 이미지를 다시 만들어야 한다 |
| 오래된 브라우저에서도 안정적이다 | 고해상도·회전·기울임에서 한계가 있다 |
| 서버에서 완성된 화면을 내려준다 | 같은 데이터라도 다국어·다크모드 대응이 무겁다 |
Raster tile은 "완성된 지도 사진"에 가깝다. 그래서 안정적이고 이해하기 쉽다. 하지만 스타일을 바꾸거나, 사용자가 선택한 테마에 맞춰 즉석에서 표현을 바꾸기는 어렵다.
Vector tile: 데이터 조각을 받아 클라이언트가 그리기
`Vector tile`은 이미지를 내려주는 대신 점, 선, 면 데이터를 내려준다. 도로는 선, 건물은 면, 지명은 텍스트 속성, POI는 점 데이터처럼 들어간다. 클라이언트는 이 데이터를 받아 스타일에 맞게 직접 그린다.
OpenStreetMap Wiki도 raster tile은 이미 렌더링된 이미지, vector tile은 아직 렌더링이 필요한 지리 데이터를 담는 방식으로 구분한다.
| 장점 | 단점 |
|---|---|
| 같은 데이터에 여러 스타일을 적용할 수 있다 | 클라이언트 렌더링 부담이 생긴다 |
| 확대·회전·기울임 표현이 자연스럽다 | 스타일·폰트·라벨 충돌 처리가 어렵다 |
| 다크모드, 언어, 강조 스타일을 바꾸기 쉽다 | 초기 구현 난이도가 raster보다 높다 |
| 데이터와 표현을 분리할 수 있다 | 디버깅할 때 포맷·렌더러 지식이 필요하다 |
최근 지도 생태계가 vector tile로 이동하는 이유는 단순히 "더 최신이라서"가 아니다. 같은 지리 데이터를 여러 화면과 스타일에서 재사용하기 좋고, 클라이언트 성능도 좋아졌기 때문이다.
MVT: 가장 널리 쓰이는 벡터 타일 포맷
`MVT`는 Mapbox Vector Tile의 줄임말이다. 벡터 타일을 담는 대표적인 포맷으로, 많은 지도 도구와 서버가 지원한다.
MVT 파일 안에는 보통 여러 layer가 들어간다. 예를 들면 하나의 타일 안에 `road`, `building`, `water`, `place` 같은 layer가 들어가고, 각 layer 안에 점·선·면 feature와 속성이 들어간다.
MVT를 쉽게 말하면 "지도 데이터를 작게 잘라 담는 표준적인 압축 봉투"다.
| 질문 | 답 |
|---|---|
| MVT는 이미지인가? | 아니다. 점·선·면과 속성을 담는 binary 데이터다. |
| 브라우저가 바로 보여주나? | MapLibre GL JS 같은 렌더러가 해석해서 그린다. |
| GeoJSON과 뭐가 다른가? | GeoJSON보다 타일 단위 전송과 렌더링에 맞게 작고 빠르게 설계됐다. |
| 지금도 많이 쓰나? | 그렇다. 호환성과 도구 생태계가 강점이다. |
새로운 포맷을 바로 도입하기 어렵다면, 보통은 MVT부터 검토하는 편이 현실적이다. PostGIS, Martin, Tegola, Planetiler 같은 도구와 연결하기 쉽고, MapLibre 쪽 예제도 많다.
MLT: MapLibre가 밀고 있는 차세대 벡터 타일
`MLT`는 MapLibre Tile의 줄임말이다. MapLibre가 발표한 새로운 벡터 타일 포맷으로, MVT의 후속 포맷을 목표로 한다.
MVT가 feature마다 key/value tag를 붙이는 방식에 가깝다면, MLT는 데이터를 더 column-oriented하게 다루려는 방향이다. 그래서 대형 타일에서 압축률과 디코딩 성능을 개선하고, CPU/GPU 처리와도 더 잘 맞게 하려는 목적이 있다.
MapLibre 발표에서는 MLT가 대형 타일에서 더 나은 압축률과 디코딩 성능을 목표로 한다고 설명한다. 다만 실무에서는 "좋아 보이니 바로 MLT"보다 순서를 나눠야 한다.
먼저 vector tile 렌더링 경로가 있는가? MVT로도 병목이 실제로 확인되는가? MLT를 지원하는 클라이언트·서버·생성 도구가 현재 요구에 맞는가?
| 항목 | MVT | MLT |
|---|---|---|
| 생태계 | 성숙하고 넓다 | 빠르게 확장 중 |
| 호환성 | 매우 좋다 | 확인이 필요하다 |
| 목표 | 범용 vector tile 표준 | 더 나은 압축·디코딩·현대 GPU 친화성 |
| 도입 순서 | 1차 후보 | MVT 실험 후 비교 후보 |
MLT는 흥미로운 기술이지만, "포맷만 바꾸면 지도 서비스가 빨라진다"는 식으로 보면 위험하다. 렌더러, 타일 생성, 캐시, 운영 배포까지 같이 봐야 한다.
PMTiles: 타일 포맷이 아니라 타일 묶음 파일
`PMTiles`는 MVT나 MLT와 같은 층의 기술이 아니다. PMTiles는 많은 타일을 하나의 파일로 묶는 archive/container 포맷이다.
예를 들어 `/z/x/y.mvt` 파일을 수백만 개 따로 올리는 대신, 하나의 `.pmtiles` 파일에 묶어 S3나 CDN에 올릴 수 있다. 클라이언트는 HTTP Range Request로 필요한 부분만 읽는다.
| 장점 | 단점 |
|---|---|
| 서버 없이 S3/CDN 중심으로 배포하기 좋다 | read-only 성격이 강하다 |
| 수많은 개별 파일 업로드 부담을 줄인다 | 일부 타일만 즉석 수정하기 어렵다 |
| 정적 지도 데이터에 잘 맞는다 | 자주 바뀌는 데이터에는 불편하다 |
| MapLibre, Leaflet, OpenLayers와 조합 가능 | Range Request와 캐시 정책을 이해해야 한다 |
PMTiles 안에는 MVT가 들어갈 수도 있고, raster tile이 들어갈 수도 있다. 그래서 PMTiles를 "벡터 타일 포맷"이라고 부르면 조금 헷갈린다. 더 정확히는 "타일 묶음 배포 방식"에 가깝다.
MBTiles: 서버가 읽는 SQLite 기반 타일 묶음
`MBTiles`도 타일을 묶는 컨테이너다. 다만 PMTiles가 HTTP Range Request로 원격 파일을 직접 읽는 방향이라면, MBTiles는 SQLite 파일을 서버 프로세스가 읽어 타일을 서빙하는 방식에 더 가깝다.
| 항목 | MBTiles | PMTiles |
|---|---|---|
| 내부 구조 | SQLite 기반 | 단일 archive 파일 |
| 주 사용 방식 | 서버가 파일을 읽어 타일 제공 | 클라이언트 또는 프록시가 원격 파일 일부를 읽음 |
| 배포 감각 | 서버 운영에 자연스러움 | S3/CDN 배포에 자연스러움 |
| 적합한 상황 | 내부 서버, 오프라인, 로컬 파일 | 정적 공개 타일, 서버리스 지도 |
둘 다 "타일 데이터를 담는 상자"라고 보면 된다. 차이는 어디서 어떻게 읽고 배포하느냐다.
GeoJSON은 타일인가
`GeoJSON`은 타일 포맷이라기보다 지리 데이터를 표현하는 JSON 포맷이다. 작은 데이터셋에는 매우 편하다. 예를 들어 매장 20개, 특정 동네의 경계 몇 개, 간단한 선 몇 개를 보여줄 때는 GeoJSON으로도 충분하다.
하지만 데이터가 커지면 문제가 생긴다.
- 파일이 커진다.
- 화면에 안 보이는 데이터까지 내려받기 쉽다.
- JSON parse 비용이 커진다.
- 확대 레벨별 단순화와 캐시 전략을 직접 설계해야 한다.
그래서 작은 데이터는 GeoJSON, 큰 데이터는 tile 방식으로 나누는 것이 실용적이다.
bbox, geohash, tile key는 어떻게 다른가
지도 데이터를 다루다 보면 `bbox`, `geohash`, `tile key`도 함께 나온다. 세 개는 경쟁 관계가 아니라 역할이 다르다.
| 개념 | 역할 |
|---|---|
| bbox | 현재 화면의 정확한 사각 범위 |
| geohash | 위치를 문자열 격자로 묶는 bucket |
| tile key | 렌더링과 배포에 쓰는 `z/x/y` 조각 주소 |
실무에서는 보통 이렇게 섞어 쓴다.
클라이언트는 현재 화면 bbox를 보낸다. 서버는 bbox를 geohash나 tile key 목록으로 정규화한다. 캐시는 geohash 또는 tile key 단위로 잡는다. 마지막 결과는 원래 bbox로 다시 정확히 걸러낸다.
이렇게 하면 정확도와 캐시 효율을 함께 챙길 수 있다.
어떤 방식을 고르면 좋을까
정답은 데이터의 성격에 따라 달라진다.
| 상황 | 먼저 볼 방식 |
|---|---|
| 작은 점 데이터 몇십~몇백 개 | GeoJSON 또는 일반 JSON |
| 이미지처럼 안정적인 배경 지도 | Raster tile |
| 스타일을 자주 바꾸는 지도 | Vector tile |
| 호환성과 도구 생태계가 중요 | MVT |
| 대형 벡터 타일의 압축·디코딩이 병목 | MLT 비교 |
| 자주 바뀌지 않는 대형 데이터 배포 | PMTiles |
| 서버에서 DB 조건별로 바로 생성 | PostGIS `ST_AsMVT` + tile server |
가장 중요한 기준은 "새 기술이 멋진가"가 아니라 "현재 병목이 어디인가"다. 네트워크 전송량이 문제인지, 서버 DB 조회가 문제인지, 클라이언트 렌더링이 문제인지에 따라 답이 달라진다.
자주 묻는 질문
벡터 타일이 이미지 타일보다 무조건 좋은가?
아니다. 벡터 타일은 스타일 변경과 고해상도 표현에 강하지만, 클라이언트 렌더링 부담과 구현 복잡도가 있다. 단순하고 안정적인 배경 지도라면 raster tile도 충분히 좋은 선택이다.
MVT와 MLT 중 무엇을 먼저 봐야 하나?
대부분은 MVT부터 보는 편이 안전하다. 도구와 예제가 많고 호환성이 좋다. MLT는 MVT 기반 실험에서 실제 병목이 확인된 뒤 비교하는 순서가 자연스럽다.
PMTiles를 쓰면 타일 서버가 필요 없나?
정적 데이터라면 타일 서버 없이 S3/CDN 중심으로 구성할 수 있다. 하지만 자주 바뀌는 데이터나 사용자 조건별 동적 결과가 필요하면 DB와 서버가 여전히 필요할 수 있다.
네이버지도나 카카오맵을 쓰면 이런 걸 몰라도 되나?
바탕 지도만 쓴다면 몰라도 된다. 하지만 지도 위에 자체 데이터, 예를 들어 매장, 숙소, 매물, 행정구역, 통계 레이어를 많이 올린다면 overlay 데이터 구조를 이해하는 것이 중요하다.
지도 위에 점 몇 개만 찍는데 벡터 타일이 필요한가?
대부분 필요 없다. 데이터가 작으면 일반 API와 JSON이 더 단순하다. 벡터 타일은 데이터가 많고, 확대 레벨별로 나누고, 반복 조회를 캐시해야 할 때 가치가 커진다.
PMTiles 안에 MVT와 MLT가 들어갈 수 있나?
그렇다. PMTiles는 타일을 담는 상자에 가깝고, 안에 들어가는 타일 포맷은 별도다. 그래서 PMTiles와 MVT/MLT를 경쟁 관계로 보면 헷갈린다.
마무리
지도 타일을 이해할 때는 세 가지를 분리하면 쉽다.
무엇을 담는가: raster, vector, GeoJSON 어떤 포맷으로 담는가: MVT, MLT 어떻게 묶고 배포하는가: 개별 z/x/y 파일, MBTiles, PMTiles
지도를 빠르게 만드는 핵심은 유행하는 포맷 하나를 고르는 일이 아니다. 데이터를 얼마나 작게 나누고, 얼마나 잘 캐시하고, 클라이언트가 얼마나 가볍게 그리게 하느냐다.
처음 지도 기능을 만든다면 JSON이나 GeoJSON으로 시작해도 된다. 데이터가 커지고, 같은 지역을 반복 조회하고, 지도 이동 중 버벅임이 보일 때 tile 방식을 검토하면 된다. 그때도 바로 MLT로 뛰기보다 MVT, PMTiles, 렌더러, 캐시 구조를 차례대로 비교하는 편이 안전하다.
댓글
댓글 쓰기