node.js 2) DB 연결

node.js를 서버측 프레임워크로 하는 관리자 페이지 작성을 진행하고 있다.

안드로이드 앱 ‘쌤통’의 관리자 페이지로서 DB는 MySQL을 사용하고 있다.
이번 포스팅에서는 지난 포스팅에 이어 node.js에서 MySQL DB를 사용하는 방법에 대해 알아보자.

node 진영의 가장 큰 장점 중에 하나는 바로 풍부한 모듈을 보유하고 있다는 것이다.
node.js에서 MySQL을 사용하기 위해 개발된 모듈이 바로 “db-mysql”과 “mysql”이다.(이것들 이외에도 node.js에서 MySQL을 사용하기 위해 작성된 모듈들은 많이 있다.) 자바로 따지면 JDBC와 비슷한 역할을 수행한다. 개발자가 이 두 모듈을 사용하면 복잡한 코드를 작성할 필요 없이 모듈에서 정의한 함수만 사용하여 DB에 접속, 조회, 수정, 삭제가 가능하다.

db-mysql과 mysql 모듈에 대한 정확한 정보는
db-mysql, MySQL에서 얻길 바란다.

가장 먼저, 테스트 용 MySQL 테이블과 데이터를 만들어놓고, db-mysql, mysql 모듈 순으로 설명을 하도록 한다.
본 포스팅 개발 환경은 CentOS release 5.8 (Final), MySQL 5.0.95, node.js v0.10.23, npm 1.3.17 버전이다.

일단 mysql 명령어를 커맨드 창에서 실행한다. 그 후에 테스트 용 테이블을 생성하고 데이터 몇 개를 insert 한다.

[root@getbanana ADMIN]# mysql
mysql> use test;
Database changed
mysql> create table teacher(
    -> no int(10) not null auto_increment primary key,
    -> name varchar(10) not null,
    -> grade int(10) not null
    ->);
mysql> insert into teacher(name, grade) values('jyp', 4);
Query OK, 1 row affected (0.15 sec)
mysql> insert into teacher(name, grade) values('gjh', 4);
Query OK, 1 row affected (0.15 sec)

1: mysql을 실행시킨다.
2: mysql을 실행하면 기본으로 생성되어 있는 ‘test’라는 database를 사용한다.
4~8: ‘teacher’ 테이블을 생성한다. 컬럼으로는 no, name, grade를 두었다.
9, 11: 데이터 두 개를 insert 한다.

mysql> select * from teacher;
| no | name | grade |
+----+------+-------+
|  1 | jyp  |     4 |
|  2 | gjh  |     4 |
+----+------+-------+
2 rows in set (0.00 sec)

데이터가 잘 insert 되었는지 확인해본다.

MySQL DB가 준비됐으니 다음으로는 db-mysql 모듈에 대해 알아보자.
db-mysql 모듈은 npm으로 설치가 가능하다.

[root@getbanana ADMIN]# npm install -g db-mysql

db-mysql 설치가 제대로 되었는지 확인하기 위해 node 콘솔 창을 열어 확인해보자.
다음 처럼 require(“db-mysql”)을 실행했을 때, 객체가 출력되면 설치가 제대로 된 것이다.

[root@getbanana ADMIN]# node

<blockquote>
  require(&quot;db-mysql&quot;)
  { Query: [Function],
  Database: 
    { [Function]
       COLUMN_TYPE_STRING: 0,
       COLUMN_TYPE_BOOL: 7,
       COLUMN_TYPE_INT: 2,
       COLUMN_TYPE_NUMBER: 3,
       COLUMN_TYPE_DATE: 4,
       COLUMN_TYPE_TIME: 5,
       COLUMN_TYPE_DATETIME: 6,
       COLUMN_TYPE_TEXT: 1,
       COLUMN_TYPE_SET: 8 } }
  

설치가 되었으니 이제는 node.js에서 MySQL에 접속하는 일만 남았다.
이제 db-mysql 모듈을 이용해 방금 전 insert 한 데이터를 조회하는 작업을 수행해보자.
app.js 스크립트를 작성한다.

var mysql = require('db-mysql');
new mysql.Database({
    hostname: 'localhost',
//    user: 'user',
//    password: 'password',
    database: 'test'
}).connect(function(error) {
    if (error) {
        return console.log('CONNECTION error: ' + error);
    }
    this.query().
        select('*').
        from('teacher').
        execute(function(error, rows, cols) {
            if (error) {
                    console.log('ERROR: ' + error);
                    return;
            }
            console.log(rows.length + ' ROWS found');
            for(idx in rows){
                console.log("name: " + rows[idx].name + ", grade: " + rows[idx].grade);
            }
        });
});

