Node.js에서 MySQL 연동하는 방법

제공

안녕하세요! 오늘은 Node.js에서 MySQL을 어떻게 연동하는지 같이 알아보려고 해요. 웹 개발하면 데이터베이스는 정말 빼놓을 수 없잖아요? Node.js는 워낙 가볍고 빠른데, 여기에 MySQL까지 연동하면 정말 강력한 조합이 된답니다. 초보 개발자분들은 데이터베이스 연동이 어렵게 느껴질 수도 있는데, 걱정 마세요! 제가 MySQL 설치부터 Node.js 연결, 그리고 실제 쿼리 실행까지 차근차근 설명해 드릴게요. 데이터베이스 쿼리도 어떻게 활용하면 좋은지 꿀팁까지 알려드릴 거예요. 같이 한 단계씩 따라 해 보면 생각보다 쉽다는 걸 알게 될 거예요! 자, 그럼 이제 Node.jsMySQL의 세계로 함께 떠나볼까요?

 

 

MySQL 설치 및 설정

자, 이제 본격적으로 Node.js와 MySQL의 아름다운 만남을 위한 첫걸음! MySQL 설치 및 설정에 대해 알아볼까요? 마치 멋진 요리를 만들기 위해 신선한 재료를 준비하는 것처럼 말이죠!

설치부터 꼼꼼하게, 그리고 설정까지 섬세하게 다뤄보도록 하겠습니다. 준비되셨나요?

MySQL을 설치하는 방법은 운영체제(OS)에 따라 조금씩 달라요. 마치 같은 언어라도 사투리가 있는 것처럼요! 윈도우, macOS, 리눅스… 각자의 매력이 있잖아요? 각 OS별 설치 방법을 자세히 알려드릴게요.

Windows MySQL 설치

Windows: MySQL 공식 웹사이트에서 MSI Installer를 다운로드하는 것이 가장 일반적이에요. 설치 과정 중에는 “Custom Setup”을 선택해서 원하는 기능만 설치할 수도 있답니다. 마치 뷔페처럼 내 입맛에 맞게 골라 먹는 재미가 있죠! 설치 유형은 “Development Computer”, “Server only”, “Client only”, “Full”, “Custom” 이렇게 다섯 가지가 있어요. 용도에 따라 선택하면 되는데, 개발 목적이라면 “Development Computer”가 적절해요. 포트 번호는 기본값인 3306을 유지하는 걸 추천합니다. 괜히 바꿨다가 나중에 헷갈릴 수도 있으니까요!

macOS MySQL 설치

macOS: Homebrew를 사용하면 터미널에서 간단하게 설치할 수 있어요! brew install mysql 명령어 하나면 끝! 정말 간편하죠? Homebrew는 macOS 패키지 관리자로, 다양한 소프트웨어를 쉽게 설치하고 관리할 수 있게 도와준답니다. 마치 마법 지팡이 같아요! 설치 후에는 mysql.server start 명령어로 MySQL 서버를 시작할 수 있어요.

Linux (Ubuntu/Debian) MySQL 설치

Linux (Ubuntu/Debian): apt 패키지 관리자를 사용하는 것이 가장 일반적입니다. 터미널에서 sudo apt-get update 명령어로 패키지 목록을 업데이트하고, sudo apt-get install mysql-server 명령어로 MySQL 서버를 설치할 수 있어요. 리눅스는 명령어 기반이라 처음엔 어려워 보일 수 있지만, 익숙해지면 정말 편리해요! 설치 과정 중 root 계정의 비밀번호를 설정하라는 메시지가 나오는데, 꼭 기억하기 쉬우면서도 보안에 강한 비밀번호를 설정해야 해요!

MySQL 설정

설치를 완료했다면 이제 설정을 해야겠죠? 마치 새 옷을 사면 내 몸에 맞게 수선하는 것처럼 말이에요! MySQL 설정 파일은 OS에 따라 위치가 다르지만, 일반적으로 my.cnf 또는 my.ini 파일이에요. 이 파일을 열어서 다양한 설정을 변경할 수 있답니다.

