Node.js + MySQL 연동
이 토픽을 마치면
Node.js에서 MySQL에 연결하고, CRUD 쿼리를 실행하는 코드를 작성할 수 있습니다.
왜 Node.js에서 데이터베이스를?
지금까지 SQL을 MySQL 클라이언트에서 직접 입력했습니다. 하지만 실제 웹 서비스는 코드가 자동으로 SQL을 실행해야 합니다.
사용자가 회원가입 버튼을 누르면 → 서버가 INSERT INTO users ... 를 실행 → 결과를 응답으로 돌려줍니다. 이 과정을 Node.js 코드로 구현합니다.
mysql2 설치와 연결
npm install mysql2const mysql = require('mysql2');
// 연결 설정
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'mypassword',
database: 'myapp'
});
// 연결 확인
connection.connect((err) => {
if (err) {
console.error('연결 실패:', err.message);
return;
}
console.log('MySQL 연결 성공');
});mysql2는 Node.js에서 MySQL을 사용하는 표준 라이브러리입니다. mysql이라는 오래된 패키지도 있지만, mysql2가 더 빠르고 Promise를 지원합니다.
쿼리 실행 — CRUD
데이터 조회 (SELECT)
connection.query('SELECT * FROM users', (err, rows) => {
if (err) {
console.error(err);
return;
}
console.log(rows);
// [ { id: 1, name: '김훈', email: 'hoon@example.com' }, ... ]
});결과는 JavaScript 배열로 돌아옵니다. 각 행이 객체 하나입니다.
데이터 삽입 (INSERT)
const name = '박진';
const email = 'jin@example.com';
connection.query(
'INSERT INTO users (name, email) VALUES (?, ?)',
[name, email],
(err, result) => {
if (err) {
console.error(err);
return;
}
console.log('삽입된 ID:', result.insertId);
}
);?는 플레이스홀더입니다. 값을 배열로 전달하면 mysql2가 안전하게 대입합니다.
데이터 수정 (UPDATE)
connection.query(
'UPDATE users SET email = ? WHERE id = ?',
['new@example.com', 1],
(err, result) => {
console.log('수정된 행:', result.affectedRows);
}
);데이터 삭제 (DELETE)
connection.query(
'DELETE FROM users WHERE id = ?',
[3],
(err, result) => {
console.log('삭제된 행:', result.affectedRows);
}
);플레이스홀더 (?) — 왜 중요한가
// ❌ 절대 이렇게 하지 마세요
const userInput = "'; DROP TABLE users; --";
connection.query(`SELECT * FROM users WHERE name = '${userInput}'`);
// ✅ 항상 플레이스홀더 사용
connection.query('SELECT * FROM users WHERE name = ?', [userInput]);사용자 입력을 SQL 문자열에 직접 넣으면 SQL 인젝션 공격에 노출됩니다. 플레이스홀더(?)를 쓰면 mysql2가 자동으로 위험한 문자를 이스케이프합니다.
커넥션 풀 — 실전 패턴
실제 서버에서는 요청마다 연결을 만들고 끊는 대신, 커넥션 풀을 사용합니다.
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'mypassword',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10
});
// 풀에서 쿼리 실행 (연결 자동 관리)
pool.query('SELECT * FROM users WHERE id = ?', [1], (err, rows) => {
console.log(rows);
});풀은 미리 여러 개의 연결을 만들어두고, 쿼리가 들어오면 빈 연결을 할당합니다. 쿼리가 끝나면 연결을 풀에 반환합니다. 매번 연결/해제 비용이 사라집니다.
Promise 방식 (async/await)
콜백 패턴이 복잡하다면 Promise 방식을 사용할 수 있습니다.
const mysql = require('mysql2/promise');
async function main() {
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'mypassword',
database: 'myapp'
});
const [rows] = await pool.query('SELECT * FROM users');
console.log(rows);
const [result] = await pool.query(
'INSERT INTO users (name, email) VALUES (?, ?)',
['새사용자', 'new@example.com']
);
console.log('삽입 ID:', result.insertId);
}
main();mysql2/promise를 import하면 모든 메서드가 Promise를 반환합니다. await로 깔끔하게 사용할 수 있습니다.