1: require 함수를 사용하여 db-mysql 모듈을 불러온다.
2~6: 연결할 대상 MySQL DB에 대한 설정 부분이다. hostname에는 db가 깔린 주소, user와 password는 각각 db의 아이디와 비밀번호를 입력한다. database는 사용할 db 이름을 입력한다. 본 포스팅에서는 MySQL DB에 아이디와 비밀번호를 설정하지 않았기 때문에 user와 password 부분은 주석처리했다.
7: connect 함수를 호출하면서 인자로 함수를 넘겨준다. 2~6에서 설정한 것들로 db에 접속을 시도하고 접속되면 인자로 넘겨주는 함수를 실행한다는 의미이다.
8~10: 접속이 실패할 수도 있기 때문에 에러처리를 하는 부분이다.
11~13: db-mysql은 sql을 직접 작성하는 것을 대신하게끔 하는 함수를 제공한다. 함수 이름이 매우 직관적이기 때문에 별다른 설명이 필요없어 보일 정도로 사용하기 쉽다. this.query() 함수의 리턴값을 이용하여 select() 함수, from() 함수를 사용한다. 이 외에도 order, where 함수 등을 제공한다.
함수를 사용하지 않고 raw한 sql문을 사용하고 싶을 경우에는 this.query() 함수 내부에 작성하면 된다.

this.query("select * from teacher")...

14~22: select 질의문의 결과값을 받아와서 처리하는 부분이다.
execute 함수가 질의문을 실행하는 함수이고 인자로 또 다른 함수를 넘겨준다. 넘겨주는 함수에는 다시 인자가 세 개 있는데 err에는 질의문 실행 결과 에러가 났을 경우 해당 정보가 담겨 있고, rows에는 결과값이 배열 형태로 담겨있으며, cols에는 컬럼에 대한 정보가 담겨 있다.
19~21: rows에서 값에 접근하는 방식을 살펴보자. rows는 배열 형태이기 때문에 rows[index] 형식으로 각 row에 접근하고 row에서는 ‘.’ 연산자로 값에 접근한다.

위 app.js를 실행하면 다음과 같다.

[root@getbanana ADMIN]# node app.js
2 ROWS found
name: jyp, grade: 4
name: gjh, grade: 4

db-mysql의 사용법에 대해 알아봤다. 본 포스팅에서는 select까지만 살펴보고 나머지는 여기를 참조하기 바란다. select를 제대로 이해했다면 나머지 insert, update, delete는 쉽게 적용이 가능할 것이다.

다음으로는 mysql 모듈에 대해서 알아본다.
db-mysql 모듈과 사용법이 상당히 유사하다. 일단 npm으로 mysql 모듈을 설치한다.

[root@getbanana ADMIN]# npm install -g mysql

그리고는 mysql 모듈로 MySQL DB에 접속하는 스크립트를 작성한다.

var mysql = require('mysql');
var connection = mysql.createConnection({
    host: 'localhost',
//    user: 'me',
//    password: 'secret',
    database: 'test'
});

connection.connect();

connection.query('select * from teacher', function(err, rows, cols){
    if(err) throw err;

<pre><code>console.log(rows);
</code></pre>

});

connection.end();

1: mysql 모듈을 불러온다.
2~7: createConnection 함수에 db 접속 정보를 설정 한 값을 넘겨주면서 호출한다.
9: db에 연결한다.
11~17: query 함수의 첫 번째 인자에 sql 문을 작성하고 두 번째 인자는 질의문 수행 결과를 처리할 함수를 넘겨준다. 함수는 db-mysql의 질의문 처리 함수 인자와 동일하다.
19: 접속을 해제한다.

mysql 모듈은 db-mysql 모듈에 비해 좀 더 풍부한 기능을 제공한다. JDBC 사용자라면 preparedStatement 인터페이스로 sql문을 작성해 본 경험이 있을 것이다. sql 문 중간에 변수 값을 할당해야 할 때, ‘+’ 연산자로 이어붙이는 게 지저분하기 때문에 다음과 같은 방식으로 가독성 있게 코드를 작성하게끔 할 수 있었다.

PreparedStatment pstmt = connection.prepareStatement("insert into teacher(name, grade) values(?, ?);
pstmt.setString(1, "csj");
pstmt.setInt(2, 4);

mysql 모듈은 이와 비슷한 방식으로 sql문을 작성하게 도와주는 기능을 제공하고 있다.

var query = connection.query("insert into teacher(name, grade) values(?, ?)", ['csj', 4], function(){...});
console.log(query.sql);

1: query 함수의 첫 번째 인자로 sql문을 작성하는데 변수 값을 할당할 부분에 ‘?’를 채워넣는다. 두 번째 인자로는 ‘?’에 넣을 값들을 배열로 주고, 세 번째 인자는 질의문 처리 함수를 넘겨준다.
2: “insert into teacher(name, grade) values(‘csj’, 4)” 가 출력된다.

이밖에도 mysql 모듈은 connection pooling, Multiple statement queries 기능 들을 제공하기 때문에 좀 더 심화된 db 접속 기능이 필요하다면 db-mysql 모듈보다는 mysql 모듈을 추천한다.

또한 node.js 0.10 버전에서부터는 db-mysql 모듈이 version mismatch 되는 에러가 나고 있기 때문에 최신의 node.js를 사용하는 개발자라면 mysql 모듈이 최선의 MySQL 접속 모듈이 아닐까 한다.

다음 포스팅에서는 DB에서 가져온 데이터를 화면에 뿌려주는 기능을 express 모듈과 함께 설명하도록 하겠다.