중요한 설정 몇 가지를 알려드릴게요.

  • port: MySQL 서버가 사용할 포트 번호를 지정합니다. 기본값은 3306이에요.
  • bind-address: MySQL 서버가 연결을 허용할 IP 주소를 지정합니다. 모든 IP 주소에서 연결을 허용하려면 0.0.0.0으로 설정하고, 로컬에서만 연결을 허용하려면 127.0.0.1로 설정하면 됩니다.
  • character-set-server: MySQL 서버의 기본 문자 집합을 설정합니다. utf8mb4를 사용하는 것이 좋습니다. 이모지까지 완벽하게 지원하거든요!
  • innodb_buffer_pool_size: InnoDB 스토리지 엔진의 성능에 중요한 영향을 미치는 설정입니다. 시스템 메모리의 50~75% 정도로 설정하는 것이 좋다고 알려져 있어요. 마치 자동차 엔진의 배기량처럼, 크면 클수록 좋지만 너무 크면 과부하가 걸릴 수도 있으니 적절한 크기를 설정하는 것이 중요해요!

설정 파일을 수정한 후에는 MySQL 서버를 재시작해야 변경 사항이 적용됩니다. 윈도우에서는 서비스 관리자에서, macOS와 리눅스에서는 터미널에서 재시작 명령어를 실행하면 돼요. 자, 이제 MySQL 설치 및 설정이 완료되었습니다! 다음 단계로 넘어갈 준비가 되었나요? Node.js와 MySQL을 연결하는 방법에 대해 알아보도록 하겠습니다.

 

Node.js와 MySQL 연결하기

자, 이제 본격적으로 Node.js와 MySQL을 연결하는 방법에 대해 알아볼까요? 마치 두 개의 다른 세상을 이어주는 다리처럼 말이죠! 설렘 반, 기대 반으로 시작해 봅시다!

Node.js는 이벤트 기반의 비동기 방식으로 작동하고, MySQL은 관계형 데이터베이스 시스템입니다. 이 둘은 각자의 영역에서 뛰어난 성능을 자랑하지만, 서로 연결되어야만 비로소 강력한 시너지를 발휘할 수 있어요. 마치 찰떡궁합처럼요!

mysql2 패키지

이 연결 과정에서 가장 중요한 역할을 하는 것이 바로 mysql2라는 npm 패키지입니다. mysql 패키지의 개선된 버전인 mysql2Promise 지원, Prepared Statement, 연결 풀링 등 다양한 기능을 제공하여 더욱 효율적이고 안전하게 데이터베이스를 관리할 수 있도록 도와줍니다. 정말 든든한 지원군이죠!

mysql2 패키지를 설치하려면 터미널에서 npm install mysql2 명령어를 실행하면 됩니다. 참 쉽죠? 설치가 완료되면, 이제 본격적으로 코드를 작성해 볼 차례입니다.

const mysql = require('mysql2/promise'); // Promise 기반으로 mysql2 임포트!

async function connectToDatabase() {
  try {
    const connection = await mysql.createConnection({ // async/await으로 비동기 처리!
      host: 'localhost', // 데이터베이스 호스트 주소 (보통 localhost)
      user: 'your_username', // MySQL 사용자 이름
      password: 'your_password', // MySQL 비밀번호
      database: 'your_database_name', // 사용할 데이터베이스 이름
      port: 3306, // MySQL 포트 번호 (기본값: 3306)
      waitForConnections: true, // 연결 풀이 가득 찼을 때 대기할지 여부 (기본값: true)
      connectionLimit: 10, // 최대 연결 수 (기본값: 10)
      queueLimit: 0, // 대기열 제한 (0은 무제한)
    });

    console.log('MySQL 데이터베이스에 연결되었습니다!');

    // 연결을 유지한 상태에서 다른 작업 수행 가능!
    // 예: 데이터베이스 쿼리 실행

    return connection; // 연결 객체 반환
  } catch (error) {
    console.error('데이터베이스 연결 오류:', error);
    throw error;
  }
}

// 함수 호출 예시
async function performDatabaseOperations() {
  const connection = await connectToDatabase();

  try {
      // 쿼리 실행 예시 (나중에 더 자세히 다룰 예정!)
      const [rows, fields] = await connection.execute('SELECT * FROM your_table');
      console.log('쿼리 결과:', rows);

  } finally {
      // 작업 완료 후 연결 종료 (중요!)
      connection.end();
      console.log('데이터베이스 연결 종료!');
  }
}

performDatabaseOperations();

코드 설명

위 코드에서는 mysql2/promise를 사용하여 Promise 기반으로 MySQL에 연결하는 방법을 보여주고 있습니다. async/await 구문을 사용하면 비동기 코드를 마치 동기 코드처럼 간결하게 작성할 수 있다는 장점이 있죠!

