문제 : NodeJS로 구성된 API서버에서 입력한 시간을 MSSQL 서버에 입력 시 간혹 1 밀리세컨드 차이가 발생함.

원인 : NodeJS에서 MSSQL로 쿼리 생성 후 전달 시 매개변수 타입을 의도와 다르게 DateTime 으로 설정함.

해결 : MSSQL 컬럼 타입과 매개변수 타입을 DateTime2로 변경.

 

상세 내용:

의도

데이터 입력 시간을 밀리세컨드 까지 기록하려 함. [예시) 2025-01-01 13:01:00.001]

API서버는 NodeJs로 구성되어 있고, mssql 라이브러리를 require 로 가져와서 사용함.

const msdb = require('mssql');

async dbtest() {
        let now = new Date();
        console.log(now); //2025-01-01 13:01:00.001
        return (await msdb.connect(conf.db)).request()
            .input('RMK', msdb.NVarChar, 'Test Remark')
            .input('REG_DT', msdb.DateTime, now)
            .query(`insert into tb_logs (RMK, REG_DT) values (@RMK, @REG_DT)`);
    }

 

문제 확인

MSSQL DB에서 Select 쿼리로 조회해보면, 간혹 한번씩 1밀리세컨드가 더 크게 들어가 있는 것을 확인함.

console.log로 찍은건 밀리세컨드가 001 인데 MSSQL 서버에서 002로 조회됨.

MSSQL 컬럼 타입을 DateTime2로 변경해서 테스트한 후 문제 원인 추측할 수 있었음.

console.log에서 [2025-01-01 13:01:00.001] 이렇게 보이던 값이

DB에 [2025-01-01 13:01:00.0016667] 과 같이 들어가 있었고, 조회될 때 4번째에서 반올림되어 002로 조회되었음.

 

문제 해결
MSSQL 컬럼 타입과 Node.js API서버의 매개변수 타입을 msdb.DateTime2로 변경해준 뒤 

DB에 [2025-01-01 13:01:00.0010000] 으로 저장됨 확인.

const msdb = require('mssql');

async dbtest() {
        let now = new Date();
        console.log(now); //2025-01-01 13:01:00.001
        return (await msdb.connect(conf.db)).request()
            .input('RMK', msdb.NVarChar, 'Test Remark')
            .input('REG_DT', msdb.DateTime2, now) //msdb.DateTime -> msdb.DateTime2
            .query(`insert into tb_logs (RMK, REG_DT) values (@RMK, @REG_DT)`);
    }

 

-- 위 코드는 상황을 설명하기 위해 재구성하여 작성하였기에 정상적으로 동작하지 않을 수 있습니다.

 

-- 개인적인 생각. 

공식 문서에는 DateTime2가 0.0000001 초까지 기록된다고 되어있는데, node의 mssql 라이브러리 버그인걸까?

mssql은 7.3.5 버전을 사용중...

Nodejs로 API 서버 구현 중 MSSQL을 사용한다.

2개의 다른 MSSQL 서버와 연결하여 데이터를 활용하려 한다.

* 아래 코드는 테스트를 위해 임시로 만든 코드이다.

 

문제 : 아래와 같이 2개 MSSQL 서버 속성을 다르게 설정하고, mssql 모듈을 2번 불러와 사용하려 했는데,

          최초 연결한 DB 서버가 pool에 들어가 있어서 인지, 다른 속성으로 Connect를 시도하여도

          이미 pool이 생성되어있던 DB서버에 쿼리를 날려버린다.

// db.js
let conf = require(./conf);

const msdb1 = require('mssql');
const msdb2 = require('mssql');

module.exports = {

    async dbtest1() {
        return (await msdb1.connect(conf.db1)).request()
            .input('NM_ID', msdb1.NVarChar, 'test_id1')
            .input('RMK', msdb1.NVarChar, 'TEST Remark1')
            .query(`insert into tb_logs (NM_ID, RMK) values (@NM_ID, @RMK)`);
    }
    
    
    async dbtest2() {
        return (await msdb2.connect(conf.db2)).request()
            .input('NM_ID', msdb2.NVarChar, 'test_id2')
            .input('RMK', msdb2.NVarChar, 'TEST Remark2')
            .query(`insert into tb_logs (NM_ID, RMK) values (@NM_ID, @RMK)`);
    }
}

 

 

해결 방안 : 스택 오버플로우에 답변을 올려주신 분이 있어서, 해당 코드를 참고하였다. (매우 감사한 분이다.)

                  GetCreateIfNotExistPool 함수명이 싫어서 기존과 동일한 connect 로 함수를 변경하여 사용했다.

                  1. 여러 MSSQL DB의 커넥션 풀을 관리하는 mssql-connection-pooling.js 파일을 하나 만든다.

                      - 이 파일에서는 여러 MSSQL DB의 커넥션 풀을 pools 객체에 넣어관리한다.
                      config 객체를 문자열로 만든 뒤 key로 사용한다.

                      connection을 요청할 때 동일한 key가 있다면 pools에서 해당 pool을 제공한다.

                      동일한 key가 없으면 새로운 pool을 연결하여 pools 에 새로 넣어놓고 pool을 제공한다.

                  2. mssql-connection-pooling.js 파일을 기존 코드에 불러와 사용한다.

 

