개요

지오서버는 오라클 지원 기능이 내장되어 있지 않다. 확장을 통해 설치해야하는데 자세한 사항은 geoserver menual을 보면 알 수 있다.


위 링크를 타고 들어가서 'Installing the Oracle extension' 영역을 확인하면 geoserver download page. 로 이동한다. 또한 oracle datastore 설정 방법도 자세하게 나온다.

1. Oracle pluging download

메뉴얼을 확인해 보면 Oracle extension 을 다운로드 하라고 나와 있다.


설치된 geoserver의 버전을 확인하여 자신이 설치한 지오서버에 해당하는 버전을 선택한다.

버전확인은 설치된 지오서버 메인 페이지에서 확인하거나 geoserver 설치 디렉토리 루트에 VERSION.txt 파일에 적혀있다.


geoserver 해당 버전 다운로드 화면에서 아래쪽 'Extensions' 영역에 있는 버튼을 선택한다.


해당 라이브러리중 oracle을 찾아 다운로드

해당 라이브러리를 다운로드 하였다면 이제 ojdbc6.jar or ojdbc7.jar 를 다운로드 하자.

* ojdbc 라이브러리가 추가가 안되면 geoserver에서 사용할 수 있는 oracle저장소는 Oracle NG(JNDI)만 사용 할 수있다. JNDI형식으로 사용하려면 ojdbc를 다운로드 할 필요는없다.


2. jar 파일 추가 후 geoserver 재시작

ojdbc-6.jar 와 gt-jdbc-oracle-20-SNAPSHOT.jar 이두개의 jar를 지오서버가 설치되어 있는 루트 및 WEB-INF/lib 위치에 복사해준다.


이후 지오서버를 재기동하고 저장소 생성화면으로 가보자.

오라클 관련 extension이 추가된 것을 확인 할 수 있다.

클라우드가 주는 산업 구조 개편 기회를 가질 수 있다면...

국가정보화사업을 업으로 하는 필자의 입장에서 KLIS, 국가공간정보통합체계(이하 국통), UPIS 등 국토정보시스템의 기반 인프라 구성은 많은 의문점이 들게 한다. 국토정보시스템의 기반 인프라가 고마운 것은 수많은 서버로 인해 많은 유지관리 항목이 많은 것,
황당한 것은 굳이 저리 많은 장비가 필요했는지 여부, 화가 나는 것은 내가 낸 소중한 세금이 장비에 대한 유지보수 비용 명목으로 외국 기업으로 나간다는 것,
여기까지 생각이 도달하면, 언론에 공개되는 보도자료가 말하는 것처럼 공간정보산업은 일자리를 만들고 있는가 하는 것에 동의할 수 없게 된다.

국가공간정보통합체계(이하 국통)는
전통적으로 중앙정부, 지자체에서 업무별로 GIS시스템을 개별 구축하여 공간정보의 공유 및 활용도가 낮고 중복투자 문제 등이 발생했다. 이에 대한 개선으로 국통은 국가가 보유한 공간정보를 연계 또는 통합하여 공동 활용하기 위한 서비스 체계를 구축하는 원대한 비전을 가지고 구축되었다. 

국통은 중앙센터시스템을 기준으로 200개 이상의 기초자치단체, 15개 이상의 광역자치단계, 중앙부처가 EAI를 통해 행정망 내에서 연계되는 시스템 구성을 가진다.
EAI 연계는 정보 송수신 측에 있어 EAI Adapter를 필수적으로 요구한다. 국통에 포함되는 개별 기관의 국통 인프라는 EAI 서버를 시작으로 차이는 있겠지만, 자료처리서버, GIS 서버, 데이터베이스 서버, 저장서버(또는 스토리지) 등 다수의 서버 자원을 포함한다.
구성 특성에 따라 물리서버를 이용하든 가상서버를 사용하든 하겠지만, 중앙센터시스템을 빼더라도 2,000개 이상의 서버로 구성되어 있음이 추정된다.
물리서버라면 대부분 HP, IBM, DELL의 장비 일 것이고, 가상화 서버라면 기반 소프트웨어는 VMWare가 대부분을 차지할 것이다.

