서버의 기억 저장소: 데이터베이스 연동
Express 서버 자체는 휘발성 메모리(RAM)를 사용하기 때문에 껐다 켜면 회원 정보나 게시글이 모두 날아갑니다. 데이터를 영구적으로 보관하기 위해 MySQL이나 PostgreSQL 같은 관계형 데이터베이스(RDBMS)와 서버를 연결하는 방법을 알아봅니다.
필수 드라이버 모듈
Node.js가 DB와 대화하려면 통역사 역할을 하는 라이브러리(드라이버)를 NPM에서 설치해야 합니다.
| 데이터베이스 종류 |
설치 패키지 |
특징 |
| MySQL / MariaDB |
npm install mysql2 |
과거의 mysql 모듈보다 빠르고, 기본적으로 Promise(async/await)를 완벽 지원합니다. |
| PostgreSQL |
npm install pg |
PostgreSQL 공식 드라이버로 안정성이 뛰어납니다. |
⚡ 핵심 개념: 커넥션 풀 (Connection Pool)
DB 서버와 처음 연결(Handshake)을 맺는 과정은 아주 느리고 무거운 작업입니다. 만약 사용자 100명이 동시에 접속할 때마다 새로 연결을 맺고 끊으면 서버는 뻗어버립니다.
해결책은 커넥션 풀(Pool)입니다. 서버를 켤 때 DB와의 연결 선을 미리 10개~50개 만들어 수영장(Pool)에 담아두고, 사용자가 오면 연결 선을 빌려주고 작업이 끝나면 다시 돌려받아 재사용합니다. 실무 백엔드 개발에서 풀 사용은 선택이 아닌 필수입니다.
커넥션 풀 (Connection Pool) 성능 시뮬레이션
요청이 올 때마다 DB에 연결(Connect)하고 끊는 방식과, 미리 연결을 여러 개 만들어두고 돌려쓰는 풀(Pool) 방식의 코드를 비교해 보세요.
const mysql = require('mysql2/promise');
async function testSingleConnection() {
console.log('\n[일반 연결 모드] 100건의 쿼리를 매번 연결/해제하며 실행합니다...');
const start = Date.now();
for (let i = 0; i < 100; i++) {
// ⚠️ 매번 악수(Handshake) 비용 발생: 엄청난 병목 현상
const conn = await mysql.createConnection({ host: 'localhost', user: 'root', database: 'test' });
await conn.query('SELECT 1');
await conn.end();
}
const end = Date.now();
console.log(`> 🐢 처리 완료: 총 ${end - start}ms 소요 (매우 느림)`);
}
async function testConnectionPool() {
console.log('\n[커넥션 풀 모드] 10개의 커넥션을 풀(Pool)에 미리 만들어두고 재사용합니다...');
// ⚡ 서버 시작 시 한 번만 풀(Pool)을 생성합니다.
const pool = mysql.createPool({ host: 'localhost', user: 'root', database: 'test', connectionLimit: 10 });
const start = Date.now();
// 100건의 쿼리가 풀에서 빈 커넥션을 빌려 쓰고 즉시 반납합니다.
const promises = [];
for (let i = 0; i < 100; i++) {
promises.push(pool.query('SELECT 1'));
}
await Promise.all(promises); // 비동기 병렬 처리
const end = Date.now();
console.log(`> ⚡ 처리 완료: 총 ${end - start}ms 소요 (약 8배 빠름!)`);
await pool.end();
}
async function main() {
await testSingleConnection();
await testConnectionPool();
}
main();
$ node db_test.js
[일반 연결 모드] 100건의 쿼리를 매번 연결/해제하며 실행합니다...
> DB와 악수(Handshake) 중... (연결 수립 비용 발생)
> 응답 지연 발생! (매번 연결하고 끊느라 병목 현상)
> 🐢 처리 완료: 총 2450ms 소요 (매우 느림)
[커넥션 풀 모드] 10개의 커넥션을 풀(Pool)에 미리 만들어두고 재사용합니다...
> 미리 연결해 둔 10개의 커넥션을 쉴 틈 없이 돌려 씁니다!
> Handshake 생략! 즉시 데이터 패치 시작...
> ⚡ 처리 완료: 총 310ms 소요 (약 8배 빠름!)