createConnection() 함수를 통해 데이터베이스 연결 객체를 생성하고, host, user, password, database 등의 필수 정보를 객체 형태로 전달합니다. port, waitForConnections, connectionLimit, queueLimit와 같은 추가 옵션을 통해 연결 설정을 더욱 세밀하게 조정할 수도 있어요.

try...catch 블록을 사용하여 연결 과정에서 발생할 수 있는 오류를 처리하고, finally 블록에서 연결을 안전하게 종료하는 것도 잊지 말아야 합니다. 자원 누수를 방지하는 좋은 습관이니까요!

connectionLimit 옵션

connectionLimit 옵션을 통해 연결 풀의 크기를 제한하여 서버 과부하를 방지할 수 있습니다. 예를 들어, connectionLimit 값을 10으로 설정하면 최대 10개의 연결만 유지되고, 추가 요청은 대기열에 들어가게 됩니다.

queueLimit 옵션

queueLimit 옵션은 대기열의 크기를 제한합니다. 0으로 설정하면 대기열 크기가 무제한이 됩니다. 하지만, 대기열이 너무 길어지면 성능 저하가 발생할 수 있으므로 적절한 값으로 설정하는 것이 중요합니다.

이렇게 Node.js와 MySQL을 연결하면 데이터베이스에 저장된 정보를 Node.js 애플리케이션에서 자유롭게 활용할 수 있게 됩니다. 정말 멋지지 않나요? 다음에는 데이터베이스 쿼리 실행 방법에 대해 알아보겠습니다. 기대해주세요!

 

데이터베이스 쿼리 실행

자, 이제 본격적으로 Node.js를 통해 MySQL 데이터베이스에 쿼리를 날려볼 시간이에요! 두근두근하지 않나요? 마치 새로운 세상으로 향하는 문을 여는 기분이랄까~? 앞에서 연결까지 착실하게 해 두셨으니 이제 쿼리만 실행하면 데이터베이스와 자유롭게 소통할 수 있어요. 마치 텔레파시를 쓰는 것처럼 말이죠!

SQL(Structured Query Language)

MySQL 쿼리는 기본적으로 SQL(Structured Query Language)을 사용해요. SQL은 데이터베이스와 대화하는 데 사용하는 표준 언어라고 생각하면 돼요. “데이터 좀 줘봐~”, “새로운 데이터 추가해줘~” 와 같은 요청을 하는 거죠! 참 쉽죠?!

Node.js에서 MySQL 쿼리 실행

Node.js에서는 mysql 모듈을 사용해서 쿼리를 실행할 수 있어요. 이 모듈은 connection 객체의 query() 메서드를 제공하는데, 이 메서드를 사용하면 SQL 쿼리를 전송하고 결과를 받아올 수 있답니다. 정말 편리하죠?

query() 메서드는 일반적으로 세 가지 인자를 받아요: 실행할 SQL 쿼리, 쿼리에 필요한 매개변수(선택 사항), 그리고 콜백 함수! 콜백 함수는 쿼리 실행 결과를 처리하는 역할을 해요. 쿼리가 성공적으로 실행되면 결과 데이터를, 실패하면 에러 정보를 반환하죠. 마치 우체부 아저씨처럼 말이에요!

SELECT 쿼리 예제

자, 그럼 간단한 SELECT 쿼리를 실행하는 예제를 살펴볼까요? 예를 들어, users 테이블에서 모든 사용자 정보를 가져오고 싶다면 다음과 같이 코드를 작성할 수 있어요.

connection.query('SELECT * FROM users', (error, results, fields) => {
  if (error) {
    console.error('쿼리 실행 중 오류 발생: ', error);
    // 오류 처리 로직 추가 (예: 에러 메시지 표시, 로그 기록 등)
    return; // 또는 throw error;
  }

  console.log('쿼리 실행 결과:', results);
  // results는 배열 형태로 데이터를 담고 있어요.
  // 각 요소는 테이블의 한 행에 해당하는 객체입니다.

  console.log('필드 정보:', fields);
  // fields는 쿼리 결과의 필드 정보를 담고 있어요.
  // 예를 들어, 필드 이름, 타입, 길이 등의 정보를 확인할 수 있죠.
});

위 코드에서 results에는 users 테이블의 모든 데이터가 담겨 있을 거예요. fields에는 각 컬럼에 대한 정보(이름, 타입 등)가 담겨 있고요! 이 정보들을 활용해서 원하는 데이터를 추출하고 가공할 수 있답니다.

