제품 여행

Node.js 사용자들을 위한 CUBIRD 연동 방법 [2탄-CUBRID와 Node.js 연동]

by 원종민 posted Jun 04, 2019
1. test 디렉토리 & 파일 생성
  1-1) 라우터 파일 생성

     ● /routes/test.js

 
        
  
  1-2) view 디렉토리& 파일 생성 
     ● views/test 디렉토리 생성
     ● views/test/test_view.ejs 파일 생성
 
      
  
  1-3) 프로젝트 최종 결과
 
        
 
2. node-cubrid 드라이버 모듈 설치
     ● 모듈 공식 사이트 : https://www.npmjs.com/package/node-cubrid
 
  2-1) node-cubrid 모듈 설치
     ● npm install node-cubrid --save
 
      
 
     ● package.json 에서 node-cubrid 모듈 설치 확인
 
      
 
3. node-cubrid 모듈 적용 및 DB 연동
  3-1) 컨트롤러(app.js)에서 라우팅(test.js) 설정.
     - app.js의 25번째 줄과 동일하게 app.use('/test',require('./routes/test')); 추가
 
       
 

 app.js

var createError = require('http-errors');

var express = require('express');

var path = require('path'); var cookieParser = require('cookie-parser');   // 접속한 클라이언트의 쿠키 정보에 접근하기 위한 모듈

var logger = require('morgan'); // 클라이언트의 HTTP 요청 정보를 로깅하기 위한 모듈

var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users');

var bodyParser = require('body-parser'); // 클라이언트의 HTTP 요청 중 POST 요청의 body 데이터에 접근하기 위한 모듈

var app = express();

 

// view engine setup

app.set('views', path.join(__dirname, 'views')); // 서버가 읽을 수 있도록 HTML의 위치를 정의해줍니다.

app.set('view engine', 'ejs'); // express에서 ejs 모듈 연동

app.use(logger('dev'));

app.use(express.json());

app.use(express.urlencoded({ extended: false }));

app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); // 정적 파일 호스팅을 위한 경로 설정

app.use('/', indexRouter); // 라우팅 설정. 세부 라우팅은 /routes 폴더에 구현됨

app.use('/users', usersRouter);

app.use('/test',require('./routes/test')); // 추가

 

// catch 404 and forward to error handler

app.use(function(req, res, next) { next(createError(404)); });

 

// error handler

app.use(function(err, req, res, next) {

 

// set locals, only providing error in development

res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {};

 

// render the error page

res.status(err.status || 500); res.render('error'); });

 

module.exports = app;

 
  3-2) 라우팅(test.js)에서 DB 연동.
 
      
 
     ● 주요 코드 설명은 주석으로 작성했습니다.
 

test.js 

var express = require('express');

var router = express.Router();

 

/* CUBRID 로드

const CUBRID = require('node-cubrid');

const client = CUBRID.createConnection({

    host: host,

    port: port,

    user: user,

    password: password:

    database: database,

    connectionTimeout: connectionTimeout,

    maxConnectionRetryCount: maxConnectionRetryCount,

    logger: logger

});

*/

 

const CUBRID = require('node-cubrid'); // node-cubrid 모듈 불러오기

 

const dbConf = { // DB 정보 설정

    host: 'localhost',

    port: 33000,

    user: 'dba',

    password: '111111',

    database: 'demodb'

};

const client = CUBRID.createConnection(dbConf); // cubrid DB connection

 

client.connect(function (err) { // 연결 확인

    if (err) {

        throw err;

    } else {

        console.log('connection is established');

        

        client.close(function (err) { // 연결 종료

            if (err) {

                throw err;

            } else {            

                console.log('connection is closed');

            }

        });

    }

});

 

router.get('/', function(req, res) { // get 형식으로 '/' URL로 들어갈 경우 /views/test/test_view.ejs 뷰를 보여준다.

    res.redirect('/test/test_view');

});

 

router.get('/test_view', function(req,res,next){

res.render('test/test_view');

});

 

module.exports = router; // NodeJS에 모듈사용의 편리성을 위해, global하게 access하도록 되어 있는 특별한 객체이다.

 
  3-3) View(test_view.ejs) 사용자 화면.
 
      
 

test_view.ejs 

<!DOCTYPE html>