국가정보화예산 중 유지관리 예산에서 실제 이들 장비의 유지관리 비용으로 일정 부분 소요된다.
일반적으로 서버가 감가상각되는 기간이 5년이라고 할 때, 그 5년 동안 장비에 대한 유지관리 비용 및 예비 파트 비용이 지속적으로 소요되고 시스템을 유지하기 위하여 일정 기간 사용 후 장비 교체 수요가 발생한다. 100% 외산인 서버 장비의 경우 유지관리비용의 최대 수혜자는 결국 글로벌 서버 제조사일 수 밖없다. 
또한 가상화서버를 이용할 경우에도 상용 SW 등의 패치를 위한  비용 등은 지속적으로 지불될 것이다.
해마다 연말이 되면 각 자치단체 별로 해당 시스템의 유지관리를 위한 제안요청서가 나라장터에 공개된다. 자급율이 낮은 대부분의 자치단체는 이를 유지하기 위한 비용이 사용율과 비교할 때 그리 효율성이 높은 비용은 아닐 것이다.
심각한 문제는 이런 류의 시스템이 비단 국통 뿐만 아니라 KLIS, UPIS, 도로명주소 등 GIS라는 이름이 붙은 것은 거의 대부분이 이와 비슷한 구성을 가진다는 것이다. 국통을 포함한 국토정보시스템을 구성하는 물리적 서버 갯수 만으로도 이미 공간정보 전용 클라우드 운영의 타당성이 성립된다.

물리 서버를 제작하는 국산 기술력이 낮다거나 또는 국내 시장이 작아 경쟁력을 가질 수 없다는 등의 사유는 존재하겠지만, 적어도 서버 위에 설치되는 가상화 등의 SW영역 뿐이라도 국산SW가 사용되기를 조심스레 바라본다.
공공 부문이 국산SW를 외면한다면 관련 기술의 발전 및 산업 생태계 형성을 기대할 수 없다. 현재처럼 공공부분 대부분의 정보전산담장자가 외산SW를 선호하는 환경, 어쩔 수 없을 때 국산 SW를 선택하는 상황은 결코 바람직하지 않다.
정보화사업을 진행하다보면 대부분의 정보운영실 담당자는 안정성이 중요하기 때문에 VMWare, Oracle 등을 얘기하지만 국민의 세금으로 운영되는 국가시스템이 국산 SW를 외면하면 절대 국산 SW산업은 발전 할 수 없다.
또한 최근의 화웨이 문제에서 드러나듯이 정보시스템을 구성하는 개별 요소의 국산화는 외교 무대에서 자기 목소리를 낼  수 있는 수단이다.

물론 개발자들의 외산SW 선호도 문제이다. 개발자 스스로 공공부문에서라도 불편하지만 국산SW 환경에서 개발을 수행하는 것이 내 가치(수행 단가)를 올리는 가장 빠른 길임을 공감했으면 하면 바람을 가지고 있다.

결국 필자가 공간정보분야의 클라우드를 주장하는 이유는 공간정보 관련 정보시스템의 기반 인프라를 구성하는 물리적 서버 등 장비의 갯수를 줄이고, 클라우드 서비스 운영을 위한 SW 스택을 국산을 통해 이행하자는 것이다.
이를 통해 절약되는 비용만큼을 공간정보 응용 서비스를 개발하고 유지하는 비용으로 사용한다면, 지금보다 좋은 품질의 데이터 및 서비스를 제공하게 되지 않을까하는 막연한 기대를 하는 것이다.

길었지만 개인적 견해를 밝히자면, 다음과 같다.

1. 국통의 본 취지를 재해석하여 모든 기반 인프라는 한 곳으로 모은다.
2. 이를 효율적으로 관리하기 위한 방법으로써 국토정보 전용 클라우드를 구축하여 물리적 외산서버의 갯수를 최대한 줄인다.
3. 클라우드 관리 및 운영 SW는 기반기술의 축적을 위하여 국산SW를 적용한다.
4. 클라우드에 탑재하여 동작하는 GIS SW, 연계 SW, DBMS 등도 철저히 국산 SW를 적용한다.
5. 국산 SW가 존재하지 않을 경우 외산 SW가 아닌 공개SW를 사용한다.
6. 국통 또는 다른 시스템 운용을 위한 SW 요구조건을 명세화하여 이를 클라우드가 제공하는 서비스 카탈로그로 관리하고,
7. 이러한 요구조건을 만족하는 어떠한 국산SW라도 클라우드의 서비스 카탈로그로 등록한다.
8. 사용자는 서비스 카탈로그에 등록된 국산SW를 선택하여 개별(지자체) 시스템을 구성하도록 한다.
9. 이를 통해 국산SW의 판로를 제공해 주고, GIS업체가 정보화 사업이 아닌 솔루션 판매를 통한 매출구조를 가져갈 수 있도록 지원한다.


사실은 너무 어려운 얘기를 했습니다. Oracle, ESRI, VMware 등을 배재하고, 기반 인프라 구성을 얘기하는 것은 어쩌면 말도 안되는 주장으로 비춰질 가능성이 높을 테니..... 역적일까요?





 

개요

geoserver 대용량 데이터를 이미지 서비스에 사용하기 위하여 GeoWebCache를 사용하려고함

대상 데이터는 연속지적도 경북지역 데이터로 Postgresql에  해당 데이터를 적재하여 사용하려고 한다. 

