본문 바로가기
programming_kr/nodejs

knex.js DB 연결 방법

by JSsunday 2021. 1. 6.
728x90

nodejs의 ORM 모듈 중 하나인 knex.js의 사용법에 대해 알아봅시다.

knex에 대한 소개는 이러합니다.

 

Knex.js는 유연하고 휴대하며 사용하기 쉽도록 설계된 Postgres, MSSQL, MySQL, MariaDB, SQLite3, Oracle 및 Amazon Redshift용 "batteries included" SQL 쿼리 작성기입니다. 기존의 노드 스타일의  callbakc 뿐만 아니라 더 깨끗한 비동기 흐름 제어, 스트림 인터페이스, 완전한 기능을 갖춘 쿼리 및 스키마 빌더, 트랜잭션 지원(저장 지점 포함), 연결 풀링 및 서로 다른 쿼리 client와 dialect간의 표준화된 응답을 위한 약속 인터페이스를 모두 갖추고 있습니다.

 

knex를 사용하려면 기본적으로 nodejs가 설치되어 있어야 합니다. 설치가 안되어 있는 경우 nodejs를 설치한 후 진행을 합니다. nodejs가 설치되어 있으면 npm으로 knex를 설치합니다.

 

npm install -save knex

 

그리고 dotenv 모듈도 설치합니다.

 

npm install -save dotenv

 

마지막으로 사용할 DB 모듈을 설치합니다. 두 개의 DB를 테스트 하기 위해 mysql, oracle 모듈을 설치했습니다.

 

npm install -save mysql2
npm install -save oracledb

 

모듈을 모두 설치한 뒤

 

npm init

 

으로 프로젝트를 생성한 뒤 메인 프로젝트 디렉토리에서 .env파일을 생성하고 자신의 DB정보를 입력합니다.

 

.env

 

그리고 DB에 연결할 knex object를 생성합니다. 옵션은 아래와 같고 더 자세한 내용은 knex 공식 사이트에서 확인할 수 있습니다.

제가 생성한 DB 환경설정(dbconfig.js) 파일의 코드는 아래와 같습니다.

 

require('dotenv').config();
module.exports = type => (require('knex')({
    //DB 타입
    client: type,

    //database 버전 (oracle, mysql 해당사항 없음)
    //version: ''

    //debug 모드
    debug: true,

    //connection 옵션
    connection: {
        //host
        host: process.env[type + '_HOST'],
        //user
        user: process.env[type + '_USER'],
        //password
        password: process.env[type + '_PASSWORD'],
        //database or schema
        database: process.env[type + '_DATABASE'],
        //기간 설정 토큰 (※mysql2 동작 안함.)        
        expirationChecker: () => Date.now() < Number(new Date('2020-12-30'))
    },

    //stack trace 옵션
    asyncStackTraces: true,

    //connection pool 옵션
    pool: {
        //최소 풀 개수
        min: 0,
        //최대 풀 개수
        max: 10,
        //커넥션이 생성된 후 할 로직 작성
        /* afterCreate: (conn, done) => {
            conn.query('SET timezone="UTC";', function(err) {
                if (err) {
                    // 첫 번째 쿼리가 실패할 때
                    done(err, conn);
                } else {
                    //두 번째 쿼리
                    conn.query('SELECT set_limit(0.01);', function(err) {
                        // err이 false 가 아니면 커넥션은 풀에서 제거된다.
                        // 쿼리에 의해 연결 쿼리가 작동할 경우 오류가 쿼리 프로미스로 전달된다.
                        done(err, conn);
                    });
                }
            });
        } */
    },
    //커넥션 타임아웃 시간 설정 ms 단위
    acquireConnectionTimeout: 10000,

    //배열에 넣은 타입을 조회했을 때 데이터가 스트링을 넘어오게 정의 (※oracledb에서만 사용)
    //fetchAsString: ['number', 'clob'], 

    //쿼리를 통해 결과값을 전달하기 전에 사용하는 함수, queryContext는 queryContext를 사용할 경우 사용할 수 있음 따라서 순수 쿼리로 작성될 경우 사용 못함.
    postProcessResponse: (result, queryContext) => {
        return result.map(ele => {
            ele.time = Date.now();
            return ele;
        });
    },


    //로그 설정
    log: {
        warn(msg) { console.warn(msg) },
        error(msg) { console.error(msg) },
        deprecate(msg) { console.log(msg) },
        debug(msg) { console.log(msg) }
    }
}));

 

