dat.GUI의 API 정리

dat.GUI는 값을 GUI를 통해 직관적으로 변경하여 기능을 테스트해 볼 수 있는 javascript 기반의 매우 직관적인 라이브러리입니다.

dat.gui를 js에서 사용하기 위해 간단히 CDN을 통해 아래처럼 페이지에 스크립트를 포함할 수 있습니다.


아래는 dat.GUI의 가장 간단한 예제입니다.

var MyData = function() {
    this.dataString = "Dip2K";
    this.dataNumber = 0.7;
    this.dataBoolean = false;
    this.dataFunction = function() {
        alert(
            "dataString: " + this.dataString + "\n" +
            "dataNumber: " + this.dataNumber + "\n" +
            "dataBoolean: " + this.dataBoolean
        );
    };
};

window.onload = function() {
    var myData = new MyData();
        
    var gui = new dat.GUI();
   
    gui.add(myData, "dataString");
    gui.add(myData, "dataNumber");
    gui.add(myData, "dataBoolean");
    gui.add(myData, "dataFunction");
}

관리하고자 하는 데이터는 함수에 대한 new 호출을 통한 this에 바인딩되어져야 합니다. 위의 코드를 실행해 보면 아래와 UI가 페이지의 우측 상단에 표시됩니다.



위의 UI에서 보는 것처럼 함수의 new 호출로 this에 바인딩된 dataString, dataNumber, dataBoolean, dataFunction은 각각의 데이터 타입에 따라 적절한 UI로 표시되며 사용자가 쉽게 변경할 수 있습니다. function 타입의 데이터는 버튼 UI로 표시되며 버튼 클릭시에 해당 함수가 호출됩니다.

이 정도만 되어도 dat.gui를 적절하게 활용할 수 있지만, 여기에 덧붙여 변수값에 대한 제약 조건의 지정 등 다양한 활용이 가능합니다.

예를 들어, dataString 변수에 대해서 입력받을 수 있는 문자열을 Dip2K, James, Anold로 제한하고 싶다면 다음처럼 코드를 작성하면 됩니다.

gui.add(myData, "dataString", ["Dip2K", "James", "Anold"]);

dataNumber에 대해서 0~100 사이의 값만을 입력받으며 0.1 단위로 값의 증가, 감소하고자 한다면 아래처럼 코드를 작성하면 되구요.

gui.add(myData, "dataNumber", 0, 100).step(0.1);

dataNumber가 비록 수치 타입이지만, 항목으로써 선택 받도록 하고 각 항목에 대한 수치값을 지정하는 방식도 가능한데, 아래와 같습니다.

gui.add(myData, "dataNumber", { A: 0, B:50, C:100 });

색상값에 대한 직관적인 입력도 가능합니다. 그 예는 아래와 같습니다.

var MyData = function() {
    this.dataString = "Dip2K";
    this.dataNumber = 50;
    this.dataBoolean = false;

    this.dataColor1 = "#ff0000";
    this.dataColor2 = [ 0, 255, 0 ];
    this.dataColor3 = { h: 350, s: 0.5, v: 0.7 };

    this.dataFunction = function() {
        alert(
            "dataString: " + this.dataString + "\n" +
            "dataNumber: " + this.dataNumber + "\n" +
            "dataBoolean: " + this.dataBoolean + "\n" +
            "dataColor1: " + this.dataColor1 + "\n" +
            "dataColor2: " + this.dataColor2 + "\n" +
            "dataColor3: " + this.dataColor3
        );
    };
};

window.onload = function() {
    var myData = new MyData();

    var gui = new dat.GUI();

    gui.add(myData, "dataString", ["Dip2K", "James", "Anold"]);
    gui.add(myData, "dataNumber", 0, 100).step(0.1);
    gui.add(myData, "dataBoolean");

    gui.addColor(myData, "dataColor1");
    gui.addColor(myData, "dataColor2");
    gui.addColor(myData, "dataColor3");
            
    gui.add(myData, "dataFunction");
}

그런데 만약, 값의 변경이 dat.gui가 아닌 다른 곳에서 이루어진 다면, 변경된 값을 dat.gui에서 반영해 줘야 할 것입니다. 이는 매우 간단합니다. 즉, 아래처럼 listen을 호출해 주면 됩니다. 이 listen 함수는 타이머를 생성하고 이 타이머에서 값의 변경 여부를 검사하여 dat.gui에 반영해주게 됩니다.

gui.add(myData, "dataNumber").listen();

끝으로 dat.gui를 통한 값의 변경이 발생하면, 이에 대한 이벤트가 호출되도록 할 수 있는데, 그 예는 아래와 같습니다.

gui.add(myData, "dataNumber").onChange(
    function(v) {
        //alert(v);
    }).onFinishChange(
    function(v) {
        alert(v);
    });

onChange는 값 변경 중의 매 순간 발생하는 이벤트이고, onFinishChange는 최종적인 값의 변경이 발생할 때 호출되는 이벤트입니다.