1. 데이터 작업

1GB의 연속지적도_경북 지역의 데이터를 QGIS통해 Postgresql에 import한다.



2. GeoServer 레이어 등록

https://progworks.tistory.com/6?category=810021를 참고하여 저장소(postgresql)를 추가한다.

이후 해당 레이어에 타일레어를 생성한다.


GeoWebCache 생성

  • Number of tasks to use : 사용할 작업 수
  • Type of operation : 작업 유형
  • Grid Set : 좌표계 (4326, 900913)
  • Format : 이미지 포맷
  • Zoom start : 타일 생성 줌 레벨 시작
  • Zoom stop : 타일 생성 줌 종료 
  • Modifiable Parameters : geoserver 스타일 정보
  • Bounding box : minX, minY, maxX, maxY

submit 버튼을 전송한다.

이후에 해당 레이어에대한 task가 위 리스트로 보여지는데

현재 해당 레이어에 타일이 생성되고 있는 시간과 완료예정시간 등 작업에 대한 정보가 보여진다.

연속지적도_경북 지역에 데이터다 보니 약 6시간 정도의 예상시간이 보인다


지오서버에 데이터 디렉토리 루트에 'gwc' 라는 폴더가 있고 기본적으로 이폴더에 레이어에 이미지 파일이 저장된다.


해당 레이어를 확인

이미지를 가져오는데 네트워크 속도 대략 8ms 0.008초 정도걸렸다.



서비스바로가기

개요

WMS(Web Map Service) 제공을 위한 데이터 프로바이더 계층에 메인메모리 DBMS를 사용함. 메인메모리 DBMS는 국내 업체인 리얼타임테크의 "Kairos"를 사용하였음. 데이터 프로바이더로써 클라우드서비스가 제공하는 가상서버에 DBMS를 설치하고 PaaS가 제공하는 컨테이너에 WMS 어플리케이션을 적재함.

제조사 홈페이지 바로가기: http://www.realtimetech.co.kr



목적

GIS 응용 서비스 제공을 위하여 메인메모리 DBMS가 Disk DBMS와 비교할 때 어느 정도의 성능향상을 보이는지 확인함


환경구성

1. Server : Linux Container, 가상서버 위에 설치되는 DBMS
2. DBMS : Kairos (제조사:리얼타임테크)
3. WAS(Web Application Server) : Apache Tomcat


개발환경 및 배포

1. 이클립스에서 일반 웹앱을 제작하는 방법을 준수하고, 
   배포서버를 이클립스에 등록된 서버 중 CloudFoundry를 지정하고 연결계정을 등록하여 해당 서버로 배포함
2. 최초 제작된 웹 앱(WMS)을 복사하여 어플리케이션 명칭을 변경하여, 필요한 갯수만큼 클라우드(CloudFoundry)에 배포
   ( 웹 어플리케이션의 수평적 확장 적용)

구현

1. 다양한 데이터프로바이더 수용을 위해 성능제약이 존재하는 지오서버 등의 Pakage SW 사용을 배제하고
2. DBMS가 반환하는  GIS 자료구조( WKB, WKT)를 자바 도형(java.awt.Shape) 으로 변환하여 이미지 렌더링
  (흔히 말하는 GIS 엔진의 사용을 배제 : 이미 공간 DBMS가 훌륭한 GIS 서비스 엔진임)

구현결과

1. 연속지적도(전국 SHP 파일 용량 기준 약 30GB)를 기준으로 8개의 웹 앱으로 클러스터링 했을 경우,
   동일한 환경의 Disk DBMS (PostGIS)  대비 약 10배 이상의 성능 향상을 확인
2. 수평확장되는 웹 앱(WMS)의 갯수만큼 성능이 향상확인 (저비용 서버 확장)

성능향상을 위한 개선 사항

1. 인프라 레벨에서 물리 또는 가상으로 이용될 수 있는 가속장치가 있을 경우,
   렌더링시켜야하는 도면데이터 조회 후 이미지 렌더링 속도 약 20% 향상 가능
2. 데이터 프로바이더(DBMS) 계층의 수평적 확장으로 처리되는 WMS 서버의 갯수를 최적화 시킴으로써 동시에 수용할 수 있는 사용자 증가


적용 및 응용 분야

1. 실시간 변경되는 공간정보의 실시간 서비스 발행
2. 사용자에게 빨리 전달되야 하는 비싼(?) 데이터의 저장 및 서비스 발행에 유용


결론

1. 동일한 환경 조건일 경우, 메인메모리 DBMS가 일반적인 DBMS가 월등한 성능을 보이는 것을 확인
2. 제한적인 메모리의 용량을 고려할 때 메인메모리에 적재되어야 하는 데이터의 식별이 중요함


