최근에 Nodejs에서 Mysql 연동 테스트를 진행하던 중 비동기 방식에 대한 장점을 최대한 살리고 싶었다.
현재 까지는 createConnection을 이용해 connection 객체 한 개만을 이용하여 다음 쿼리가 들어오기 전까지 대기하는 식으로 DB가 동작하는 바람에 NodeJs의 비동기 작업을 최대한 응용하지 못했던 점이 있었다.
또한 항상 connection을 열어둔 상태로 대기하기 때문에 대기 시간이 지나게 되면 자동으로 연결이 끊기는 오류가 발생하기도 했다.
그러한 점 때문에 다른 좋은 방법을 고안하던 중 Connection Pool 패턴이라는 방법을 알게 되었고,
내가 알고 깨달은 내용에 대해 최대한 상세하게 기술하려고 한다.
우선 Connection Pool 하면 무엇이 떠오르는가
딱풀? 수영장?
말 그대로 Connection 객체들을 담아두는 수영장 같은 느낌이다.
우리는 데이터를 DB로부터 가져올 때 Connection 객체를 사용해야 한다.
그러나 NodeJs에서는 Connection 객체 한 개당 하나의 Thread를 사용하도록 한다.
만약 데이터 요청 건이 어마 무시하게 많게 되면 1개의 Thread만 사용하는 Connection 객체는
과부하 상태가 걸리게 될 것이다.
따라서 Connection Pool에 n개만큼의 Thread를 사용하는 Connection 객체들을 담아두고 필요할 때 하나씩 꺼내 사용하도록 한 후 작업이 끝나면 즉시 Connection 객체를 Connection Pool에 반환하도록 해야 한다.
아래 그림은 Connection Pool에 대한 이해를 돕기 위한 도식 표다.
그럼 이제부터 본격적으로 NodeJs에서 ConnectionPool을 다뤄 보도록 하자.
우선 DB 연결을 위한 소스코드를 살펴보도록 하자.
db_options.json
{
"host":"[호스트 IP주소]",
"user":"[DB 사용자 ID]",
"password":"[DB 사용자 PW]",
"port":"[DB server 포트]",
"database":"[DB 명]",
"connectionLimit": [최대 커넥션 갯수]
}
db_service.js
const mysql = require('mysql');
const db_config = require('../../db_options.json');
let pool = mysql.createPool(db_config);
const db = {
getConnection : (callback)=>{
pool.getConnection((err, conn)=>{
if(err)throw err; //연결 오류 발생시 상위 함수로 오류를 던지기
callback(conn); //상위 함수에서 보낸 콜백함수에 conn이라는 Connection 객체를 파라미터로 담고 호출
});
}
}
module.exports = db; //db객체 반환
db 연결을 위한 모듈을 완성하였고 이제 함수를 이용해 db의 데이터를 호출해 보도록 하자.
controller.js
const db = require('../service/db_service');
function async getUsers(req,res,next) =>{ //비동기 방식으로 아래 작업 진행
const sql = `SELECT * FROM users`;
db.getConnection((conn)=>{
conn.query(sql,(err,rows)=>{
if(err) next(err); //오류 발생시 다음 미들웨어로 넘김
res.send(rows);
});
conn.release(); //사용후 connection 객체 반환
});
}
.
.
.
만약 getUser가 호출되면 db안에 있는 getConnection 함수를 호출하게 되고 비동기 callback 함수를 파라미터로
넣어주게 된다.
콜백 함수 안에서는 빌려온 connection 객체를 이용해 쿼리문을 수행하게 되고 다 쓴 후 바로 반환하도록 한다.
그런데 만약 Connection Poool의 최대 양(Connection Limit)이 5이고 엄청나게 무거운 작업을 수행하는 탓에 10개의 Connection을 모두 사용 중일 경우에는 어떻게 될까?
const db = require('../service/db_service');
function async getUsers(req,res,next) =>{ //비동기 방식으로 아래 작업 진행
const sql = `SELECT * FROM users`;
db.getConnection((conn)=>{
conn.query(sql,(err,rows)=>{
if(err) next(err); //오류 발생시 다음 미들웨어로 넘김
res.send(rows);
});
setTimeout(()=>{
conn.release();
console.log('released !');
},5000); //5초 뒤에 connection 객체 반환
});
}
.
.
.
아까 위의 코드에서 일부러 5초 뒤에 Connection 객체를 반환하도록 하였다.
결과
PostMan을 통해 연속으로 13번을 호출하였더니
5번째부터는 로드 상태가 되었다가 몇 초 후 결과가 다시 출력되기 시작했다.
결국에는 Connection Pool의 모든 Connection 객체가 사용 중일 경우 요청을 대기하였다가 순차적으로 connection 객체가 들어오는 대로 실행이 되는 것이라고 한다.
'⚙️ Node.js' 카테고리의 다른 글
[Node.js] path 모듈에 대해 알아보자 (0) | 2023.02.20 |
---|---|
[Node.js] Callback 패턴을 async/await 패턴으로 바꾸기 (0) | 2023.02.17 |
[Node.js] MySql 시간 출력 시 Z가 붙는 문제 (0) | 2022.09.02 |
[Node.js] crypto 암호화 구현 시 Invalid key length 오류 (0) | 2022.08.17 |
[Node.js] MySql PROTOCOL_CONNECTION_LOST 해결 (0) | 2022.07.01 |