MySQL Connection Pool
✒️ 2025-05-26 15:02 내용 수정
참고 자료 : techbless's Node.js에서 Mysql Connection Pool 이용하기, 주형's MySQL 단일 Connection VS Connection Pool 방식의 차이, Hooligans's 내가 만든 서비스는 얼마나 많은 사용자가 이용할 수 있을까? - 3편(DB Connection Pool)
- Node에서 MySQL 연결 시 단일 Connection을 생성했다가 지우는 구조 대신 Connection Pool을 만들어 미리 만들어 놓은 Connection을 빌리고 Pool에 다시 돌려주는 식으로 구성할 수 있다.
- Connection pool은 DBCP 참고.
- 프로젝트의 구조를 설정하던 중 api/ 폴더의 여러 js 파일들에서 매번 DB connection을 만들고 삭제하는 것이 어플리케이션 성능과 비용 측면에서 적절하지 않을 것 같아 Connection Pool을 사용하기로 했다.
설정
- 프로젝트에 express, mysql2가 설치되어 있어야 한다.
- db 연결 설정을 위한 json 파일을 만든다.
// db_config.json
{
"host" : "localhost",
"user" : "root",
"password" : "password",
"database" : "databaseName",
"port" : "3306", // 기본 3306
"connectionLimit" : 10
}
- db connection pool을 모듈화하기 위해 db.js 파일에 pool을 생성하고 export 한다.
// db.js
const mysql = require('mysql2');
const config = require("../db_config.json"); // db config file
// connection pool 생성
let pool = mysql.createPool(config);
function getConnection(callback) { // callback에 기능 함수 추가(query)
pool.getConnection((err, conn) => {
if (!err) {
console.log("DB에 연결되었습니다.");
callback(conn); // callback에서 connection을 받아 동작을 수행하고, 반환한다.
} else {
throw err;
}
});
}
module.exports = getConnection;
- router 파일에서 db connection을 사용하기 위해
getConnection()을 가져오고, 특정 요청이 들어왔을 때 db에서 정보를 조회하도록 설정했다.
// user.js
const router = require('express').Router();
const getConnection = require("../db.js"); // db connection pool
router.get('/user', (req, res) => {
// query문 설정
let sql = 'SELECT * FROM users';
// db connection pool을 가져오고, query문 수행
getConnection((conn) => {
conn.query(sql, (error, data) => {
res.send({data}); // 웹 페이지에 data가 출력됨
});
// 반드시 connection 반환하기
conn.release();
});
});
module.exports = router;
- server.js에서 express 설정과 라우트 설정을 진행한다.
// 서버 세팅 -----------------------------------------------
// 환경변수
require("dotenv").config();
// express 설정
const express = require("express");
const app = express();
// db
const dbConfig = require("../db_config.json");
const getConnection = require("./db.js");
const PORT = process.env.PORT || 10000;
// app 설정
app.use(express.json());
app.use(express.urlencoded({ extended : true }));
// DB 연결 시 서버 열림-------------------------------------------
getConnection((conn) => {
app.listen(PORT, () => {
console.log(`http://localhost:${PORT}/test`);
});
// 반드시 connection 반환하기
conn.release();
});
// router --------------------------------------------------------
app.get("/test", (req, res) => {
res.send("<h1>React server test</h1>");
});
app.use("/", require('./api/user.js'));
- 서버를 실행하고 요청 url을 입력하면 DB에 보낸 요청의 결과가 출력된다.
비동기를 위한 promise화
- 다른 js 파일에서 비동기로 DB에 연결 요청을 수행하기 위해서 pool 객체를 Promise화 시킨 후 module로 내보낸다.
// db.js
const mysql = require('mysql2');
const config = require("../db_config.json");
const util = require("util");
// connection pool 생성
let pool = mysql.createPool(config);
pool.getConnection((err, connection) => {
if (err) { // 연결 에러 처리
if (err.code === 'PROTOCOL_CONNECTION_LOST') {
console.error("DB ERROR : Database connection was closed");
}
if (err.code === 'ER_CON_COUNT_ERROR') {
console.error("DB ERROR : Database has too many connections");
}
if (err.code === 'ECONNREFUSED') {
console.error("DB ERROR : Database connection was refused");
}
}
// connection이 있으면 연결되었으므로 connection을 다시 반환
if (connection) connection.release();
return
});
// pool.query()를 Promise화시켜 비동기에 사용
pool.query = util.promisify(pool.query);
module.exports = pool;
- pool을 사용할 js 파일에서 pool을 가져온 후, async 함수 내에서
pool.query()로 데이터를 가져온다.
// user.js
const router = require('express').Router();
const pool = require("../db.js"); // db connection pool
router.get('/user', async (req, res) => { // 비동기 처리
// query문 설정
let email = 'test@google.com'; // 아래 query()에 넣을 테스트용 email
let sql = 'SELECT * FROM users where email = ?';
// db connection pool을 가져오고, query문 수행
let result = await pool.query(sql, [email]); // sql의 와일드카드 ?에 email이 들어감
res.send(result);
});
pool.query()는 배열을 반환하므로 이후 데이터를 사용할 때 배열임을 감안하고 사용해야 한다.