서비스 바로가기

> 서비스 비교 (Disk 기반 웹 맵서비스)



안녕하세요 캡틴개구리입니다.

이번시간은 Openlayers3(OL3)와 Leaflet에 Feature 이벤트 연동을 알아보겠습니다.

Feature Event 요약 기능

 - 지도 마커 클릭 시, 팝업 창 호출

 - 지도 클릭 시, 좌표정보 호출


그전에 결과화면부터 보겠습니다.

서비스바로가기


Openlayers3 와 Leaflet 라이브러리를 받을 수 있는 곳은 아래와 같습니다. 

OpenLayers3 :  https://openlayers.org/ 

Leaflet : http://leafletjs.com/

VWORLD :  http://map.vworld.kr



1. Openlayers3 Feature Event 추가


활용라이브러리 : ol.Map, ol.layer.Tile, ol.source.Vector, ol.layer.Vector, ol.Feature, ol.geom.Point, ol.style.Style, ol.style.Icon, ol.Overlay 


먼저 Openlayers3(이하 OL3)  <script></script>부분입니다.


OL3 지도 및 마커 띄우기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<script>
    //openlayers 지도 띄우기
    var iconFeature = new ol.Feature({
        //아이콘 위치좌표
        geometry: new ol.geom.Point([14129600.824512500.74]),
        name'I am a Progworks.',
    });
 
    var iconStyle = new ol.style.Style({
        image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
            anchor: [146],
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            src: 'https://openlayers.org/en/v3.20.1/examples/data/icon.png'
        }))
    });
 
    iconFeature.setStyle(iconStyle);
    var vectorSource = new ol.source.Vector({
        features: [iconFeature]
    });
 
    var vectorLayer = new ol.layer.Vector({
        source: vectorSource
    });
     
    var raster = new ol.layer.Tile({
        source: new ol.source.XYZ({
            url: 'http://xdworld.vworld.kr:8080/2d/Base/201802/{z}/{x}/{y}.png'
        })
    });
        
    var map = new ol.Map({
           
        layers: [raster,vectorLayer],
          
        target: document.getElementById('map'),
          
        view: new ol.View({
          center: [14129600.824512500.74],
          maxZoom: 19,
          zoom: 14
        })
    });
</script>
cs

다음은 Feature Event를 가져오도록 하겠습니다. 참고로 OL3에서는 마커 표시와 지도의 좌표정보 불러오기가 별도의 example로 존재합니다.

각각의 example를 하나로 합치면서 OL3에서 제공하는 소스와는 조금 다르다는점 참고하시면 좋을것 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<script>
    var element = document.getElementById('popup');    
    var coordElement = document.getElementById('olPopup');
    
    var popup = new ol.Overlay({
        element: element,
            positioning: 'bottom-center',
            stopEvent: false,
            offset: [-18-50]
    });
    map.addOverlay(popup);
    
    map.on('click'function(evt) {
        var feature = map.forEachFeatureAtPixel(evt.pixel,function(feature) {
            return feature;
        });
        if (feature) {
            
            var coordinates = feature.getGeometry().getCoordinates();
            popup.setPosition(coordinates);
            $(element).popover({
              'placement''top',
              'animation'false,
              'html'true,
              'content': feature.get('name')
            });
            $(element).popover('show');
            $(coordElement).popover('destroy');
        } else {
            $(element).popover('destroy');
        }
    });
    
    var olPopup = new ol.Overlay({
        element: document.getElementById('olPopup')
    });
    map.addOverlay(olPopup);
 
    map.on('click'function(evt) {
        var feature = map.forEachFeatureAtPixel(evt.pixel,function(feature) {
            return feature;
        });
        
        if(feature == null){
            var coordinate = evt.coordinate;
            var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(coordinate, 'EPSG:3857''EPSG:4326'));
    
            $(coordElement).popover('destroy');
            olPopup.setPosition(coordinate);
            $(coordElement).popover({
                'placement''top',
                'animation'false,
                'html'true,
                'content''<p>현재 위치 좌표정보</p><code>' + hdms + '</code>'
            });
            $(coordElement).popover('show');
        } else{
            $(coordElement).popover('destroy');
        }
    });
 
        // change mouse cursor when over marker
    map.on('pointermove'function(e) {
        if (e.dragging) {
            $(element).popover('destroy');
            return;
        }
        var pixel = map.getEventPixel(e.originalEvent);
        var hit = map.hasFeatureAtPixel(pixel);
        map.getTarget().style.cursor = hit ? 'pointer' : '';
    });
</script>
cs

5행 : 마커 클릭 시, 나타나는 팝업의 위치 구현

13행~32행 : OL3 map 클릭 이벤트 (마커)

34행 : 지도 클릭 시, 좌표정보 팝업의 위치구현

