DuraMap-Xr의 SpatialOperator를 이용한 공간연산 응용예

DuraMap-Xr은 Windows 기반의 Desktop GIS Application 개발을 위한 맵 엔진입니다. DuraMap-Xr의 기능 중 SpatialOperator 기능은 벡터 데이터 간의 Intersects나 Intersection과 같은 API와 단일 벡테 데이터의 Buffer 연산자와 같은 API를 제공합니다. 이러한 연산자를 이용하여 다음과 같은 기능에 DuraMap-Xr이 활용되었는데요. 간단히 소개해 봅니다.

위의 그림은 건물 레이어와 홍수범람에 대한 하천 레이어 그리고 행정구역도 레이어로 구성된 간단한 지도입니다. 건물 레이어의 건물 도형 데이터에는 인구수에 대한 속성 데이터가 조인되어 있습니다. 건물 중 홍수범람에 대한 하천 레이어의 도형과 교차(Intersects)되는 건물을 추출하고 추출된 건물에 거주하는 인구수의 총합을 계산해야 합니다. 바로 이 인구수가 홍수에 의한 피해 인구수라고 생각할 수 있습니다.

위의 UI는 위에서 설명한 기능에 대해 실제 구현한 UI입니다. 홍수피해의 결과로 4006명이 산출되었고, 피해를 받은 건물은 result.shp 파일로 저장되도록 하였습니다.

위의 이미지에서 빨간색 도형이 기능에 대한 결과로 생성된 홍수 피해를 받은 건물에 대한 레이어어 입니다. 이미지를 살펴보면, 건물이 하천 경계 도형으로 클리핑(Intersection) 처리 되어 저장된 것을 볼 수 있습니다.

DuraMap-Xr은 우리가 흔히 알고 있는 지도 위에 도형 매쉬업이라는 단순한 기능에서 한발 더 나아가 각 도형들간의 관계와 연산을 통해 더욱 의미 있는 결과를 생성해 내는 GIS 엔진입니다.

Node.js 정리

자바스크립트로 서버 어플리케이션을 개발할 수 있는 Node.js는 다음과 같은 특징을 갖습니다.

  • 단일 스레드 기반으로 동작함으로써 직관적이고 단순해 안정적이라고 할 수 있음. 특히 스레드간 데이터 동기화등에 대한 골치 아픈 문제가 근본적으로 없다는 점이 큰 장점이지만, 스레드에 숙련된 개발자에게는 한계가 될 수 있음
  • 단일 스레드 기반이므로 클라이언트 측의 요청에 대한 빠른 응답에 대한 처리는 비동기 IO 방식을 활용함
  • 위의 2가지의 특징과 자바스크립트라는 한계로 인해 서비스 내용을 생성하는데 아주 짧은 시간을 필요로 하는 경우에 대한 서버 개발에 알맞음. 즉, CPU에 너무 많은 부하를 주는 연산이 아닌 간단하고 명료한 서비스에 적합함. 간단하고 명료하다는 기준은 서버의 사양 등에 따라 매우 상대적임.
  • 흔히 Node Application이라고 하는 것은 Node.js로 개발한 서버 프로그램을 언급하는 것임
  • npm이라는 기능을 통해 Node.js의 확장기능을 추가로 설치할 수 있는데, 확장 기능의 개발과 npm과 같은 손쉬운 추가 방식은 Node.js의 장점 중 특장점이라고 할 수 있음

뭐 일단, 이제는 내 스스로에게 상당히 친숙하고 호감도가 높아진 자바스크립트라는 언어를 통해 서버를 개발할 수 있다는 점에서 Node.js는 충분히 매력적이라고 할 수 있는데요. 특히 스크립트이기 때문에 소스코드를 변경하면 바로 해당 변경 내용을 쉽게 배포할 수 있다는 점이 가장 매력적이라고 할 수 있습니다. 게다가 퍼포먼스 적인 측면에서 V8이라는 자바스크립트 엔진을 사용함으로써 생각 이상으로 상당히 뛰어나다라는 평가 역시 매우 큰 장점입니다. 몇가지 Node.js에 대한 간단한 샘플 코드를 통해 웹상에서 수집한 Node.js에 대한 내용을 정리해 보겠습니다.

먼저 가장 간단한 Node.js의 샘플 코드입니다.

var http = require('http');

http.createServer(
  function(request, response) {
    response.writeHead(200, { 'Content-Type' : 'text/plain' });
    response.write("Hello, I am a Korea! GIS Developer.");
    response.end();
  }
).listen(8888);

위의 코드는 8888 포트를 통해 HTTP 서버(웹서버) 기능을 가진 프로그램 코드로 클라이언트에게 고정된 문서를 서비스하는 코드입니다.

다음은 URL을 통한 QueryString을 받아 해석하는 코드입니다.

var http = require('http');
var url = require('url');

var server = http.createServer();

server.addListener('request', function(request, response) {
  console.log('requested ...');

  response.writeHead(200, {'Content-Type' : 'text/plain'} );
  var parseUrl = url.parse(request.url, true);
  //var pathname = parseUrl.pathname;
  var query = parseUrl.query;
 
  response.write("a for QueryString : " + query.a);
  response.end();
});

server.listen(8888);

QueryString으로 a=123으로 주었을 경우, a for QueryString : 123 과 같은 문서를 서비스할 것입니다. 주석으로 처리된 pathname은, 예를 들어 http://www.gisdeveloper.co.kr:8888/Hello?a=133과 같은 URL 호출일 경우 Hello가 됩니다.

다음은 POST 방식을 통한 호출에 대한 코드 예입니다.