이외에도 dat.gui는 설정된 값을 localStorage에 저장할 수 있는 기능도 있다는 것도 알아두시면 유용할듯합니다.

C#으로 SQLite 다루기

메모리 기반에서 자료를 다루기 위해 Array나 Linked List 그리고 Hashmap 등을 사용하지만, 대용량 또는 SQL 문을 통한 다양한 조건검색을 위해 DBMS을 사용해야할 때가 있습니다. 설치도 필요없고 가볍고 빠르게 사용할 수 있는 Local DBMS로 SQLite는 안드로이드나 SVN 등과 같이 매우 광범위하게 사용되는데.. C#으로 이 SQLite를 다루는 내용에 대해 정리를 해 봅니다.

C#에서 SQLite를 사용하기 위해서는 먼저 .NET용 SQLite 어셈블리 모듈을 설치해야 합니다. SQLite 공식 사이트에서 관련 파일을 설치할 수 있는 setup 파일을 받아 설치하기 바랍니다.

개발을 위해 필요한 파일이 설치되면 Visual Studio에서 C# 프로젝트를 생성하고 아래의 화면처럼 어셈블리 참조를 추가해 줍니다.

위의 화면에서 추가한 System.Data.SQLite 참조는 SQLite를 위한 ADO.NET 데이터 제공자(Data Provider)입니다. 이 참조는 앞서 설치된 폴더에 System.Data.SQLite.dll 파일을 통해 추가할 수 있습니다.

참조를 추가했으므로 코드에서 참조와 관련된 클래스를 빠르게 접근하기 위한 아래의 using 문을 추가합니다.

using System.Data.SQLite;

이제 다음과 같은 폼을 디자인함으로써 SQLite에 대한 주요 내용에 대한 코드를 살펴 보겠습니다.

폼 상에 버튼의 제목을 통해 우리가 파악할 SQLite에 대한 코드가 무엇인지 짐작할 수 있습니다. 즉, 아래와 같습니다.

  1. Create DB File – SQLite DB 파일을 생성합니다.
  2. Open DB – 생성한 DB 파일을 사용하기 위해 연결합니다.
  3. Create Table – DB 파일에 테이블을 생성합니다.
  4. Insert Row – 생성한 테이블에 Row를 추가합니다.
  5. Query Data – 테이블에 저장된 데이터를 조회합니다.
  6. Close Connection – DB 파일에 대한 연결을 닫습니다.

먼저 SQLite DB 파일을 생성하는 버튼에 대한 코드는 다음과 같습니다.

SQLiteConnection.CreateFile("c:/a.sqlite");

위의 코드가 성공한다면 C:\ 경로에 a.sqlite라는 파일이 생성될 것입니다. 다음은 생성한 DB 파일을 사용하기 위해 연결하는 코드입니다.

conn = new SQLiteConnection("Data Source=c:/a.sqlite;Version=3;");
conn.Open();

위의 코드에서 conn 변수는 다음과 같이 정의되어 있습니다.

private SQLiteConnection conn = null;

이제 다음은 DB 파일에 테이블을 생성하는 코드입니다.

string sql = "create table members (name varchar(20), age int)";

SQLiteCommand command = new SQLiteCommand(sql, conn);
int result = command.ExecuteNonQuery();

sql = "create index idx01 on members(name)";
command = new SQLiteCommand(sql, conn);
result = command.ExecuteNonQuery();

우리가 흔히 알고 있는 CREATE SQL 문을 통해 테이블을 생성하고 있습니다. 추가적으로 인덱스(INDEX)까지도 생성하고 있습니다. 이제 다음은 생성한 테이블에 Row를 추가하는 코드입니다.

String sql = "insert into members (name, age) values ('김도현', 6)";

SQLiteCommand command = new SQLiteCommand(sql, conn);
int result = command.ExecuteNonQuery();

아.. 우리 와이프 코고는 소리가 들리네요.. -_-; 여튼.. 위의 코드를 보면 Row를 추가하기 위해 흔히 알고 있는 INSERT SQL문을 사용하고 있습니다. 다음은 테이블에 저장된 데이터에 대한 조회 코드입니다.

String sql = "select * from members";

SQLiteCommand cmd = new SQLiteCommand(sql, conn);
SQLiteDataReader rdr = cmd.ExecuteReader();
while (rdr.Read()) {
    MessageBox.Show(rdr["name"] + " " + rdr["age"]);
}

rdr.Close();

SELECT SQL문을 통해 조회할 수 있으며, SQLiteDataReader 클래스를 통해 실제 조회된 데이터를 필드별로 읽어 낼 수 있는 것을 볼 수 있습니다. 이제 끝으로 DB에 연결된 Connection 객체를 닫는 코드는 아래와 같습니다.

conn.Close();

자, 이상으로 요긴하게 바로 사용할 수 있는 Local DBMS인 SQLite를 C#에서 사용할 수 있는 최소한의 내용을 정리해 보았습니다.

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 엔진이라고 생각됩니다.