// mssql-connection-pooling.js 파일 코드
const { ConnectionPool } = require('mssql');
const pools = {};

// 새로운 커넥션 풀 생성
function CreatePool(config) {
    let key = JSON.stringify(config);

    if (GetPool(key)) {
        throw new Error('Pool already exists');
    }

    pools[key] = (new ConnectionPool(config)).connect();
    return pools[key];
}

// pools 안에 생성된 connection pool 받기
function GetPool(name) {
    if (pools[name]) {
        return pools[name];
    } else {
        return null;
    }
}

// pool이 생서되어 있으면 return pool, 없으면 새로 생성
function connect(config) {
    let key = JSON.stringify(config);

    let pool = GetPool(key);
    if (pool) {
        return pool;
    } else {
        return CreatePool(config);
    }
}

function ClosePool(config) {
    let key = JSON.stringify(config);

    if (pools[key]) {
        const pool = pools[key];
        delete pools[key];
        pool.close();
        return true;
    }
    return false;
}

// 모든 pool 종료
function CloseAllPools() {
    pools.forEach((pool) => {
        pool.close();
    });
    pools = {};
    return true;
}

module.exports = {
    ClosePool,
    CloseAllPools,
    CreatePool,
    GetPool,
    connect,
}

 

// db.js //수정본
let conf = require(./conf);

const msdb = require('mssql');
const mssql = require('./mssql-connection-pooling.js')
//const msdb1 = require('mssql');
//const msdb2 = require('mssql');


module.exports = {
    async dbtest1() {
        return (await mssql.connect(conf.db1)).request()
            .input('NM_ID', mssql.NVarChar, 'test_id1')
            .input('RMK', mssql.NVarChar, 'TEST Remark1')
            .query(`insert into tb_logs (NM_ID, RMK) values (@NM_ID, @RMK)`);
    }
    
    
    async dbtest2() {
        return (await mssql.connect(conf.db2)).request()
            .input('NM_ID', mssql.NVarChar, 'test_id2')
            .input('RMK', mssql.NVarChar, 'TEST Remark2')
            .query(`insert into tb_logs (NM_ID, RMK) values (@NM_ID, @RMK)`);
    }   
}

 

참조 : https://stackoverflow.com/questions/64254145/node-js-mssql-multiple-concurrent-connections-to-sql-servers-interfering-with-ea

 

Node.js mssql multiple concurrent connections to SQL servers interfering with each other

I am using mssql in my Node.js express application to make connections to many different databases across many different SQL servers. I have constructed the following example to demonstrate the gen...

stackoverflow.com

 

 

Vue2에서 eslint-plugin-vue를 사용한다면, 하위 컴포넌트의 slot에 v-text 또는 v-html을 전달하여 사용할 때 간혹 아래와 같은 오류가 발생한다.

 

vue/no-v-text-v-html-on-component error

 

원인은 아래 코드와 같이 하위 컴포넌트를 사용하며 v-text를 속성으로 전달하여 사용하도록 작성된 것이다.

<child-component v-text="ABC" />

 

v-text를 속성으로 전달할 경우, 하위 컴포넌트의 콘텐츠를 덮어쓰기 하며 컴포넌트가 정상적으로 동작하지 않을 수 있기 때문에 eslint-plugin-vue에서 error 로 표시한다.

 

해결 방법은 v-text를 하위 컴포넌트 내부에 div 태그나 p 태그로 전달하면 된다.

<child-component>
	<div v-text="ABC"/>
</child-component>

 

 

다른 방법으로는 eslint에서 특정 라인을 검사하지 않도록 처리하는 방법이 있으나, 추천하진 않는다.

<!-- eslint-disable-next-line vue/no-v-text-v-html-on-component -->
<child-component v-text="ABC" />

 

해당 오류를 수정하기 위해서 아래 사이트를 참고하였다.

https://eslint.vuejs.org/rules/no-v-text-v-html-on-component.html

 

vue/no-v-text-v-html-on-component | eslint-plugin-vue

 

eslint.vuejs.org

https://stackoverflow.com/questions/75698069/disable-eslint-error-with-vuejs-and-v-html

 

Disable eslint error with Vuejs and v-html

I use Nuxt 2 with Vue 2 and vuetify. My vscode was updated and I am getting an eslint error with v-html. The code is: <v-list-item-title v-html="`${parent.genFilteredText(item.nome)}`&q...

stackoverflow.com

 

+ Recent posts