updated_at: 2025-09-19 16:59

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]
    );
    
평점을 남겨주세요
평점 : 2.5
총 투표수 : 1

질문 및 답글