39행~60행 : OL3 map 클릭 이벤트 (지도)

63행~71행 : 마커 위로 마우스 이동 시 포인터 활성화 및 지도 좌표정보 팝업 숨김 구현

OL3 Feature Event <body></body>입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
    <div class="container-fluid">
        <div class="row content">
            <div class="col-sm-6" style="border-right: 1px solid;">
                <h1>Oepnlayers 3</h1>
                <div id="map" class ="map">
                    <div id="popup"></div>
                </div>
                <div style="display: none;">
                    <div id="olPopup" title="Welcome to ol3"></div>
                </div>
            </div>
        </div>
    </div>
</body>
cs


2. Leaflet Feature Event

활용라이브러리 : L.map, L.tileLayer, L.marker, L.popup


먼저 leaflet  <script></script>부분입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
//leaflet 지도 띄우기
    var leafletMap = L.map('leafletMap').setView([37.5247030824278714129046.928310394],14)
    //Vworld Tile 변경
    L.tileLayer('http://xdworld.vworld.kr:8080/2d/Base/201802/{z}/{x}/{y}.png').addTo(leafletMap);
    
    var marker = L.marker([37.5247030824278714129046.928310394]).addTo(leafletMap)
        .bindPopup("I am a Progworks.").openPopup();
    
    var leafletPopup = L.popup();
    
    function onMapClick(e) {
        leafletPopup
            .setLatLng(e.latlng)
            .setContent("현재 위치 좌표정보 <br>" + e.latlng.toString())
            .openOn(leafletMap);
    }
 
    leafletMap.on('click', onMapClick);
});
</script>
cs


이번에도 지도는 VWORLD를 이용했습니다.

3행~ 5행 : 지도 띄우기
7행~8행 : 마커 위치 및 내용 넣기
10행 : 팝업
12행 : 클릭이벤트

다음은 <body></body>입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<body>
    <div class="container-fluid">
        <div class="row content">
            <div class="col-sm-6" style="border-left: 1px solid;">
                <h1>leaflet</h1>
                <div id="leafletMap"></div>
            </div>
            <div class="col-sm-6" style="border-right: 1px solid; border-top: 1px solid;">
                
            </div>
            <div class="col-sm-6" style="border-left: 1px solid; border-top: 1px solid;">
                
            </div>
        </div>
    </div>
</body>
cs

결과화면은 아래와 같습니다.

서비스바로가기

1. Raster Image 와 Vector Graphics의 정의

일부 GIS 웹 사이트를 보게 되면 WMS와 WFS의 선택이 부적절하여 서비스 성능을 떨어뜨리는 경우가 있다. 본 글을 통해 어플리케이션 구성에 있어 WMS와 WFS 선택 기준을 설명한다.

Raster Image는 흔히 Smart Phone의 카메라를 통해 생성되는 JPEG, PNG 등의 형식을 가지는 데이터를 의미한다. 각각의 포맷 별로 저장되고 압축되는 방식의 차이가 존재하지만 기본적으로 흔히 Pixel 이라고 부르는 것에 입력되는 색상으로 표현되는 데이터라고 할 수 있다.
OGC의 WMS(Web Map Service)는 HTTP를 통해 Raster Image를 제공하는 서비스이다.

Vector Graphics는 흔히 좌표라고 부르는 위치를 지정하는 요소의 연결을 통해 구성되는 데이터를 의미한다. GIS 분야에서 GeoJSON, KML, GML, ESRI SHP 등으로 정의되는 형식이라고 할 수 있다.
OGC의 WFS(Web Feature Service)는 HTTP를 통해  Vector Data 를 제공하는 서비스이다.


2. Raster Image 와 Vector Graphics의 특징

Raster Image의 경우 저장되는 포맷에 상관없이 메모리에 풀린 상태라면 가로 1024px, 세로 1024px 크기의 TRUE COLOR ( RED, GREEN, BLUE) 이미지라면 3MB의 크기를 가진다.
즉, 이미지 생성을 위한 원본 데이터의 크기에 상관없이 렌더링 되는 이미지의 가로, 세로 크기만큼만의 사이즈를 가진다. 국가공간정보포털이 제공하는 연속지적도 서울지역 SHP파일의 경우 약 1.5 GB 이지만, 1024px * 1024px * 3Bands (RED, GREEN, BLUE)의 Raster Image로 렌더링되면 결국 3Mb 의 크기만 가질 것이다. 물론 저장되는 포맷에 따라 압축이 됨으로 실제 생성되어 전송되는 크기는 수백KB 일 것이다.

Vector Graphics의 경우 지형을 표현하는 도형이 가지는 좌표 셋을 그대로 반환함으로써 원본 크기만큼의 전송 양을 가지게 될 것이다.
즉, 국가공간정보포털이 제공하는 연속지적도 서울지역 SHP파일의 경우 약 1.5 GB이므로 , 전송되는 데이터 양 또는 이와 같을 것이다.