INSERT, UPDATE, DELETE 쿼리 예제

INSERT, UPDATE, DELETE 쿼리도 비슷한 방식으로 실행할 수 있어요. 다만, 쿼리 문자열과 매개변수만 변경해주면 된답니다. 정말 간단하죠?

// INSERT 예제
connection.query('INSERT INTO users (name, email) VALUES (?, ?)', ['홍길동', 'gildong@example.com'], (error, results) => {
  // ... 결과 처리 ...
});

// UPDATE 예제
connection.query('UPDATE users SET email = ? WHERE id = ?', ['updated_email@example.com', 1], (error, results) => {
  // ... 결과 처리 ...
});

// DELETE 예제
connection.query('DELETE FROM users WHERE id = ?', [1], (error, results) => {
  // ... 결과 처리 ...
});

Placeholder와 SQL Injection

여기서 중요한 점!! 바로 placeholder(?)를 사용하는 거예요! placeholder를 사용하면 SQL Injection 공격을 예방할 수 있답니다. 보안은 정말 중요하니까요! 꼭 기억해 두세요!

Connection 종료

또한, 쿼리 실행 후에는 반드시 connection.end()를 호출해서 연결을 끊어주는 것도 잊지 마세요! 자원을 효율적으로 관리하는 습관, 정말 중요해요!

자, 이제 여러분은 Node.js를 통해 MySQL 데이터베이스를 자유자재로 다룰 수 있게 되었어요! 정말 멋지지 않나요? 이제 여러분의 상상력을 마음껏 펼쳐보세요! 무궁무진한 가능성이 여러분을 기다리고 있답니다!

 

실제 예제와 활용팁

자, 이제까지 Node.js와 MySQL을 연결하고 쿼리를 실행하는 기본적인 방법들을 알아봤어요! 그런데 이론만으론 뭔가 아쉽죠? 마치 레시피만 보고 요리를 안 해본 느낌이랄까요? ^^ 그래서! 실제로 어떻게 활용할 수 있는지, 살아 숨 쉬는 예제들을 가지고 왔답니다! 더 나아가, 성능 향상 꿀팁들까지 알려드릴 테니, 집중해 주세요~?!

1. 회원가입 및 로그인 기능 구현 예제

웹 서비스에서 가장 기본적이면서도 중요한 기능 중 하나! 바로 회원가입과 로그인이죠. MySQL을 이용해서 어떻게 구현하는지 볼까요?

const mysql = require('mysql2/promise');

// ... (DB 연결 설정)

async function createUser(username, password) {
    const connection = await mysql.createConnection(dbConfig);
    try {
        const hashedPassword = bcrypt.hashSync(password, 10); // 비밀번호 암호화! 필수!
        const [rows] = await connection.execute(
            'INSERT INTO users (username, password) VALUES (?, ?)',
            [username, hashedPassword]
        );
        console.log(`${rows.affectedRows}개의 행이 삽입되었습니다.`);
        return rows.insertId; // 새로 생성된 user의 ID 반환!
    } catch (err) {
        console.error("회원 생성 중 오류 발생:", err);
        throw err; // 에러 처리 잊지 마세요!
    } finally {
        connection.end(); // 연결 종료 필수!
    }
}

async function loginUser(username, password) {
    const connection = await mysql.createConnection(dbConfig);
    try {
        const [rows] = await connection.execute(
            'SELECT * FROM users WHERE username = ?',
            [username]
        );
        if (rows.length === 0) {
            return false; // 해당 유저 없음!
        }
        const user = rows[0];
        const isPasswordValid = bcrypt.compareSync(password, user.password); // 암호화된 비밀번호 비교!
        if (isPasswordValid) {
            return user; // 로그인 성공! 유저 정보 반환!
        } else {
            return false; // 비밀번호 틀림!
        }
    } catch (err) {
        console.error("로그인 중 오류 발생:", err);
        throw err;
    } finally {
        connection.end();
    }
}

bcrypt 라이브러리를 사용해서 비밀번호를 암호화하는 것, 잊지 않으셨죠? 보안은 아무리 강조해도 지나치지 않으니까요! try...catch...finally 구문을 사용해서 에러 처리와 연결 종료를 확실하게 해주는 것도 중요해요.

2. 게시판 글 목록 가져오기 예제 (페이징 처리 포함!)