<html>

  <head>

    <title>hellow</title>

    <link rel='stylesheet' href='/stylesheets/style.css' />

  </head>

  <body>

    <h1>hellow</h1>

  </body>

</html>

 
4. DB 연동 결과
  4-1) CUBRID Manager 실행
     ● demodb 실행
 
      
 
  4-2) Node.js 서버 실행
     ● npm start
        - connection is established, connection is closed 로그가 확인 되면 연동 성공.
 
      
 
  4-3) View 사용자 화면 결과
     ● http://localhost:3000/ 접속
 
      
 
5. DB 조회(SELECT), 삽입(INSERT), 삭제(DELETE), 수정(UPDATE)
 
  5-1) 조회(SELECT)
     ● 라우터(test.js) 코드
        - 질의 방법에는 총 4가지 방법이 있으며, 각각 다른 특성을 가지고 있습니다.
  - .query('SQL', function(err, result, queryHandle){}); // 기본 질의 방법으로 질의 실행 후 .closeQuery(); 함수를 이용해 수동으로 연결을 끊어줘야 합니다.
  - .queryAsObjects('SQL', function(err, result, queryHandle){}); // 기본 질의 방법에 결과 값을 객체로 변환시켜주며, .closeQuery(); 함수를 이용해 연결을 끊어줘야 합니다.
  - .queryAll('SQL', function(err, result){}); // .query와 같이 질의 실행 하지만, 자동으로 연결이 끊어집니다.
  - .queryALLsObjects('SQL', function(err, result){}); // .queryAsObjects와 같이 결과 값을 객체로 변환시켜주며, 질의 실행 후 자동으로 연결이 끊어집니다.
 
      
 

test.js 

 router.get('/test_view', function(req,res,next){ // select 쿼리

var sql = 'SELECT * FROM code';

client.queryAllAsObjects(sql, function (err, rows) { // queryAllAsObjects 함수는 query가 끝나면 자동으로 연결을 끊는다.

if (err) {

  throw err;

} else {

  // `rows` is now an array of row objects.

  const rowsCount = rows.length; // 가져온 결과 개수를 체크할 수 있다.

  res.render('/test/test_view', {rows: rows?rows:{} }); // 질의 결과를  rows 객체에 담아 JSON 형태로 /test/test_view로 보낸다. 

}

});

});

 
     ● View(test_view.ejs) 코드
 
      
 

 test_view.ejs

<!DOCTYPE html>

<html>

  <head>

    <title>hellow</title>

    <link rel='stylesheet' href='/stylesheets/style.css' />

  </head>

  <body>

    <table border="1" style="width:100%">

        <caption>demodb(code) 조회</caption>

        <colgroup>

            <col width='25%' />

            <col width='25%' />

        </colgroup>

        <thead>

            <tr>

                <th>s_name</th>

                <th>f_name</th>

            </tr>

        </thead>

        <tbody>

        <%

             for(var i=0; i<rows.length; i++) {

        %>

            <tr>

                <td><%=rows[i].s_name%></td>

                <td><%=rows[i].f_name%></td>

            </tr>

        <%

             }

        %>

        </tbody>

    </table>

  </body>

</html>

 
     ● 조회(SELECT) 결과 화면
 
      
 
  5-2) 삽입(INSERT)
     ● post 방식 삽입 설정
        - 컨트롤러(app.js)에 10번 째줄과 동일하게 app.use(bodyParser.json()); 추가
 
      
 

app.js 

var createError = require('http-errors');

var express = require('express');

var path = require('path');

var cookieParser = require('cookie-parser'); // 접속한 클라이언트의 쿠키 정보에 접근하기 위한 모듈

var logger = require('morgan'); // 클라이언트의 HTTP 요청 정보를 로깅하기 위한 모듈

 

var indexRouter = require('./routes/index');

var usersRouter = require('./routes/users');

var bodyParser = require('body-parser'); // 클라이언트의 HTTP 요청 중 POST 요청의 바디 데이터에 접근하기 위한 모듈

 

var app = express();

 

// view engine setup

app.set('views', path.join(__dirname, 'views')); // 서버가 읽을 수 있도록 HTML의 위치를 정의해줍니다.

app.set('view engine', 'ejs'); // express에서 ejs 모듈 연동

 

