백엔드/Node.js

[Node.js] 시퀄라이즈(Sequelize)를 활용한 Node.js & Express & MySQL 연동

순코딩 2024. 8. 23. 23:09
아래 내용은 Mysql 설치 및 데이터베이스 생성이 완료되었다는 가정하에 진행합니다.

 

 

시퀄라이즈란?

Sequelize는 Node.js의 ORM(Object-Relational Mapping) 라이브러리로, SQL 쿼리를 작성하지 않고 JavaScript 코드로 데이터베이스 작업을 수행할 수 있습니다.

 

 

Sequelize 설정
패키지 설치
npm install sequelize sequelize-cli mysql2

 

Sequelize 초기화

Sequelize CLI를 사용하여 프로젝트를 초기화합니다.

이 명령어는 config, models, migrations, seeders 폴더를 생성합니다.

npx sequelize-cli init

 

 

데이터베이스 설정

config/config.js 파일에서 데이터베이스 설정을 변경합니다.

// 아래 코드는 보안을 위해 환경변수를 사용하였습니다.
// 이에 dotenv 라이브러리를 사용했고 파일 또한 config.json 에서 config.js로 변경하였습니다.

require('dotenv').config(); // .env 파일에서 환경 변수 로드

module.exports = {
  development: {
    username: process.env.DB_USERNAME || 'root',  // 계정명(기본적으로 root로 설정되어 있다.)
    password: process.env.DB_PASSWORD || null, // 데이터베이스 비밀번호
    database: process.env.DB_NAME || 'database_name', // 데이터베이스 이름(Mysql에서 생성한 데이터베이스 이름)
    host: process.env.DB_HOST || '127.0.0.1',
    dialect: process.env.DB_DIALECT || 'mysql',
  },
  test: {
    username: process.env.DB_USERNAME || 'root',
    password: process.env.DB_PASSWORD || null,
    database: process.env.DB_TEST_NAME || 'database_test',
    host: process.env.DB_HOST || '127.0.0.1',
    dialect: process.env.DB_DIALECT || 'mysql',
  },
  production: {
    username: process.env.DB_USERNAME || 'root',
    password: process.env.DB_PASSWORD || null,
    database: process.env.DB_PRODUCTION_NAME || 'database_production',
    host: process.env.DB_HOST || '127.0.0.1',
    dialect: process.env.DB_DIALECT || 'mysql',
  }
};

 

 

MySQL 연동

models 폴더에 index.js 파일을 생성 후 아래와 같이 작성합니다.

const Sequelize = require("sequelize"); // Sequelize ORM 라이브러리 가져오기

const env = process.env.NODE_ENV || "development"; // 실행 환경 설정 (기본값: "development")
const config = require("../config/config.json")[env]; // config.json 파일에서 현재 환경에 맞는 설정 가져오기
const db = {}; // 데이터베이스 객체 초기화

// Sequelize 인스턴스 생성 (데이터베이스 연결 설정)
const sequelize = new Sequelize(config.database, config.username, config.password, config);

// db객체 세팅
db.sequelize = sequelize; // DB 객체에 Sequelize 인스턴스 추가

// 데이터베이스 연결
sequelize
  .sync({ force: false })
  .then(() => {
    console.log("데이터베이스 연결 성공");
  })
  .catch((err) => {
    console.error(err);
  });

// DB 객체를 모듈로 내보내기
module.exports = db;
// app.js

const express = require("express");
const cors = require("cors");
const app = express();
const {sequelize} = require('./models/index');
const port = 3001;

// CORS 미들웨어 추가 (다른 도메인에서의 요청을 허용하기 위함)
app.use(cors());
app.use(express.json());

app.get("/", (req, res) => {
  res.send("hello world");
});

// 서버 실행
app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});



 

 

테이블 생성(모델 구조 정의)

models 폴더에 테이블명의 파일을 생성합니다.

ex) user 테이블을 생성하고 싶다면 user.js

이후 아래와 같이 모델 구조를 정의합니다.

// model/user.js

const Sequelize = require("sequelize"); // Sequelize ORM 라이브러리 가져오기