3. WMS와 WFS의 성능향상을 위한 확장 기법

WMS에서 Raster Image는 지리 공간 상의 도형 형상 좌표를 이미지 픽셀 좌표로 변환하는 과정(AffineTransform)과 컬러링 과정이 요구됨으로 사용자의 서비스 요청 처리에 있어 비교적 많은 Computing Power를 사용한다.
이러한 특징으로 이미지 생성 성능 향상을 위해서는 수직적 확장(CPU 추가, Memory 추가, GPU 주가등)이 우선 고려되어야 한다.

WFS에서 Vector Graphics는 원 데이터 소스가 가지는 지형 도형을 반환 포맷에 맞도록 텍스트 렌더링 과정만 있음으로 비교적 적은 Computing Power를 사용한다.
이러한 특징으로 Vector Data 생성을 위한 성능향상은 사용자 수용 능력 향상 측면에서 접근되며, 이를 위해 수평적 확장 (서버 증설:로드밸런싱, 클러스터링)이 요구된다. 그러나 서버가 많은 데이터를 반환해야 한다면 네트워크 부하가 중요 고려요소가 될 수 밖에 없다.


4. WMS와 WFS의 선택

WMS와 WFS의 선택에서 고려해야 할 것은 

  • 렌더링 되야 하는 원본 데이터의 크기로써, 원천 데이터의 크기가 크다면 WMS가 유리할 것이다.
  • 사용자 페이지를 기준으로 각 객체에 이벤트가 연동되어야 한다면 어쩔 수 없이 WFS가 선택지 일 것이다. 
  • 그러나 위 경우에도 전체 형상 확인을 위해 WMS를 호출하고, 마우스이벤트 등과 연결하여 개별 객체를 호출하는 방식으로 페이지를 구성하는 것이 효율적일 수도 있다. 


안녕하세요 캡틴개구리입니다.

이번시간은 Openlayers3(OL3)와 Leaflet에 Static Image를 올려보겠습니다.

그전에 결과화면부터 보겠습니다.

서비스바로가기


Openlayers3 와 Leaflet 라이브러리를 받을 수 있는 곳은 아래와 같습니다. 

OpenLayers3 :  https://openlayers.org/ 

Leaflet : http://leafletjs.com/


활용 좌표계 : EPSG 4326


1. Openlayers3 및 Leaflet Image Overlay(Static Image)


이번에는 소스가 그렇게 길지 않고 간단하여 OL3와 Leaflet을 함께 진행해보도록 하겠습니다.


OL3 활용 라이브러리 : ol.Map, ol.layer.Tile, ol.layer.Image, ol.source.ImageStatic, ol.View

Leaflet 활용 라이브러리 : L.map, L.tileLayer, L.imageOverlay


<script></script>부분입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<script type="text/javascript">
 

    //openlayers3
    var extent = [126.92462837.518308126.92662837.520308]  // image size is 128x128 px
    
    var map = new ol.Map({
        
        layers: [
              new ol.layer.Tile({
                
                source: new ol.source.OSM()
              }),
              new ol.layer.Image({
                  source: new ol.source.ImageStatic({
                    url: '/images/common/example5OL.png',
                    crossOrigin: '',
                    projection: 'EPSG:4326',
                    imageExtent: extent
                  })    
              })
        ],
        target: 'map',
        view: new ol.View({
            projection : 'EPSG:4326',      
            center: extent,
            zoom: 16
            
        })
    });
    
    //leaflet 지도
    var leafletMap = L.map('leafletMap').setView([37.518308126.924628],16)
    
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(leafletMap);
    
    var imageUrl = '/images/common/example5Leaflet.png',
        imageBounds = [[37.518308126.924628], [37.520308126.926628]];
 
    L.imageOverlay(imageUrl, imageBounds).addTo(leafletMap);
    

</script>
cs

OL3와 Leaflet에서 Image를 Overlay함에 있어서 가장 중요한 부분은 좌표계였던것 같습니다. 그리고 

OL3 Extent는 경도 위도 순으로 [minX, minY, maxX, maxY] 넣어주시면 됩니다. 

Leaflet imageBounds는 위도 경도 순으로 [[minY,minX],[maxY,maxX]] 넣어주시면 됩니다.

저는 프로그웍그 로고를 넣었습니다 ㅎㅎㅎ

<body></body>부분입니다.

1
2
<div id="map"></div>
<div id="leafletMap"></div>
cs


마지막으로 이 기능은 어디에 사용할까요? 혹시 현재 지도 위에 옛날 고지도 또는 일부 지역의 위성영상 등을 오버레이 할 때 사용합니다.