app.use(logger('dev'));

app.use(express.json());

app.use(express.urlencoded({ extended: false }));

app.use(cookieParser());

app.use(express.static(path.join(__dirname, 'public'))); // 정적 파일 호스팅을 위한 경로 설정

 

app.use('/', indexRouter); // 라우팅 설정. 세부 라우팅은 /routes 폴더에 구현됨

app.use('/users', usersRouter);

app.use('/test',require('./routes/test'));

 

// catch 404 and forward to error handler

app.use(function(req, res, next) {

  next(createError(404));

});

 

// error handler

app.use(function(err, req, res, next) {

  // set locals, only providing error in development

  res.locals.message = err.message;

  res.locals.error = req.app.get('env') === 'development' ? err : {};

 

// render the error page

  res.status(err.status || 500);

  res.render('error');

});

 

module.exports = app;

 
     ● 라우터(test.js) 코드
        - INSERT 질의 방법에는 여러 함수가 있나, 현재 사용해본 한 가지 함수를 소개하겠습니다.
   - .execute('SQL', [parameter01, parameter02], function(err){});  // 기본 INSERT 질의 방법으로 질의 실행 후 .close(); 함수를 이용해 수동으로 연결을 끊어줘야 합니다.
 
      
 

test.js 

 router.post('/insert_post', function(req,res,next){ // post 형식으로 라우터 처리합니다.

var s_name_post = req.body.s_name_post; // name 값이 s_name_post인 태그를 찾아 입력값을 반환합니다.

var f_name_post = req.body.f_name_post; // name 값이 f_name_post인 태그를 찾아 입력값을 반환합니다.

 

var sql = "INSERT INTO code(s_name, f_name) VALUES(?,?)";  // INSERT 쿼리

 

client.execute(sql, [s_name_post, f_name_post], function (err) { // .execute() 함수로 SQL 질의 안에 들어갈 파라미터를 넣어준다.

// check the error first

if (err) console.error("err : " + err);

        res.redirect('/test/test_view'); // INSERT 후 /test/test_view로 이동하여 사용자에게 view를 보여준다. 

});

 

client.close(function (err) { // INSERT 후 연결을 끝는다.

if (err) {

        throw err;

    } else {            

        console.log('connection is closed');

    }

});

});

 
     ● View(test_view.ejs) 코드
         - 조회(SELECT) test_view.ejs에서 </table>태그 다음 줄에 추가하면 됩니다.
 
      
 

 test_view.ejs

<form method="post" action="/test/insert_post">

<div style="float: left; width: 50%;">

<table border="1">

<caption>demodb(code) post 삽입</caption>

<tr>

  <th>s_name</th>

  <td><input type="text" name="s_name_post" size="50%" maxlength="50%"/></td>

</tr>

<tr>

  <th>f_name</th>

  <td><input type="text" name="f_name_post" size="50%" maxlength="50%"/></td>

</tr>

<tr>

  <td colspan="2"><input type="submit" value="등록"></td>

</tr>

  </table>

</div>

</from>

<br/>

 

     ● 삽입(INSERT) 전 결과 화면 

         - s_name에 'C' , f_name에 'CCCC' 값을 추가하는 화면.

 

      

 

     ● 삽입(INSERT) 후 결과 화면 

         - s_name에 'C' , f_name에 'CCCC' 값이 추가된 화면.

 

      

 

  5-3) 삭제(DELETE)

 

     ● 라우터(test.js) 코드

 

      

 

 test.js

 router.post('/delete', function(req,res,next){ // post 형식으로 라우터 처리합니다.

var s_name_delete = req.body.s_name_delete; // name 값이 s_name_delete인 태그를 찾아 입력값을 반환합니다.

 

var sql = "delete from code where s_name = ?"; // DELETE 질의

client.query(sql,s_name_delete, function (err, rows, queryHandle) { // .query() 함수로 SQL 질의 안에 들어갈 파라미터를 넣어준다.

if (err) {

throw err; // err를 던져준다.

} else {

res.redirect('/test/test_view'); // .query() 함수가 성공 후 /test/test_view로 이동하여 사용자에게 view를 보여준다.

}

});

});

 

     ● View(test_view.ejs) 코드

        - 삽입(INSERT) test_view.ejs에서 </form> <br/> 태그 다음 줄에 추가하면 됩니다.

 

      

 