// User 모델 클래스 정의 (Sequelize.Model을 상속받음)
class User extends Sequelize.Model {
  // initiate 메서드에서 모델을 초기화
  static initiate(sequelize) {
    // User 모델의 스키마 정의
    User.init(
      {
        // name 필드: 최대 20자, null 허용하지 않음, 유일한 값이어야 함
        nickname: {
          type: Sequelize.STRING(30),
          allowNull: false,
          unique: true,
        },
        // email 필드: 부호 없는 정수, null 허용하지 않음
        uid: {
          type: Sequelize.STRING(100),
          allowNull: false,
        },
        // password 필드: 최대 20자, null 허용하지 않음
        password: {
          type: Sequelize.STRING(50),
          allowNull: false,
        },
        profileImage: {
          type: Sequelize.STRING(100),
          allowNull: true,
        },
      },
      {
        sequelize, // Sequelize 인스턴스를 통해 연결
        timestamps: true, // createdAt 및 updatedAt 타임스탬프 필드 자동 생성
        underscored: false, // 필드 이름을 camelCase로 유지 (스네이크 케이스가 아님)
        paranoid: true, // deletedAt 필드 추가 (소프트 삭제를 위해)
        modelName: "User", // 모델 이름 설정
        tableName: "Users", // 테이블 이름 설정
        charset: "utf8mb4", // 문자셋 설정 (이모지 지원)
        collate: "utf8mb4_general_ci", // 문자열 비교 방식 설정
      }
    );
  }
}

module.exports = User; // User 모델을 모듈로 내보내기

 

 

모델 초기화
// models/index.js

const Sequelize = require("sequelize"); // Sequelize ORM 라이브러리 가져오기
const User = require("./user.js"); // User 모델 가져오기

const env = process.env.NODE_ENV || "development"; // 실행 환경 설정 (기본값: "development")
const config = require("../config/config.js")[env]; // config.json 파일에서 현재 환경에 맞는 설정 가져오기
const db = {}; // 데이터베이스 객체 초기화

// Sequelize 인스턴스 생성 (데이터베이스 연결 설정)
const sequelize = new Sequelize(config.database, config.username, config.password, config);

// db객체 세팅
db.sequelize = sequelize; // DB 객체에 Sequelize 인스턴스 추가
db.User = User; // DB 객체에 User 모델 추가

// 모델 초기화
User.initiate(sequelize); // User 모델 초기화 (모델과 Sequelize 인스턴스 연결)

// 데이터베이스 연결
sequelize
  .sync({ force: false })
  .then(() => {
    console.log("데이터베이스 연결 성공");
  })
  .catch((err) => {
    console.error(err);
  });

module.exports = db; // DB 객체를 모듈로 내보내기

 

CRUD 

user모델(테이블)에서 CRUD 실습 코드입니다.

이 때  가져오는 모듈은 models/index.js 임을 유의하시길 바랍니다.

// routes/sign-up.js

const express = require("express");
const router = express.Router();
const { User } = require("../models/index");

// CREATE: 사용자 생성
router.post("/", async (req, res) => {
  try {
    const user = await User.create(req.body);
    res.status(201).json(user);
  } catch (error) {
    res.status(500).send("회원가입 실패");
  }
});

// READ: 특정 사용자 조회
router.get("/:id", async (req, res) => {
  try {
    const user = await User.findByPk(req.params.id);
    user ? res.json(user) : res.status(404).send("사용자 없음");
  } catch (error) {
    res.status(500).send("조회 실패");
  }
});

// UPDATE: 사용자 수정
router.put("/:id", async (req, res) => {
  try {
    const user = await User.findByPk(req.params.id);
    user ? (await user.update(req.body), res.json(user)) : res.status(404).send("사용자 없음");
  } catch (error) {
    res.status(500).send("수정 실패");
  }
});

// DELETE: 사용자 삭제
router.delete("/:id", async (req, res) => {
  try {
    const user = await User.findByPk(req.params.id);
    user ? (await user.destroy(), res.sendStatus(204)) : res.status(404).send("사용자 없음");
  } catch (error) {
    res.status(500).send("삭제 실패");
  }
});

module.exports = router;

 

 

결과

DB에 데이터가 잘 추가된 모습을 확인할 수 있다.