Post List

2016년 11월 15일 화요일

Node.js에서 MariaDB 와 GIS

1. 필요한 모듈

  • Node.js - 크롬의 자바스크립트 런타임이 내장된 Node.js 플랫폼이다. 이는 이벤트 기반과 넌블럭 아키텍처 기반이다.
  • Express.js - node.js 기반의 웹 프레임워크이다.(루비의 Sinatra 와 유사하다) 응용 프로그램에 대하여 쉽게 Configuration을 할 수 있고, 괜찮은 구조를 만들어 준다.
  • Jade - node.js 의 뷰 템플릿 엔진으로 HTML 태그 보다 심플한 형태의 마크업을 작성하면, 자동으로 HTML을 생성해 주는 역할을 한다.
  • node-mariasql - MariaDB를 node.js에 바인딩할 수 있는 클라이언트 라이브러이다.
  • xml2js - XML 파싱을 위한 node 모듈이다.
  • Google Maps - 최종결과를 맵에 표시하기 위해 필요하다.
여기에서 사용하는 소스는 github인 https://github.com/rasmushoj/nodejs-gpx-mariadb 에서 다운을 받을 수 있다.



그리고 이 소스의 라이선스는 MIT Lecense 를 따르고 있음으로 저작권 고지 및 라이선스 사본 포함 정도의 규정만 지키면 된다.

2. 설치 하기
설치를 할 환경은 CentOS7 64비트를 기준으로 하겠다.
기본적으로 root 계정을 사용하지 말고 다른 사용자 계정을 만들어 사용하자. 여기서 사용할 계정은 binrang 이라는 계정에 sudo 권한을 부여하여 사용할 것이다.

[binrang@binrang routes]$ sudo adduser binrang
[binrang@binrang routes]$ sudo usermod -G wheel binrang

MariaDB 에서 10.0 을 다운로드를 받아 설치를 하자. (참고 : CentOS7에서 MariaDB 10.0 설치하기)

MariaDB에 running 이라는 데이터베이스를 생성하자.

mysql -u root -p
MariaDB [(none)]> create database running;

프로그램의 Github 저장소 에서 running.sql 을 다운 받아 생성한 데이터베이스에 import 를 하자.

[root@binrang-db ~]# wget https://raw.githubusercontent.com/rasmushoj/nodejs-gpx-mariadb/master/running.sql
--2016-11-04 17:42:42--  https://raw.githubusercontent.com/rasmushoj/nodejs-gpx-mariadb/master/running.sql
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.100.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.100.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1770 (1.7K) [text/plain]
Saving to: ‘running.sql’
100%[==================================================================================>] 1,770       --.-K/s   in 0s      
2016-11-04 17:42:42 (501 MB/s) - ‘running.sql’ saved [1770/1770]
[root@binrang-db ~]# mysql -u root -p running < running.sql


환경준비 :


[binrang@binrang mariajs]$ npm install express
/home/binrang/mariajs
└─┬ express@4.14.0 
  ├─┬ accepts@1.3.3 
  │ ├─┬ mime-types@2.1.12 
  │ │ └── mime-db@1.24.0 
  │ └── negotiator@0.6.1 
......
  ├── utils-merge@1.0.0 
  └── vary@1.1.0 
npm WARN enoent ENOENT: no such file or directory, open '/home/binrang/mariajs/package.json'
npm WARN mariajs No description
npm WARN mariajs No repository field.
npm WARN mariajs No README data
npm WARN mariajs No license field.
[binrang@binrang mariajs]$ 


  • Jade 설치

[binrang@binrang mariajs]$ npm install jade
npm WARN deprecated jade@1.11.0: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated transformers@2.1.0: Deprecated, use jstransformer
/home/binrang/mariajs
└─┬ jade@1.11.0 
  ├── character-parser@1.2.1 
  ├─┬ clean-css@3.4.20 
  │ ├─┬ commander@2.8.1 
  │ │ └── graceful-readlink@1.0.1 
......
  ├── void-elements@2.0.1 
  └─┬ with@4.0.3 
    ├── acorn@1.2.2 
    └── acorn-globals@1.0.9 