http = require('http') ,qs = require('querystring');

http.createServer(function (req, res) {
  if( req.url == '/' && req.method == 'POST'){
    var postBody = '';

    req.on('data', function (data) {
      postBody += data;
    });

    req.on('end', function () {
      var post = qs.parse(postBody);
      //post데이터확인
      console.log(post['postname']);
    });

    res.end('true');
  } else {
    res.writeHead(404, {'Content-Type': 'text/plain'});
    res.end('404 ERROR');
}
}).listen(8888);

끝으로 Node.js와 DBMS 연동에 대한 코드인데요. DBMS는 MongoDB로써 Node.js는 MongoDB와의 연동을 위해 Mongoose 모듈을 사용합니다. 이 Mongoose는 npm을 통해 설치할 수 있습니다. 참고로 버전 2.7대의 파이션이 필요합니다.

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/myDB');

var db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback() {
  console.log('open');
});

var userSchema = mongoose.Schema({
  username: 'string',
  age: 'number'
});

var User = mongoose.model('User', userSchema);

var user1 = new User({ username: 'gchoi', age: 30 });
var user2 = new User({ username: 'jmpark', 'age': 29 });

user1.save(function (err, user1) {
  if(err) 
    console.log('error');
});

user2.save(function (err, user2) {
  if(err)
    console.log('error');
});

이상으로 예제 코드를 중심으로한 Node.js에 대한 내용을 정리해 보았습니다.

Leaflet 강좌 ㅡ 4. 지도 이벤트 살펴보기

이 글은 강좌 2에 이어 지도의 이벤트를 사용하는 내용에 대한 정리로써, 클릭(click) 이벤트를 예로 소개합니다.이 강좌의 진행을 위해 강좌 2에서 작성한 코드가 꼭 필요하니 바로 가져오기 바랍니다.

아래의 코드를 onLoad 함수의 마지막에 추가합니다.

var popup = L.popup();

function onMapClick(e) {
    popup.setLatLng(e.latlng)
        .setContent("당신은 지도를 클릭했고만, 바로 " + e.latlng.toString())
        .openOn(map);
    }

    map.on('click', onMapClick);

먼저 9번 코드가 지도에 대한 클릭 이벤트를 설정하고 있습니다. 첫번째 인자값인 click가 바로 클릭 이벤트 지정입니다. 그리고 두번재 인자에 클릭시 호출할 함수를 지정합니다. 이 함수는 3번~7번 코드에서 살펴볼 수 있습니다. 강좌3에서 설명한 Popup 객체를 사용하고 있습니다. 1번 코드에서 사용자가 클릭하면 표시될 팝업 객체를 미리 생성해 놓고 있습니다.

실행 결과는 아래와 같습니다. 아래의 지도 화면을 클릭해 보시기 바랍니다.

이상으로 기본적인 leaflet에 대한 API를 학습하면서, 총 4개의 글을 정리해 보았습니다. leaflet은 일반 사용자가 가지고 있는 위치 기반 데이터를 쉽게 매쉬업하고, 지도를 기반으로 다양한 기능을 구현할 수 있는 좋은 웹 GIS 엔진이라고 생각됩니다.

Leaflet 강좌 ㅡ 3. 지도에 팝업(Popup) 표시하기

이 글은 강좌 2에 이어 지도에 팝업을 표시하는 내용에 대한 정리입니다. 이 강좌의 진행을 위해 강좌 2에서 작성한 코드가 꼭 필요하니 바로 가져오기 바랍니다.

지도 상에 파업을 표시하는 경우는 크게 2가지로써, 첫번째 사용자가 지도에 추가한 그래픽 요소를 클릭했을때 표시되는 팝업, 두번째로 사용자가 지정한 좌표 위에 파업을 표시하는 것입니다. 먼저 사용자가 지도에 추가된 그래픽 요소를 클릭했을 때 표시되는 파업에 대한 API를 살펴 보겠습니다.

이미 강좌2에서 마커, 원, 폴리곤에 대한 3개의 그래픽 요소를 추가했습니다. 아래의 코드를 onLoad 함수의 가장 마지막 부분에 추가합니다.

marker.bindPopup("Hello world!
I am a popup.").openPopup(); circle.bindPopup("I am a circle."); polygon.bindPopup("I am a polygon.");

marker와 circle 그리고 polygon 변수는 강좌 2에서 작성한 그래픽 요소를 참조하고 있는 변수입니다. 이 변수에 bindPopup 함수를 호출함으로써 각 그래픽 요소를 클릭할때 표시할 팝업을 지정할 수 있습니다. 표시할 팝업은 HTML 태그로 작성할 수 있으므로 매우 유연하고 자유롭게 내용을 구성할 수 있습니다. 1번 코드를 보면 marker에 대해서는 openPopup 함수를 호출하고 있습니다. 이는 사용자가 해당 요소를 클릭하지 않아도 기본적으로 팝업이 표시되도록 하는 함수입니다. 실행 결과는 아래와 같습니다.

이제 다음로 개발자가 지정한 임의의 좌표에 팝업을 표시하는 코드에 대해 살펴 보겠습니다. onLoad 함수 가장 마지막에 아래와 같은 코드 한줄을 추가합니다.

var popup = L.popup()
    .setLatLng([51.5, -0.09])
    .setContent("I am a standalone popup.")
    .openOn(map);

위의 코드를 보면 Popup 객체를 생성하고 표시될 좌표와 내용을 지정하고 openOn 함수를 호출함으로써 바로 지도에 팝업을 표시하도록 합니다. 실행 결과는 아래와 같습니다.