결과화면은 아래와 같습니다.


서비스바로가기

안녕하세요 캡틴개구리입니다. 

OpenLayers3(OL3)와 Leaflet에서 Feature Clustering을 알아보도록 하겠습니다. 

그전에 결과화면부터 보겠습니다.

서비스바로가기


Openlayers3 와 Leaflet 라이브러리를 받을 수 있는 곳은 아래와 같습니다. 

OpenLayers3 :  https://openlayers.org/ 

Leaflet : http://leafletjs.com/

VWORLD :  http://map.vworld.kr


leaflet.zip

 첨부파일(.Zip)은 leaflet에서 클러스터링을 진행하기 위해 추가적으로 필요한 자료들입니다. 


1. Openlayers3(이하 OL3)


활용 라이브러리 : ol.format.GeoJSON, ol.source.Vector, ol.loadingstrategy.bbox, ol.source.Cluster, ol.layer.Vector, ol.style.Style, ol.style.Stroke, ol.style.Fill

ol.style.Text, ol.layer.Tile, ol.source.XYZ, ol.Map, ol.View


지난시간에 알려드린 Openlayers3에서 wfs를 올리는 방법에 기초하여 소스 추가를 통해 Feature Clustering을 진행해보겠습니다.

<script></script>부분부터 살펴보도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<script type="text/javascript">
    //Openlayers3
    var distance = 30;
    var format = new ol.format.GeoJSON();
    
    var vectorSource = new ol.source.Vector({
        format : format,
        url: function(extent) {
            return 'http://***.****.***/geoserver/progworks/wfs?service=WFS&' +
                'version=1.1.0&'+
                'request=GetFeature&'+
                'typename=progworks:lptd_ldreg_dogeun_point_info_2&' +
                'outputFormat=application/json&'+
                'srsname=EPSG:3857&' +
                'bbox=' + extent.join(','+ ',EPSG:3857';
        },
        strategy: ol.loadingstrategy.bbox
    })
    
    var clusterSource = new ol.source.Cluster({
        distance: parseInt(distance, 30),
        source: vectorSource
    });
    
    var styleCache = {};
    var clusters = new ol.layer.Vector({
        source: clusterSource,
        style: function(feature) {
            var size = feature.get('features').length;
            var style = styleCache[size];
            if (!style) {
                style = new ol.style.Style({
                    image: new ol.style.Circle({
                        radius: 20,
                        stroke: new ol.style.Stroke({
                            color: '#ffffff'
                            
                        }),
                        fill: new ol.style.Fill({
                            color: '#ff9933'
                        })
                    }),
                    text: new ol.style.Text({
                        text: size.toString(),
                        font:'Bold 20px Verdana',
                        fill: new ol.style.Fill({
                            color: '#ffffff'
                            
                            
                        })
                    })
                });
            styleCache[size] = style;
            }
        return style;
        }
    });
    
    var raster = new ol.layer.Tile({
        source: new ol.source.XYZ({
            url: 'http://xdworld.vworld.kr:8080/2d/Base/201802/{z}/{x}/{y}.png'
        })
    });
    
    var map = new ol.Map({
        
        layers: [raster,clusters],
       
        target: document.getElementById('map'),
       
        view: new ol.View({
          center: [14128579.824512570.74],
          maxZoom: 19,
          zoom: 10
        })
    });
});
</script>
cs

소스가 점점 길어지는거 같습니다... ㅠㅠ 하하하하하 

먼저 Feature Clustering를 위해 데이터는 불러와야합니다. 데이터 출저는 "국가공간정보포털 오픈마켓의 지적도근점 정보를 이용하였습니다.

데이터는 wfs으로 불러와 변수 vectorSource에 담았습니다.

그후 clusterSource에서 wfs방식으로 불러온 데이터를 활용하여 Cluster를 진행하였습니다. 그 이후 스타일 지정 이후 map에서 layers로 스타일이 지정된 변수 clusters를 불러오면 끝입니다. 

<boby></body>부분은 아래와 같습니다.

1
<div id="map"></div>
cs


2. Leaflet

활용 라이브러리 : L.map, L.tileLayer, L.Util.extend, L.Util.getParamString, L.geoJson, L.markerClusterGroup