npm WARN enoent ENOENT: no such file or directory, open '/home/binrang/mariajs/package.json'
npm WARN mariajs No description
npm WARN mariajs No repository field.
npm WARN mariajs No README data
npm WARN mariajs No license field.
[binrang@binrang mariajs]$ 


  • MariaDB non-blocking client 설치

[binrang@binrang mariajs]$ npm install mariasql
> mariasql@0.2.6 install /home/binrang/mariajs/node_modules/mariasql
> node-gyp rebuild
make: Entering directory `/home/binrang/mariajs/node_modules/mariasql/build'
  CXX(target) Release/obj.target/taocrypt/deps/libmariadbclient/extra/yassl/taocrypt/src/aes.o
  CXX(target) Release/obj.target/taocrypt/deps/libmariadbclient/extra/yassl/taocrypt/src/aestables.o
  CXX(target) Release/obj.target/taocrypt/deps/libmariadbclient/extra/yassl/taocrypt/src/algebra.o
......
make: Leaving directory `/home/binrang/mariajs/node_modules/mariasql/build'
/home/binrang/mariajs
└─┬ mariasql@0.2.6 
  ├── lru-cache@2.7.3 
  └── nan@2.4.0 
npm WARN enoent ENOENT: no such file or directory, open '/home/binrang/mariajs/package.json'
npm WARN mariajs No description
npm WARN mariajs No repository field.
npm WARN mariajs No README data
npm WARN mariajs No license field.
[binrang@binrang mariajs]$ 


  • 이제 마지막으로 xml2js 모듈을 설치한다.

[binrang@binrang mariajs]$ npm install xml2js
/home/binrang/mariajs
└─┬ xml2js@0.4.17 
  ├── sax@1.2.1 
  └─┬ xmlbuilder@4.2.1 
    └── lodash@4.16.6 
npm WARN enoent ENOENT: no such file or directory, open '/home/binrang/mariajs/package.json'
npm WARN mariajs No description
npm WARN mariajs No repository field.
npm WARN mariajs No README data
npm WARN mariajs No license field.
[binrang@binrang mariajs]$ 

3. git 을 이용하여 소스를 받아오자.

[binrang@binrang mariajs]$ git clone https://github.com/rasmushoj/nodejs-gpx-mariadb.git
Cloning into 'nodejs-gpx-mariadb'...
remote: Counting objects: 226, done.
remote: Total 226 (delta 0), reused 0 (delta 0), pack-reused 226
Receiving objects: 100% (226/226), 156.56 KiB | 161.00 KiB/s, done.
Resolving deltas: 100% (75/75), done.
[binrang@binrang mariajs]$ ls -al
합계 16
drwxrwxr-x.  5 binrang binrang   71 11월  9 09:48 .
drwx------. 31 binrang binrang 4096 11월  9 09:47 ..
drwxrwxr-x. 92 binrang binrang 4096 11월  8 17:33 node_modules
drwxrwxr-x.  6 binrang binrang 4096 11월  9 09:48 nodejs-gpx-mariadb
[binrang@binrang mariajs]$ 

  • nodejs-gpx-mariadb 디렉토리로 이동 후 npm install 명령을 실행한다.

[binrang@binrang mariajs]$ cd nodejs-gpx-mariadb/
[binrang@binrang nodejs-gpx-mariadb]$ npm install
npm WARN deprecated jade@1.11.0: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated transformers@2.1.0: Deprecated, use jstransformer
application-name@0.0.1 /home/binrang/mariajs/nodejs-gpx-mariadb
├─┬ express@3.4.5 
│ ├── buffer-crc32@0.2.1 
│ ├─┬ commander@1.3.2 
│ │ └── keypress@0.1.0 
......
  ├── void-elements@2.0.1 
  └─┬ with@4.0.3 
    ├── acorn@1.2.2 
    └── acorn-globals@1.0.9 
[binrang@binrang nodejs-gpx-mariadb]$ 


위 소스는 MIT 라이선스 규약을 따른다.

이 프로그램에 대한 환경 분석.

아래 common.js 와 data.js 를 통해 모듈을 데이터베이스를 핸들링하게 된다.