test_view.ejs 

<form method="post" action="/test/delete">

    <div style="float: left; width: 33%;">

    <table border="1">

    <caption>demodb(code) 삭제</caption>

        <tr>

          <th>s_name</th>

          <td><input type="text" name="s_name_delete" size="33%" maxlength="33%"/></td>

        </tr>

        <tr>

          <td colspan="2"><input type="submit" value="삭제"></td>

        </tr>

      </table>

   </div>

 </form>

 

     ● 삭제(DELETE) 전 결과 화면 

        - s_name의 값이 'Z'인 튜플(tuple)을 삭제하는 화면.

 

      

 

     ● 삭제(DELETE) 후 결과 화면 

        - s_name의 값이 'Z'인 튜플(tuple)을 삭제된 화면.

 

      

 

  5-4) 수정(UPDATE)

 

     ● 라우터(test.js) 코드

 

      

 

 test.js

router.post('/update', function(req,res,next){ // post형식으로 라우터 처리 합니다.

var af_sname_up = req.body.af_sname_up;

var bf_sname_up = req.body.bf_sname_up;

var af_fname_up = req.body.af_fname_up;

var bf_fname_up = req.body.bf_fname_up;

 

var sql = "update code set s_name = ?, f_name = ? where s_name = ? and f_name = ?";    // UPDATE쿼리

 

client.query(sql, [bf_sname_up, bf_fname_up, af_sname_up, af_fname_up], function (err, rows, queryHandle) { // .query() 함수로 SQL 쿼리 안에 들어갈 파라미터를 넣어준다.

if (err) {

throw err; // err를 던져준다.

} else {

res.redirect('/test/test_view'); // .query() 함수가 성공 후 /test/test_view로 이동하여 사용자에게 view를 보여준다.

}

});

}); 

 

     ● View(test_view.ejs) 코드

        - 삭제(DELETE) test_view.ejs에서 </form> 태그 다음 줄에 추가하면 됩니다.

 

      

 

test_view.ejs 

 <form method="post" action="/test/update">

    <div style="float: left; width: 33%;">

    <table border="1">

    <caption>demodb(code) 수정</caption>

        <tr>

          <th>변경 전 s_name</th>

          <td><input type="text" name="af_sname_up" size="33%" maxlength="33%"/></td>

        </tr>

        <tr>

          <th>변경 후 s_name</th>

          <td><input type="text" name="bf_sname_up" size="33%" maxlength="33%"/></td>

        </tr>

        <tr>

          <th>변경 전 f_name</th>

          <td><input type="text" name="af_fname_up" size="33%" maxlength="33%"/></td>

        </tr>

        <tr>

          <th>변경 후 f_name</th>

          <td><input type="text" name="bf_fname_up" size="33%" maxlength="33%"/></td>

        </tr>

        <tr>

          <td colspan="2"><input type="submit" value="수정"></td>

        </tr>

      </table>

   </div>

</form>

 

     ● 수정(UPDATE) 전 결과 화면 

        - s_name의 'C' 값을 'Z' 로, f_name의 'CCC' 값을 'ZZZ'로 변경 하려는 화면.

 

      

 

     ● 수정(UPDATE) 후 결과 화면 

        - s_name의 'C'값을 'Z' 로, f_name의 'CCC' 값을 'ZZZ' 로 변경된 화면.

 

      

* 앞서 소개한 삭제(DELETE), 수정(UPDATE)의 test.js에 .query()함수 사용 후 .closeQuery()함수를 추가 못 하였습니다. 

   사용에는 문제가 없으나, 수동으로 연결을 끊지 않으면 CAS가 계속 대기하는 문제가 발생하기 때문에 .closeQuery()함수를 추가하여 연결을 끊도록 해주세요.

 

* 이상 2탄에서는 CUBRID DB와 Node.js 연동 후 간단한 조회, 삽입, 삭제, 수정 방법을 소개했습니다.
   앞서 소개한 방법을 응용하면 다양한 웹페이지를 만드실 수 있습니다.
   다음 3탄에서는 비동기 처리, CALLBACK 패턴과 Promise 패턴을 소개하겠습니다.