Knex를 활용한 mariadb 다루기
1. Knex란 무엇인가? (핵심 기능)
- 쿼리 빌더:
db('users').where('id', 1).select('name')
와 같은 JavaScript 코드를SELECT name FROM users WHERE id = 1;
과 같은 실제 SQL 쿼리문으로 변환해줍니다. - 다양한 DB 지원: 동일한 Knex 코드로 MySQL, MariaDB, PostgreSQL, SQLite, Oracle 등 다양한 종류의 데이터베이스와 통신할 수 있습니다. (
client
옵션만 변경하면 됩니다.) - 안전성: SQL 인젝션(SQL Injection)과 같은 보안 공격을 막기 위해 모든 입력값을 자동으로 안전하게 처리(이스케이프)해줍니다.
- 마이그레이션 & 시딩: Laravel의 마이그레이션처럼, 데이터베이스의 스키마를 코드로 관리하고 초기 데이터를 채워 넣는 기능도 제공합니다.
2. 사용법
2.1 인스톨
npm i knex
npm i mysql2
2.2. 초기화
// 1. 라이브러리 불러오기
const knex = require("knex");
// 2. DB 연결 정보 설정
const dbConfig = {
client: "mysql2", // MariaDB/MySQL용 드라이버
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
},
};
// 3. Knex 인스턴스 생성
const db = knex(dbConfig);
client: 'mysql2'
: Node.js가 MySQL/MariaDB와 통신하기 위해 필요한mysql2
드라이버를 사용하라고 알려줍니다. (npm install mysql2
필요)connection
:.env
파일에서 읽어온 DB 접속 정보를 담습니다.- 이렇게 생성된
db
객체를 사용하여 모든 데이터베이스 작업을 수행합니다.
3. 간단한 예제 (CRUD)
users
라는 테이블이 있고, id
, name
, email
컬럼이 있다고 가정해 보겠습니다.
3.1. 데이터 조회 (SELECT - 읽기)
-
모든 사용자 조회:
async function getAllUsers() { const users = await db("users").select("*"); // 실행되는 SQL: SELECT * FROM `users`; console.log(users); // 결과는 객체 배열: [{id: 1, name: 'John'}, ...] }
-
특정 조건으로 한 명만 조회:
async function findUserById(userId) { const user = await db('users').where('id', userId).first(); // 실행되는 SQL: SELECT * FROM `users` WHERE `id` = ? LIMIT 1; // (물음표 부분은 Knex가 안전하게 userId 값으로 채워줌) console.log(user); // 결과는 단일 객체: {id: 1, name: 'John', ...} } ``` - `.first()`: 여러 개가 찾아지더라도 첫 번째 결과 하나만 반환합니다.
3.2. 데이터 생성 (INSERT - 쓰기)
async function createUser(name, email) {
const newUserId = await db("users").insert({
name: name,
email: email,
});
// 실행되는 SQL: INSERT INTO `users` (`name`, `email`) VALUES (?, ?);
console.log(`새로운 사용자가 ID ${newUserId}로 생성되었습니다.`);
}
3.3. 데이터 수정 (UPDATE)
async function updateUserEmail(userId, newEmail) {
const affectedRows = await db("users").where("id", userId).update({
email: newEmail,
updated_at: db.fn.now(), // DB의 내장 함수(NOW()) 사용
});
// 실행되는 SQL: UPDATE `users` SET `email` = ?, `updated_at` = NOW() WHERE `id` = ?;
console.log(`${affectedRows}개의 행이 수정되었습니다.`);
}
3.4. 데이터 삭제 (DELETE)
async function deleteUser(userId) {
const affectedRows = await db("users").where("id", userId).del();
// 실행되는 SQL: DELETE FROM `users` WHERE `id` = ?;
console.log(`${affectedRows}개의 행이 삭제되었습니다.`);
}
3.5. 원시 쿼리 (Raw Query)
- 복잡한 쿼리가 필요할 때는
db.raw()
를 사용하여 직접 SQL을 실행할 수도 있습니다.await db.raw( 'UPDATE macros SET logs = CONCAT(IFNULL(logs, ""), ?) WHERE id = ?', [message + "\n", jobId] );