DB 환경설정 파일이 만들어졌으면 본격적으로 knex 모듈을 사용해 봅시다.

저는 knex.js라는 파일을 생성 후 knex 모듈을 테스트 해보았습니다.

우선 mysql을 테스트 해봅니다.

 

const db1 = require('./dbconfig')('mysql2');
db1.raw('SELECT * FROM user').then(result => {
    //console.log(result);
})

db1.transaction(trx => {
    trx.raw('SELECT * FROM user WHERE id = ?', 'bny9164').then(result => {
        //result[0] 결과값
        //result[1] 컬럼정보
        //console.log(result);
    }).catch(e => {
        console.error(e);
    });

    let id = 'abcd1234';
    trx.raw(`SELECT * FROM user WHERE id = '${id}'`).then(result => {
        //console.log(result);
    }).catch(e => {
        console.error(e);
    })
});

 

기본적인 방식과 트랜잭션을 사용한 방식으로 나눠서 테스트 해보았습니다.

트랜잭션을 사용한 코드 중에 첫 번째 방법과 같이 where 절에 들어가는 변수를 두 번째 파라미터로 입력해 사용하는 방법과 ES6 문법의 백틱을 사용해 쿼리문에 직접 입력하는 방법이 있습니다.

mysql 테스트가 끝난 후 oracle을 테스트 해봅시다.

 

const db2 = require('./dbconfig')('oracledb');
db2.raw('SELECT * FROM TEST1 WHERE name = ?', '박원숙').then(result => {
    //console.log(result);
});

db2.transaction(async trx => {
    try {
        //oracle 알파벳 한 단어만 입력할 경우 issue 있음.
        const result = await trx.raw('SELECT a.name, a.age, b.clsname FROM TEST1 a JOIN TEST2 b ON a.name = b.name WHERE b.clsname = ?', '김');
        //result 결과값
        console.log(result);
    } catch (e) {
        console.error(e);
    }

    let clsName = 'A';
    try {
        const result = await trx.raw(`SELECT a.name, a.age, b.clsname FROM TEST1 a JOIN TEST2 b ON a.name = b.name WHERE b.clsname = '${clsName}'`);
        console.log(result);
    } catch (e) {
        console.error(e);
    }

})

 

oracle도 mysql과 같이 정상적으로 조회가 됩니다.

테스트 하면서 버그를 발견했는데 oracle의 경우 쿼리문 입력 시 두 번째 파라미터로 ?에 해당하는 값을 입력하는데 SELECT문에서 알파벳 한 글자를 입력하니 정상적으로 조회가 되지 않았습니다. 두 번째 백틱을 사용해서 조회를 하면 정상적으로 조회가 되는데 혹시 이런 이슈가 발생할 경우 두 번째 방법으로 사용하면 될 것 같습니다. 

※발생한 이슈는 현재 knex 커뮤니티에 이슈를 등록해놓은 상태입니다.

 

프로젝트의 모든 디렉토리는 아래와 같습니다.

 

directory

 

참고로 경우에 따라 ES7의 async, await문법을 사용하셔도 됩니다. 단순히 callback함수로 받는 방법도 있습니다. 보다 자세한 사용법은 knex 공식 사이트를 참조하시기 바랍니다.

728x90

'programming_kr > nodejs' 카테고리의 다른 글

nodejs 설치 방법  (0) 2021.09.29
nodejs ENOSPC 에러  (0) 2020.12.26

댓글