<script></script>부분부터 살펴보도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<script type="text/javascript">
//Leaflet
    var leafletMap = L.map('leafletMap').setView([37.52470308242787126.9234],10)
    L.tileLayer('http://xdworld.vworld.kr:8080/2d/Base/201802/{z}/{x}/{y}.png').addTo(leafletMap);
    
    var owsrootUrl = 'http://***.****.***/geoserver/progworks/wfs';
    
    var defaultParameters = {
        service : 'WFS',
        version : '1.1.0',
        request : 'GetFeature',
        typeName : 'progworks:lptd_ldreg_dogeun_point_info_2',
        outputFormat : 'application/json',
        format_options : 'callback:getJson',
        SrsName : 'EPSG:4326',
    };
    
    var parameters = L.Util.extend(defaultParameters);
    
    var URL = owsrootUrl + L.Util.getParamString(parameters);
    
    var WFSLayer = null;
        
    var ajax = $.ajax({
        url : URL,
        dataType : 'json',
        jsonpCallback : 'getJson',
        success : function(response){
            markers.addLayer(L.geoJson(response));
        }
    });
    
    var markers = L.markerClusterGroup({
        //Disable all of the defaults:
        spiderfyOnMaxZoom: true, showCoverageOnHover: false, zoomToBoundsOnClick: false
    });
    
    leafletMap.addLayer(markers);
</script>
cs

Leaflet에서도 Openlayers3에서 데이터를 불러왔던 wfs형태로 데이터를 불러오도록 하겠습니다.

Leaflet Feature Clustering에서 가장 중요한 부분은 29행부터 입니다.!!!!!!!!

JQuery ajax를 이용하여 wfs형태의 데이터로 불러온 데이터를 기존에는 바로 " addTo(leafletMap); "  했지만 이번에는 변수 markers에 담아줍니다.

이렇게 " markers.addLayer(L.geoJson(response)); " 이후 L.markerClusterGroup 함수를 이용하여 Clusterring이 진행됩니다.

그리고 그렇게 진행된 markers를 " leafletMap.addLayer(markers); "를 해주시면 끝이납니다.

<boby></body>부분은 아래와 같습니다.

1
<div id="leafletMap"></div>
cs


결과화면은 아래와 같습니다.


서비스바로가기


서비스바로가기

개요

PostGIS의 좌표 변환 SQL을 이용하여 좌표변환(Coordinates Transformation)을 진행하고 웹에 게시함 

geometry ST_Transform(geometry g1, integer srid);
geometry ST_Transform(geometry geom, text to_proj);
geometry ST_Transform(geometry geom, text from_proj, text to_proj);
geometry ST_Transform(geometry geom, text from_proj, integer to_srid);




목적

PostGIS 가 지원하는 좌표변환(ST_Transform) 함수가 국내에서 이용되는 좌표계에서 정확한 전환을 제공하는지 확인함


환경구성

1. Server : Linux Container, 가상서버 위에 설치되는 DBMS
2. DBMS : Postgre + PostGIS
3. WAS(Web Application Server) : Apache Tomcat


개발환경 및 배포

1. 이클립스에서 일반 웹앱을 제작하는 방법을 준수하고, 
   배포서버를 이클립스에 등록된 서버 중 CloudFoundry를 지정하고 연결계정을 등록하여 해당 서버로 배포함

구현

1. Datum 변환을 위한 축적계수가 등록되지 않은 5174좌표계에 대한 정확한 정의를 Postgre에 신규 등록 (User Custom SRS)
2. ST_Transform 함수를 이용하여 주요 업무기능 제작

구현결과

1. EPSG Database 에 등록된 좌표계 및 국내 좌표계에서의 전환을 정확하게 수행함을 확인함
2. 저사양 서버환경에서도 단 건 좌표변환의 경우 충분한 응답속도를 보이는 것을 확인


이용 제약 사항

1. 웹기반 환경에서 대용량 좌표 셋의 좌표 변환은 서비스 제공 여부는 지양하는 것이 좋음 


2. 위 그림에서와 같이 타원체가 변하는 투영좌표계(Projection Coordinate System) 에서 투영좌표계로 변환하는 것은 7번의 전환과정을 요구함
3. 이 때 순간적으로 많은 연산이 요구됨으로써 비교적 과도한 컴퓨팅 파워를 요구함
4. 따라서, 대용량 데이터의 좌표변환을 실시간으로 처리하는 로직의 적용 여부는 신중을 기해야 함


결론

1. PostGIS의 기본 설정만으로도 훌륭한 좌표변환서비스가 가능함을 확인


서비스 바로가기



ESRI Shapefile Technical Description 

에스리 쉐이프파일 기술 설명


* 본 문서는 ESRI 社에서 제공한 ESRI Shapefile Technical Description 국문 번역본입니다.

본 문서는 독자들로 하여금 Shapefile에 대한 이해를 돕기위해 의역하였습니다.

쉐이프파일에 대한 정의와 사용되는 이유, 그리고 쉐이프파일의 생성 방법과 파일의 조직 및 구성에 대해 기술되어있습니다.




* 원본 문서 (영문)

ESRI Shapefile Technical Description (영문).pdf


* 번역 문서 (국문)

ESRI Shapefile Technical Description (국문).pdf


+ Recent posts