MySql(MariaDB)와의 연동방법 알아보기
mysql 패키지를 이용한 Node.js와 MySQL(MariaDB) 연동 가이드
1. mysql 패키지란?
mysql 패키지는 Node.js 환경에서 MySQL 및 MariaDB 데이터베이스와 상호작용하기 위한 가장 전통적이고 널리 사용되는 드라이버입니다. 모든 비동기 작업이 콜백(Callback) 함수 스타일로 구현되어 있는 것이 특징입니다.
참고: 최근에는
Promise와async/await를 기본으로 지원하는mysql2패키지가 더 많이 사용되는 추세입니다.
2. 설치
npm install mysql
3. 연결 방식 비교
| 구분 | createPool (권장) |
createConnection |
|---|---|---|
| 개념 | 미리 만들어 둔 연결 객체를 재사용 | 매번 새로운 연결을 생성 |
| 성능 | 우수 (연결 오버헤드 없음) | 비효율적 (매번 연결/종료 비용 발생) |
| 안정성 | 높음 (자동 재연결, 연결 수 제어) | 낮음 (수동 재연결 필요) |
| 주 사용처 | 웹 서버 등 다중 요청 환경 | 단일 스크립트, 특정 트랜잭션 |
결론: 웹 애플리케이션과 같이 지속적으로 여러 DB 요청을 처리해야 하는 환경에서는 createPool 방식 사용이 강력히 권장됩니다.
4. createPool 방식 (권장)
미리 정해진 수의 연결을 풀(Pool)에 만들어두고, 필요할 때마다 가져다 쓰고 반납하는 방식입니다. 웹 서버 환경의 표준적인 DB 연결 방식입니다.
1) 주요 옵션
const mysql = require("mysql");
const pool = mysql.createPool({
// --- 필수 옵션 ---
host: process.env.DB_HOST || "localhost", // DB 서버 호스트 주소
port: process.env.DB_PORT || 3306, // DB 서버 포트
user: process.env.DB_USER, // DB 사용자 계정
password: process.env.DB_PASSWORD, // DB 계정 비밀번호
database: process.env.DB_DATABASE, // 사용할 데이터베이스 이름
// --- 성능 및 안정성 관련 옵션 (권장) ---
connectionLimit: 10, // 커넥션 풀에서 유지할 최대 연결 수 (기본값: 10)
waitForConnections: true, // 풀이 가득 찼을 때, 연결을 사용할 수 있을 때까지 대기할지 여부 (기본값: true)
queueLimit: 0, // waitForConnections가 true일 때 대기열에 쌓일 수 있는 최대 요청 수 (0: 무제한, 기본값: 0)
// --- 기타 유용한 옵션 ---
multipleStatements: true, // 한 번의 쿼리로 여러 SQL 문장을 실행할 수 있도록 허용 (SQL 인젝션 위험이 있으므로 주의 필요)
charset: "utf8mb4", // 문자 인코딩 설정
timezone: "Z", // 'local' 또는 '+09:00' (KST) 등 타임존 설정
});
2) 기본 쿼리 헬퍼 함수 (재사용 가능한 패턴)
반복적인 getConnection, release 코드를 줄이기 위해 헬퍼 함수를 만들어 사용하는 것이 효율적입니다.
function query(sql, params, callback) {
// 파라미터 유연성 확보 (params가 없는 경우 처리)
if (typeof params === "function") {
callback = params;
params = [];
}
pool.getConnection((err, connection) => {
if (err) {
console.error("Database connection failed:", err);
return callback(err);
}
connection.query(sql, params, (err, results) => {
connection.release(); // 쿼리 후 반드시 커넥션 반납!
if (err) {
console.error("Query Error:", err);
return callback(err);
}
callback(null, results);
});
});
}
3) CRUD 예제 (createPool 기반)
아래 모든 예제는 위에서 정의한 query 헬퍼 함수를 사용합니다.
Create (INSERT)
const newUser = { name: "Jane Doe", email: "jane.doe@example.com" };
const sql = "INSERT INTO users SET ?";
query(sql, newUser, (err, result) => {
if (err) return console.error("INSERT Error:", err);
console.log("New user created! Inserted ID:", result.insertId);
});
Read (SELECT)
const sql = "SELECT id, name, email FROM users WHERE id = ?";
query(sql, [1], (err, rows) => {
if (err) return console.error("SELECT Error:", err);
console.log("User Found:", rows.length > 0 ? rows[0] : "Not found");
});
Update (UPDATE)
const sql = "UPDATE users SET name = ? WHERE id = ?";
const params = ["Jane Smith", 2];
query(sql, params, (err, result) => {
if (err) return console.error("UPDATE Error:", err);
console.log("Changed Rows:", result.changedRows);
});
Delete (DELETE)
const sql = "DELETE FROM users WHERE id = ?";
query(sql, [3], (err, result) => {
if (err) return console.error("DELETE Error:", err);
console.log("Deleted Rows:", result.affectedRows);
});
4) 트랜잭션(Transaction) 처리 예제
트랜잭션은 여러 쿼리를 하나의 작업 단위로 묶어 처리하는 기능입니다.
pool.getConnection((err, connection) => {
if (err) throw err;
connection.beginTransaction((err) => {
if (err) {
connection.release();
throw err;
}
const userQuery = "INSERT INTO users SET name = 'John'";
connection.query(userQuery, (err, result) => {
if (err)
return connection.rollback(() => {
connection.release();
throw err;
});
const logQuery = "INSERT INTO logs SET user_id = ?, action = 'created'";
connection.query(logQuery, [result.insertId], (err, result) => {
if (err)
return connection.rollback(() => {
connection.release();
throw err;
});
connection.commit((err) => {
if (err)
return connection.rollback(() => {
connection.release();
throw err;
});
console.log("Transaction Complete.");
connection.release();
});
});
});
});
});
이처럼 콜백 함수가 중첩되는 구조("콜백 지옥")는 코드를 복잡하게 만듭니다. 이것이 mysql2의 async/await가 선호되는 주된 이유입니다.
5. createConnection 방식 (참고용)
단일 연결을 생성하고 모든 쿼리를 해당 연결로 처리합니다. 간단한 일회성 스크립트에 적합하며, 사용 후에는 반드시 connection.end()로 연결을 종료해야 합니다.
1) 주요 옵션
createPool과 동일한 옵션 객체를 사용합니다.
const mysql = require("mysql");
const connection = mysql.createConnection({
host: process.env.DB_HOST || "localhost",
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
});
2) 기본 사용 패턴 및 CRUD 예제
// 1. 연결 시도
connection.connect((err) => {
if (err) return console.error("Error connecting: " + err.stack);
console.log("Connected to database as id " + connection.threadId);
// --- 연결 성공 후 쿼리 실행 ---
// SELECT
connection.query("SELECT * FROM users LIMIT 1", (err, rows) => {
if (err) throw err;
console.log("User data:", rows[0]);
});
// INSERT
connection.query(
"INSERT INTO users SET ?",
{ name: "Single User" },
(err, result) => {
if (err) throw err;
console.log("Insert ID:", result.insertId);
}
);
// 모든 쿼리가 끝나면 연결을 종료해야 합니다.
connection.end((err) => {
if (err) return console.error("Error closing connection:", err);
console.log("Connection closed.");
});
});