[binrang@binrang nodejs-gpx-mariadb]$ pwd
/home/binrang/mariajs/nodejs-gpx-mariadb
[binrang@binrang nodejs-gpx-mariadb]$ vi app.js 
.......
var user = require('./routes/user');
var common = require('./routes/common');

업로드 되는 파일의 대한 경로는 아래 코드와 같다.

app.use(express.bodyParser({ keepExtensions: true, uploadDir: __dirname + '/public/uploads' }));

app.js 파일에 이 프로그램에서 필요한 URL 매핑을 정의한 부분이다.

app.get('/upload', common.fileForm);
app.post('/upload', common.fileUpload);
app.get('/readfile', common.readFile);
app.get('/parsegpx', common.parseGPX);
app.get('/track', common.listPoints);
app.get('/xmltracks', common.xmlTracks);
app.get('/xmltracksduration', common.xmlTracksDuration);
app.get('/showmap', function (req, res) {
    res.sendfile(__dirname + '/views/maps.html');
});
app.get('/showxmlfiles', function (req, res) {
    res.sendfile(__dirname + '/views/xmltracks.html');
});
app.get('/trackinfo', common.trackInfo);

maridb의 환경이 다른 서버로 되어 있다면 data.js 파일에서 환경을 설정한다.

[binrang@binrang nodejs-gpx-mariadb]$ pwd
/home/binrang/mariajs/nodejs-gpx-mariadb
[binrang@binrang nodejs-gpx-mariadb]$ vi data.js 
// adapted from https://github.com/mscdex/node-mariasql
var inspect = require('util').inspect;
var Client = require('mariasql');
var client = new Client();
exports.connect = function() {
    client.connect
    (
        {
            host: '원격 mariadb IP',
            user: '접근 DB 계정',
            password: '접근 DB 패스워드',
            db: 'running'
        }
    );


그리고 해당 DB에 테이블을 조회하여 보자.

[binrang@binrang-db ~]$ mysql -uroot -p running
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 5
Server version: 10.0.28-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [running]> show tables;
+-------------------+
 Tables_in_running |
+-------------------+
 trackpoints       |
+-------------------+
1 row in set (0.00 sec)
MariaDB [running]> 

이제 서버를 구동 시켜 보자.

[binrang@binrang nodejs-gpx-mariadb]$ node app
connect.multipart() will be removed in connect 3.0
visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
connect.limit() will be removed in connect 3.0
Express server listening on port 3000

먼저 브라우저로 열기 전에 uploads 디렉토리에 파일이 있는지 체크 부터 해 보자.

[binrang@binrang uploads]$ pwd
/home/binrang/mariajs/nodejs-gpx-mariadb/public/uploads
[binrang@binrang uploads]$ ls -al
합계 4
drwxrwxr-x. 2 binrang binrang 23 11월  9 09:48 .
drwxrwxr-x. 4 binrang binrang 38 11월  9 09:48 ..
-rw-rw-r--. 1 binrang binrang 42 11월  9 09:48 .emptyfile
[binrang@binrang uploads]$ 


이제 웹 브라우저로 화면을 열어보자.

http://해당 IP:3000/ 으로 접속시 Express 화면을 만날 수 있다.

http://해당IP:3000/upload 로 접속 시 화면
샘플 GPX 파일 참조 : 울릉도 백패킹

첨부파일 중의 gpx 파일을 선택

자세히 보면 파일 업로드 경로와 파일명을 확인 할 수 있다.

서버의 해당 디렉토리를 확인해보자.

[binrang@binrang uploads]$ ls -al
합계 36
drwxrwxr-x. 2 binrang binrang    58 11월 15 11:24 .
drwxrwxr-x. 4 binrang binrang    38 11월  9 09:48 ..
-rw-rw-r--. 1 binrang binrang    42 11월  9 09:48 .emptyfile
-rw-rw-r--. 1 binrang binrang 31656 11월 15 11:24 13641-16x33l1.23139v0a4i.gpx
[binrang@binrang uploads]$ 


이번에는 GPX 파일을 파싱하는 부분이다.
GPX 파일은 아래와 같이 구성되어 있다.

      <trkpt lat="37.860275" lon="128.549301"><ele>839.848389</ele><time>2016-08-20T08:22:34Z</time></trkpt>
      <trkpt lat="37.860302" lon="128.550125"><ele>826.139038</ele><time>2016-08-20T08:23:06Z</time></trkpt>
      <trkpt lat="37.860474" lon="128.550873"><ele>831.081543</ele><time>2016-08-20T08:24:06Z</time></trkpt>
      <trkpt lat="37.860561" lon="128.551697"><ele>841.117920</ele><time>2016-08-20T08:25:07Z</time></trkpt>
      <trkpt lat="37.860779" lon="128.552582"><ele>841.464233</ele><time>2016-08-20T08:26:07Z</time></trkpt>
      <trkpt lat="37.860634" lon="128.552124"><ele>852.028809</ele><time>2016-08-20T08:26:37Z</time></trkpt>
      <trkpt lat="37.860649" lon="128.551849"><ele>842.237671</ele><time>2016-08-20T08:27:08Z</time></trkpt>

현재 DB의 trackpoints 테이블에는 아무런 데이터가 없다.

MariaDB [running]> select * from trackpoints;
Empty set (0.01 sec)
MariaDB [running]> 

파싱과 관련된 코드는 아래와 같다.

[binrang@binrang routes]$ pwd
/home/binrang/mariajs/nodejs-gpx-mariadb/routes
[binrang@binrang routes]$ vi common.js 
......
exports.parseGPX = function(req, res) {
    var data = require('../data.js');
    var json = '';
    try {
        var fileData = fs.readFileSync(req.session.uploadedFilePath, 'ascii');
        var parser = new xml2js.Parser();
        parser.parseString(fileData.substring(0, fileData.length), function (err, result) {
            json = result;
        });
        var debug = '';
        var lon = null;
        var lat = null;
        data.connect();
        for(var i in json.gpx.trk[0].trkseg[0].trkpt) {
            lon = json.gpx.trk[0].trkseg[0].trkpt[i].$.lon;
            lat = json.gpx.trk[0].trkseg[0].trkpt[i].$.lat;
            data.insertPoint(lon, lat);
            debug += "lon: " + lon + " - ";
            debug += "lat: " + lat + "\n";
        }
        data.disconnect();
        res.send(debug);
    } catch (ex) {
        res.send(ex);
    };
};

이 부분에서 data의 insertPoint를 통해 DB에 데이터를 입력한다.

[binrang@binrang nodejs-gpx-mariadb]$ pwd
/home/binrang/mariajs/nodejs-gpx-mariadb
[binrang@binrang nodejs-gpx-mariadb]$ vi data.js 
......
exports.insertPoint = function(lon, lat) {
// console.log('INSERT INTO trackpoints (gpsPoint) VALUES (PointFromText(:loc))', { loc: 'POINT(' + lon + " " + lat +  ')' });
    client.query('INSERT INTO trackpoints (gpsPoint) VALUES (PointFromText(:loc))', { loc: 'POINT(' + lon + " " + lat +  ')' })


웹 브라우저에서 http://해당IP:3000/parsegpx 로 접속해 보자.
GPX 파일을 파싱하는 부분을 확인 할 수 있다.

DB를 확인하여 보자.

MariaDB [running]> select * from trackpoints;
+---------+---------+---------------------------+
 pointId | trackId | gpsPoint                  |
+---------+---------+---------------------------+
     151 |       1 |         հߓ`@H¿}큀      |
     152 |       1 |        ȶ¾`@yW=`큀      |
     153 |       1 |        򪀠`@w$큀       |
     154 |       1 |        ¤w§`@E䚦큀         |
     155 |       1 |        wKr.`@³
.큀      |
     156 |       1 |        Ū𿨑`@¯老)큀        |
     157 |       1 |        軿¨`@㨖¿)큀        |

이제 웹브라우저로 다시 돌아가 showmap을 확인해 보자.
그러나 뭔가 문제가 있다.. 예시와 같이 맵에 추적이 되지 않는다.

??? 이유가 뭘까?


참조 URL : https://mariadb.org/node-js-mariadb-and-gis/