자, 이번엔 게시판 글 목록을 가져오는 예제를 볼까요? 데이터가 많아지면 페이징 처리는 필수죠!

async function getPosts(page = 1, limit = 10) {
    const connection = await mysql.createConnection(dbConfig);
    try {
        const offset = (page - 1) * limit;
        const [rows] = await connection.execute(
            'SELECT * FROM posts ORDER BY created_at DESC LIMIT ?, ?',
            [offset, limit]
        );
        return rows;
    } catch (err) {
        console.error("게시글 목록 가져오는 중 오류 발생:", err);
        throw err;
    } finally {
        connection.end();
    }
}

LIMITOFFSET을 활용해서 페이징 처리를 간단하게 구현했어요. ORDER BY를 사용해서 최신 글이 먼저 보이도록 정렬했답니다.

3. 성능 향상 팁: Connection Pool 활용!

매번 쿼리를 실행할 때마다 연결하고 끊는 것은 비효율적이에요. Connection Pool을 사용하면 이미 생성된 연결을 재사용해서 성능을 향상시킬 수 있답니다. mysql2에서는 createPool 함수를 사용하면 돼요!

const pool = mysql.createPool(dbConfig);

async function getSomething() {
    try {
      const [rows, fields] = await pool.execute('SELECT * FROM something');
      return rows;
    } catch (err) {
        console.error("에러 발생:", err);
        throw err;
    }
}

// pool.end()를 사용하여 pool을 종료할 수 있습니다. (서버 종료 시 등)

Connection Pool을 사용하면 연결 생성 오버헤드를 줄여서 훨씬 빠른 쿼리 실행이 가능해진답니다!

4. Prepared Statement 활용하기

Prepared Statement는 SQL Injection 공격을 방지하고 쿼리 성능을 향상시키는 데 도움이 돼요. ?를 사용해서 placeholder를 만들고, 값을 배열로 전달하는 방식이죠! 위의 예제들에서 이미 사용하고 있었답니다~ 보안과 성능, 두 마리 토끼를 잡을 수 있는 아주 좋은 방법이에요!

5. 트랜잭션 관리

여러 쿼리를 하나의 작업 단위로 묶어서 처리해야 할 때, 트랜잭션을 사용해야 해요. 모든 쿼리가 성공적으로 실행되어야 데이터베이스에 반영되도록 하는 것이죠!

async function transferMoney(fromUserId, toUserId, amount) {
    const connection = await mysql.createConnection(dbConfig);
    try {
        await connection.beginTransaction(); // 트랜잭션 시작!
        await connection.execute(
            'UPDATE users SET balance = balance - ? WHERE id = ?',
            [amount, fromUserId]
        );
        await connection.execute(
            'UPDATE users SET balance = balance + ? WHERE id = ?',
            [amount, toUserId]
        );
        await connection.commit(); // 모든 쿼리 성공! 커밋!
        console.log("송금 완료!");
    } catch (err) {
        await connection.rollback(); // 에러 발생! 롤백!
        console.error("송금 중 오류 발생:", err);
        throw err;
    } finally {
        connection.end();
    }
}

beginTransaction(), commit(), rollback() 메서드를 사용해서 트랜잭션을 관리할 수 있어요. 데이터의 일관성을 유지하는 데 필수적인 기능이랍니다!

자, 여기까지 Node.js에서 MySQL을 연동하는 방법에 대해 알아봤어요. 실제 예제와 활용팁들을 통해 더욱 쉽게 이해하셨길 바랍니다. 이제 여러분도 Node.js와 MySQL을 활용해서 멋진 웹 서비스를 만들어 보세요! 화이팅!

 

자, 이제 Node.js와 MySQL을 연결하는 방법에 대한 긴 여정이 끝났네요! 처음엔 어려워 보였을 수도 있지만, 차근차근 따라오셨다면 이제 여러분도 데이터베이스 연동의 기초를 다지셨을 거예요. 직접 코드를 작성하고 실행해보면서 훨씬 더 깊이 있는 이해를 얻으셨기를 바라요. 앞으로 여러분의 프로젝트에서 데이터베이스를 자유자재로 활용하며 멋진 웹 서비스를 만들어낼 수 있을 거예요. 배움의 즐거움을 느끼셨다면 더할 나위 없이 기쁘고요. 궁금한 점이 있다면 언제든 질문 남겨주세요. 함께 더 깊이 파고들어 보아요! 앞으로의 개발 여정을 응원할게요!

 


코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다