- OpenLayers를 여행하는 개발자를 위한 안내서 - 25. WebGL로 초대용량 데이터 표시하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 24. Heat Map 표현하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 23. Cluster Map 표현하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 22. WFS Transaction으로 데이터 삭제하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 21. WFS Transaction으로 데이터 수정하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 20. WFS Transaction으로 데이터 추가하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 19. WMS에 팝업 붙이기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 18. WFS에 팝업 붙이기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 17. WFS 객체에 상호작용 추가하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 16. WMS GetImage를 사용하여 지도에 이미지 표시하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 15. WFS GetFeature를 사용하여 지도에 객체 표시하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 14. 지도에 사용자의 위치 표시하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 13. 브라우저에서 사용자 위치정보 수집하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 12. 맵의 유용한 정보 표시하기
👀 OpenLayers를 여행하는 개발자를 위한 안내서 - 11. VWorld 맵 만들기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 10. Open Street Map(OSM) 맵 만들기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 9. 데이터 필터링하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 8. 공간정보 데이터를 주문하는 법. OGC
- OpenLayers를 여행하는 개발자를 위한 안내서 - 7. 공간정보 데이터를 관리하는 법. GeoServer
- OpenLayers를 여행하는 개발자를 위한 안내서 - 6. 공간정보의 DB화
- OpenLayers를 여행하는 개발자를 위한 안내서 - 5. OpenLayers
- OpenLayers를 여행하는 개발자를 위한 안내서 - 4. QGIS 체험하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 3. 좌표계
- OpenLayers를 여행하는 개발자를 위한 안내서 - 2. GIS랑 인사하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 1. 머릿말
Table of Contents
OSM만으로 괜찮을까? 🔗
이전 장에서 OSM을 통해 지도를 표시해봤다. 하지만, OSM의 지도는 디테일함이 떨어진다는 무시할 수 없는 단점이 존재한다.
OSM은 사용하기 쉬운 세계지도라는 큰 장점이 있음에도, 저 단점 하나로 인해 국내 서비스용 지도로 사용하기 어렵다.
즉, 예제 이상의 실질적인 서비스에 사용하려면 국내 지리에 특화된 지도가 필요하다.
VWorld 🔗
이 때 고려해볼만한 것이 VWorld 지도다. VWorld는 국가기관인 공간정보산업진흥원에서 제공하는 지도다. 국가기관에서 제공하는 지도인 만큼. OSM보다 국내 지리에 좀 더 특화되어 있다.
VWorld는 API 서비스를 제공하며, URL의 형태로 배경지도를 제공하므로, OpenLayers와 호환성이 좋다.
VWorld는 여러 타입의 배경지도를 제공하므로, 필요에 맞게 활용할 수 있다.
- 기본지도: 우리가 흔히 사용하는 지도
- 백지도: 일반지도의 흑백버전
- 야간지도: 어두운 배색을 사용하여 야간 가시성을 높인 지도
- 위성지도: 실사지도
- 하이브리드 지도: 도로, 지명만을 강조한 확장용 지도. 단독으로 사용하긴 어렵다.
이 장에서는 OpenLayers를 통해 VWorld를 지도에 띄워본다.
VWorld API Key 발급하기 🔗
API키를 발급하기 위해선 회원가입이 필요하다. 위 링크에 접속하여 회원가입을 수행하자.
[인증키] - [인증키 발급] 메뉴에서 API 발급을 신청할 수 있다. 발급은 신청 즉시 이루어진다.
요구하는 항목을 작성하고 신청하면 된다.
[브이월드 활용API]는 반드시 [WMTS/TMS API]가 체크되어야 한다.
처음 지급되는 키는 개발키로, 개발키는 3개월 간 유효하며, 최대 3번 연장 가능하다.
안정적인 서비스를 원한다면 운영키 신청을 하면 된다. 최대 10일 정도의 심사기간이 있다. 예제 페이지 같은 사이트는 발급해주지 않는 것 같다.
운영키 역시 무제한은 아니고, 1년 주기로 갱신이 필요하며, 갱신을 요청할 때마다 재심사를 거치는 것 같다.
VWorld API 사용하기 🔗
VWorld를 요청하는 방법은 아래와 같다.
TXT
0 | http://api.vworld.kr/req/wmts/1.0.0/{key}/{layer}/{tileMatrix}/{tileRow}/{tileCol}.{tileType} |
Name | Description | Value |
---|---|---|
key | 발급받은 API Key | |
layer | 요청 지도 타입 | Base , gray , midnight , Hybrid , Satellite |
tileMatrix | 지도 레벨 | 6 ~ 18 (gray, midnight) / 6 ~ 19 (Base, Hybrid, Satellite) |
tileRow | y좌표 | |
tileCol | x좌표 | |
tileType | 확장자 | jpeg (Satellite) / png (other) |
자세한 정보는 VWorld WMTS/TMS API 레퍼런스에서 확인할 수 있다.
웹 사이트에 VWorld 띄우기 🔗
1. VWorld Source 만들기 🔗
OSM의 경우, OpenLayers에서 자체적으로 OSM
이라는 객체를 제공했으므로 매우 쉽게 사용이 가능했지만, VWorld의 경우 직접 소스를 구성해줄 필요가 있다.
XYZ
객체를 통해 VWorld 소스를 만들 수 있다.
TYPESCRIPT
0 | import XYZ from 'ol/source/XYZ'; |
1 | |
2 | const source = new XYZ({ url: 'https://api.vworld.kr/req/wmts/1.0.0/API_KEY/Base/{z}/{y}/{x}.png' }); |
위 URL은 VWorld의 기본지도를 호출하는 URL이다.
Name | Type | Default | Description |
---|---|---|---|
attributions | ol/source/Source-AttributionLike | undefined |
기여 문구 (지도 우측 하단) | |
attributionsCollapsible | boolean |
true |
기여 문구 축소 여부 |
cacheSize | number | undefined |
타일 캐시 크기 | |
crossOrigin | string | null |
anonymous |
CORS 속성 |
boolean |
true |
Deprecated 속성. 보간 사용 여부 | |
interpolate | boolean |
true |
보간 사용 여부 |
opaque | boolean |
true |
불투명 여부 |
projection | ol/proj-ProjectionLike | EPSG:3857 |
좌표계 |
reprojectionErrorThreshold | number |
0.5 |
최대 재투영 오류 픽셀 (0 ~ 1) |
maxZoom | number |
42 |
최대 줌 레벨. 지정된 줌레벨을 초과할 경우 데이터 미출력 |
minZoom | number |
0 |
최소 줌 레벨. 지정된 줌레벨 보다 미만일 경우 데이터 미출력 |
maxResolution | number | undefined |
0 |
줌 레벨 0의 해상도 (tileGrid 가 있을 경우 미적용) |
tileGrid | ol/tilegrid/TileGrid-TileGrid | undefined |
0 |
타일 그리드 |
tileLoadFunction | ol/Tile-LoadFunction | undefined |
타일 로드 함수 | |
tilePixelRatio | number |
1 |
타일 픽셀 비율 (값이 2일 경우, 타일 픽셀은 512x512) |
tileSize | number | ol/size-Size |
[ 256, 256 ] |
타일 사이즈 (tileGrid 가 있을 경우 미적용) |
tileUrlFunction | ol/Tile-UrlFunction | undefined |
URL 반환 함수 | |
url | string | undefined |
URL 양식. {x} , {y} 혹은 {-y} , {z} 를 포함해야 함 |
|
urls | Array<string> | undefined |
URL 양식 배열 | |
wrapX | boolean |
true |
수직 감싸기 여부 |
transition | number |
250 |
렌더링 출력 애니메이션 시간 |
zDirection | ol/array-NearestDirectionFunction | number |
0 |
줌 레벨이 실수(ex. 12.552)일 경우 더 높은 타일을 사용할지, 낮은 타일을 사용할지 여부 |
다른 옵션은 몰라도, 자원의 위치를 제공하는 url
혹은 urls
, tileUrlFunction
은 반드시 명시해야한다.
url
의 경우 URL에 리터럴 패턴으로 {x}
, {y}
, {-y}
, {z}
등을 입력할 수 있는데, 현재 지도의 x, y, z좌표를 URL에 자동으로 반영해준다.
그 밖의 동적인 URL 생성이 필요하다면 tileUrlFunction
을 활용하는 것이 좋다.
그 외 사용할 수 있는 옵션과 메서드의 종류는 ol/source/XYZ에서 확인하자.
여담으로, 이전 장에서 다뤘던 OSM
객체 또한 XYZ
객체를 확장하여 구현한 객체다.
2. Layer 만들기 🔗
XYZ Source를 담을 Layer 객체를 생성한다. 이 Layer는 할당된 XYZ Source를 통해 VWorld 지도를 표출해줄 것이다.
TYPESCRIPT
0 | import TileLayer from 'ol/layer/Tile'; |
1 | import XYZ from 'ol/source/XYZ'; |
2 | |
3 | // 기본지도 |
4 | const vworldBaseLayer = new TileLayer({ |
5 | source: new XYZ({ url: 'https://api.vworld.kr/req/wmts/1.0.0/2AAC4DD9-4F6F-3844-A740-E2DB6BDC8CEF/Base/{z}/{y}/{x}.png' }), |
6 | properties: { name: 'base-vworld-base' }, |
7 | minZoom: 5, |
8 | maxZoom: 19, |
9 | zIndex: 2, |
10 | preload: Infinity |
11 | }); |
12 | |
13 | // 백지도 |
14 | const vworldGrayLayer = new TileLayer({ |
15 | source: new XYZ({ url: 'https://api.vworld.kr/req/wmts/1.0.0/2AAC4DD9-4F6F-3844-A740-E2DB6BDC8CEF/gray/{z}/{y}/{x}.png' }), |
16 | properties: { name: 'base-vworld-gray' }, |
17 | minZoom: 5, |
18 | maxZoom: 18, |
19 | zIndex: 2, |
20 | preload: Infinity |
21 | }); |
22 | |
23 | // 야간지도 |
24 | const vworldMidnightLayer = new TileLayer({ |
25 | source: new XYZ({ url: 'https://api.vworld.kr/req/wmts/1.0.0/2AAC4DD9-4F6F-3844-A740-E2DB6BDC8CEF/midnight/{z}/{y}/{x}.png' }), |
26 | properties: { name: 'base-vworld-midnight' }, |
27 | minZoom: 5, |
28 | maxZoom: 18, |
29 | zIndex: 2, |
30 | preload: Infinity |
31 | }); |
32 | |
33 | // 하이브리드 지도 |
34 | const vworldHybridLayer = new TileLayer({ |
35 | source: new XYZ({ url: 'https://api.vworld.kr/req/wmts/1.0.0/2AAC4DD9-4F6F-3844-A740-E2DB6BDC8CEF/Hybrid/{z}/{y}/{x}.png' }), |
36 | properties: { name: 'ext-vworld-hybrid' }, |
37 | minZoom: 5, |
38 | maxZoom: 19, |
39 | zIndex: 3, |
40 | preload: Infinity |
41 | }); |
42 | |
43 | // 위성지도 |
44 | const vworldSatelliteLayer = new TileLayer({ |
45 | source: new XYZ({ url: 'https://api.vworld.kr/req/wmts/1.0.0/2AAC4DD9-4F6F-3844-A740-E2DB6BDC8CEF/Satellite/{z}/{y}/{x}.jpeg' }), |
46 | properties: { name: 'base-vworld-satellite' }, |
47 | minZoom: 5, |
48 | maxZoom: 19, |
49 | zIndex: 2, |
50 | preload: Infinity |
51 | }); |
Name | Type | Default | Description |
---|---|---|---|
className | string |
ol-layer |
클래스명 |
opacity | number |
1 |
투명도 (0 ~ 1) |
visible | boolean |
true |
표시 여부 |
extent | ol/extent-Extent | undefined |
레이어의 렌더링 범위. 해당 범위를 넘어가면 데이터를 표시하지 않음 | |
zIndex | number | undefined |
우선 순위 (높을수록 위에 표시) | |
minResolution | number | undefined |
최소 표시 해상도 | |
maxResolution | number | undefined |
최대 표시 해상도 | |
minZoom | number | undefined |
최소 표시 줌 레벨 | |
maxZoom | number | undefined |
최대 표시 줌 레벨 | |
preload | number |
0 |
지정한 레벨까지 저해상도 타일을 미리 로드 (0은 미사용) |
source | ol/source/Tile-TileSource | undefined |
레이어의 소스 | |
map | ol/PluggableMap-PluggableMap | undefined |
지정한 Map 객체에서 해당 레이어를 오버레이로 사용 |
|
useInterimTilesOnError | boolean |
true |
오류 시 중간타일 사용 여부 |
properties | object | undefined |
임의 속성. get() , set() 으로 조작 가능 |
TileLayer
객체를 통해 타일 레이어를 생성할 수 있다.
옵션의 source
는 필수 옵션으로, 이 옵션을 비우면 레이어에 아무 것도 뜨지 않아 레이어의 의미가 없다.
properties
는 레이어의 임의의 속성을 지정할 수 있다. 위 처럼 레이어의 고유 식별자를 할당해주면, 레이어를 관리하는 데 도움이 된다. Map
객체에서 레이어를 뽑아낼 때, 고유 식별자가 없으면 곤란하기 때문.
그 외 사용할 수 있는 옵션과 메서드의 종류는 ol/layer/Tile에서 확인하자.
3. View 만들기 🔗
TYPESCRIPT
0 | import View from 'ol/View'; |
1 | |
2 | const view = new View({ |
3 | projection: 'EPSG:3857', |
4 | center: [ 14135490.777017945, 4518386.883679577 ], |
5 | zoom: 17 |
6 | }); |
[ 14135490.777017945, 4518386.883679577 ]
은 EPSG:3857
으로 표기한 서울시청 좌표다.
Name | Type | Default | Description |
---|---|---|---|
center | ol/coordinate-Coordinate | undefined |
지도의 중심 | |
constrainRotation | boolean | number |
true |
회전 구속 여부. 숫자일 경우 회전 가능 갯수를 의미 (0일 경우, 90, 180, 270, 360) |
enableRotation | boolean |
true |
회전 가능 여부 |
extent | ol/extent-Extent | undefined |
지도의 뷰잉 범위. 지정된 범위 밖을 벗어날 수 없음 | |
constrainOnlyCenter | boolean |
false |
true 일 경우 extent 제한이 View 중심에만 적용되며, 전체 extent에 적용되지 않음 |
smoothExtentConstraint | boolean |
true |
View가 extent 범위를 약간 벗어날 수 있는지 여부 |
maxResolution | number | undefined |
최대 뷰잉 해상도. 지정 해상도 이상 확대 불가능. | |
minResolution | number | undefined |
최소 뷰잉 해상도. 지정 해상도 이상 축소 불가능. | |
maxZoom | number |
28 |
최대 뷰잉 줌 레벨. 지정 줌 레벨 이상 확대 불가능. |
minZoom | number |
0 |
최소 뷰잉 줌 레벨. 지정 줌 레벨 이상 축소 불가능. |
multiWorld | boolean |
false |
다중 월드 사용 여부 |
constrainResolution | boolean |
false |
줌 레벨 정수만 허용 여부 |
smoothResolutionConstraint | boolean |
true |
느슨한 확대/축소 규칙 사용 여부 |
showFullExtent | boolean |
false |
전체 구성된 extent 표시 여부 |
projection | ol/proj-ProjectionLike | EPSG:3857 |
좌표계 |
resolution | number | undefined |
초기 해상도 | |
resolutions | Array<number> | undefined |
사용 가능한 해상도 목록 (내림차순) max/minResolution , max/minZoom , zoomFactor 옵션이 무시됨 |
|
rotation | number |
0 |
기본 회전값 |
zoom | number | undefined |
기본 줌 레벨 | |
zoomFactor | number |
2 |
줌 배율 |
padding | Array<number> |
[ 0, 0, 0, 0 ] |
패딩 |
View
객체를 통해, 지도의 뷰잉 정보를 선언할 수 있다.
smoothResolutionConstraint
옵션은, 예를 들어 지도의 크기가 width: 120px
, height: 80px
이라고 가정하자. 기본값 false
라면, 지도는 최대 80px까지 확대가 가능하다.
그러나 true
라면, 지도는 최대 120px까지 확대가 가능해진다. 즉, 지도의 확대 기준을 가장 짧은 길이로 할지, 긴 길이로 할지 지정하는 것.
4. Map 만들기 🔗
모든 정보를 종합하여 지도를 만드는 Map 객체를 생성한다.
TYPESCRIPT
0 | import Map from 'ol/Map'; |
1 | import View from 'ol/View'; |
2 | import TileLayer from 'ol/layer/Tile'; |
3 | import XYZ from 'ol/source/XYZ'; |
4 | |
5 | // 기본지도 |
6 | const vworldBaseLayer = new TileLayer({ |
7 | source: new XYZ({ url: 'https://api.vworld.kr/req/wmts/1.0.0/2AAC4DD9-4F6F-3844-A740-E2DB6BDC8CEF/Base/{z}/{y}/{x}.png' }), |
8 | properties: { name: 'base-vworld-base' }, |
9 | minZoom: 5, |
10 | maxZoom: 19, |
11 | zIndex: 2, |
12 | preload: Infinity |
13 | }); |
14 | |
15 | // 하이브리드 지도 |
16 | const vworldHybridLayer = new TileLayer({ |
17 | source: new XYZ({ url: 'https://api.vworld.kr/req/wmts/1.0.0/2AAC4DD9-4F6F-3844-A740-E2DB6BDC8CEF/Hybrid/{z}/{y}/{x}.png' }), |
18 | properties: { name: 'ext-vworld-hybrid' }, |
19 | minZoom: 5, |
20 | maxZoom: 19, |
21 | zIndex: 3, |
22 | preload: Infinity |
23 | }); |
24 | |
25 | const view = new View({ |
26 | projection: 'EPSG:3857', |
27 | center: [ 14135490.777017945, 4518386.883679577 ], |
28 | zoom: 17 |
29 | }); |
30 | |
31 | const map = new Map({ |
32 | layers: [ vworldBaseLayer, vworldHybridLayer ], |
33 | target: 'map', |
34 | view: view |
35 | }); |
Name | Type | Default | Description |
---|---|---|---|
controls | ol/Collection-Collection<ol/control/Control-Control> | Array<ol/control/Control-Control> | undefined |
ol/control/defaults | 지도 컨트롤 객체 |
pixelRatio | number |
window.devicePixelRatio |
기기 픽셀 비율 |
interactions | ol/Collection-Collection<ol/interaction/Interaction-Interaction> | Array<ol/interaction/Interaction-Interaction> | undefined |
||
keyboardEventTarget | HTMLElement | Document | string | undefined |
키보드 이벤트 대상 요소 | |
layers | Array<ol/layer/Base-BaseLayer> | ol/Collection-Collection<ol/layer/Base-BaseLayer> | ol/layer/Group-LayerGroup | undefined |
레이어 목록. 배열 뒤에 있을 수록 우선순위가 높아짐 | |
maxTilesLoading | number |
16 |
동시 로드 가능한 최대 타일 수 |
moveTolerance | number |
1 |
지도 이동 이벤트로 인식하기 위해 마우스가 움직여야할 최소 픽셀 |
overlays | ol/Collection-Collection<ol/Overlay-Overlay> | Array<ol/Overlay-Overlay> | undefined |
지도 오버레이 객체 | |
target | HTMLElement | string | undefined |
지도를 표시할 DOM 혹은 DOM 아이디 | |
view | ol/View-View | Promise<ol/View-View> | undefined |
지도 뷰 객체 |
Map
객체에 지금까지 선언한 객체들을 할당한다. target
에 지정된 DOM에 선언된 지도가 표시된다.
target: map
은 아이디가 map
인 DOM에 지도를 표시한다는 뜻이다. 꼭 아이디가 아니더라도 HTMLElement
를 할당할 수도 있다.
예제 확인하기 🔗
OpenLayers6 Sandbox - VWorld에서 이를 구현한 예제를 확인할 수 있다.
4가지 배경 지도와, 확장용 지도인 하이브리드 지도를 확인할 수 있다. 좌측 상단의 패널에서 배경지도를 변경하거나, 확장 지도를 On/Off 할 수 있다.
OSM에 비해 다양한 타입의 지도를 제공함과 동시에, 국내에 최적화된 지도임을 확인할 수 있다.
📆 작성일
2022-03-21 Mon 14:51:45
📚 카테고리
🏷️ 태그