본문 바로가기
개발공부일지/DataBase

ORM - Sequelize 기본 사용하기

by Hynn1429 2023. 1. 12.
반응형

안녕하세요.

Hynn 입니다.

 

이번 포스팅에서는 Sequelize 사용의 기본 구성을 작성해보도록 하겠습니다.

Sequelize 는 MVC Pattern 을 사용해서, Module 을 사용한 중앙집중식 구조로 의존성을 덜어 작성해보도록 하겠습니다.

 

==============

==============

기본 작성예제는, Sequelize Official Document 내용을 기반으로 해설하여 작성해보도록 하겠습니다.

이 Sequelize 는 개인적으로 공식 문서가 방대한만큼이나 세세하게 작성이 되어 있어서, 이를 기반으로 학습을해도 될 정도로 많은 내용이 세부적으로 나와 있습니다.

1)Sequelize Module Setting

먼저 자신이 사용할 DB 의 대한 Module 설치를 해야합니다.

예제에서는 "MySQL" 을 사용할 것이므로, MySQL 과 Sequelize 를 모두 설치해야 합니다.

아래의 명령어를 Terminal 에서 사용해보도록 하겠습니다.

// mysql Install
npm install mysql2

//Sequelize Install
npm install sequelize

그리고 나서, DB에 이제 연결을 해야합니다. 

공식 문서에 제공되는 기본 Code 를 가지고 보도록 하겠습니다.

const { Sequelize } = require('sequelize');

// Option 1: Passing a connection URI
const sequelize = new Sequelize('sqlite::memory:') // Example for sqlite
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname') // Example for postgres

// Option 2: Passing parameters separately (sqlite)
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: 'path/to/database.sqlite'
});

// Option 3: Passing parameters separately (other dialects)
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: /* one of 'mysql' | 'postgres' | 'sqlite' | 'mariadb' | 'mssql' | 'db2' | 'snowflake' | 'oracle' */
});

 

먼저 당연하게도 Sequelize 를 가져와야 합니다.

따라서 Const 로 "Sequelize" 라는 변수를 선언하고 변수 안에는 "Require" method 를 사용하여 'sequelize' 를 가져오도록 설정합니다.

다만 위의 예시에서는 구조분해문으로 작성이 되었습니다.

꼭 구조분해 할당으로 작성할 필요는 없지만, 각각의 특성에 따라서 자신이 원하는 방식으로의 최초 설정을 하시면 되겠습니다.

각각의 옵션은 아래의 특성을 지니고 있습니다. 

 

  • Option 1 : 연결 URI를 전달하여 연결하는방법, URI(Uniform Resource Identifier)
  • Option 2 : 매개변수를 별도로 전달하는 방식으로 DataBase 연결
  • Option 3 : 매개변수를 개별적으로 전달하는 방법

여기서 중요하게 적용되어야 할 "dialect" 는 이후에도 나오게 될 속성이므로, 꼭 기억하도록 합시다.

이제 DB와 Sequelize 를 연결했다면, 아래의 Code 를 가지고 테스트가 가능합니다. 

try {
  await sequelize.authenticate();
  console.log('Connection has been established successfully.');
} catch (error) {
  console.error('Unable to connect to the database:', error);
}

위 테스트 코드에서 테스트를 가능하게 핵심 method 는 바로 ".authenticate()" 입니다.

이 method 가 Module 에 내장이 되어 있어, 테스트가 가능하며, 이를 통해 올바르게 연결이 되었는지, 연결이 되지 않았는지를 확인할 수 있습니다. 

 

만약 Sequelize 에서 종료하기를 원한다면 아래의 코드를 적용하여 종료할 수 있습니다.

다만 이 코드를 호출하게 될 경우, Sequelize 는 완전히 연결을 종료합니다. 따라서 이러한 경우 새로운 인스턴스(Instance) 를 생성해야 하므로, 사용에 주의가 필요합니다.

sequelize.close()

2)Sequelize Model 설정하기

const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');

const User = sequelize.define('User', {
  // Model attributes are defined here
  firstName: {
    type: DataTypes.STRING,
    allowNull: false
  },
  lastName: {
    type: DataTypes.STRING
    // allowNull defaults to true
  }
}, {
  // Other model options go here
});

// `sequelize.define` also returns the model
console.log(User === sequelize.models.User); // true

먼저 ".define()" 을 통해 Sequelize 를 정의해야 합니다.

Define() 은 이제 Sequelize 에서 DB를 정의해야 하는 method 입니다. 세부 설명은 아래와 같습니다.

 

먼저 "Defined" 은 아래의 규칙을 설정하면, 이해가 더 쉽습니다.

먼저 Define() 에서는 총 3개의 정의 분류가 필요합니다. 아래의 순서가 중요합니다.

 

  1. Table Name
  2. Table Attribute
  3. Table Option

첫번째는 단순히 Table 명을 설정하므로 예시에서는 "User" 를 부여햇습니다.

그리고 {} 를 사용해서 각각의 Attribute 를 생성합니다. 예시 구문에서는 "firstName" 을 생성하고 이 Attribute 내의 속성을 부여합니다. type 은 INT,VARCHAR 같은 속성입니다. 

allowNull 은 Null, NotNull 을 부여합니다. 

 

그리고 세번째로는, Table 의 인코딩이나, Timestamp 같은 일부 옵션을 부여합니다. 

물론 아래와 같이 추가 확장 옵션도 제공이 됩니다. 본질적으로 같은 방식으로 접근하지만, 기존의 Query 구문을 method 들이 "객체화" 하여 Code 를 작성하는 것이, 이 ORM 의 핵심이기도 하기 때문에, 이러한 객체/method 를 생각하고 접근해야 합니다.

 

init() 예시문은 아래의 사항입니다.

const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');

class User extends Model {}

User.init({
  // Model attributes are defined here
  firstName: {
    type: DataTypes.STRING,
    allowNull: false
  },
  lastName: {
    type: DataTypes.STRING
    // allowNull defaults to true
  }
}, {
  // Other model options go here
  sequelize, // We need to pass the connection instance
  modelName: 'User' // We need to choose the model name
});

// the defined model is the class itself
console.log(User === sequelize.models.User); // true

이제 실제 기초 작성을 살펴보도록 하겠습니다.

 

이제 실제 MVC Design Pattern 에 기초하여 작성을 해보도록 하겠습니다.

먼저 DB 와 연결을 위해 Model 에서 DB와 연결을 준비합니다.

const Sequelize = require('sequelize');
const sequelize = new Sequelize(db.database, db.username, db.password, db)
const user = require("./user.model")(sequelize, Sequelize)
module.exports = {
    Sequelize,sequelize
}

소문자와 대문자로 각각의 변수를 분리해주고, 그에 맞게 export 를 구성합니다.

그리고 각각 Controller, Service, repository 에 설정을 부여합니다.

1)Repository 설정하기

class UserRepository {
    constructor({ Users }){
        this.Users = Users;
    }

    async AddUser(payload){
        try{
            // const users1 = await this.Users.create({ userid: ${userid}, userpw:${userpw}, username: ${username}});
            // const users2 = await this.Users.create({userid:'124', userpw:'124', username:'asd'}); // like this "req.body"
            const users = await this.Users.create(payload);
            return users;
        }catch(e){
            throw new Error(e);
        };
    };

    async GetUserByToken({ userid }){
        // findOne = select * from users
        // inclusive where userid='Hynn'
        const user = await this.Users.findOne({
            where:{
                userid:userid,
            },
        })

        return user.dataValues
    }
};

module.exports = UserRepository

2)Service 설정하기

class UserService {
    constructor({ UserRepository}){
        this.UserRepository = UserRepository;

    };

    async SignUp({ userid, userpw, username }){
        try{
            //add to logic 
            const user = await this.UserRepository.AddUser({userid, userpw, username});
            return user;
        }catch(e){
            throw new Error (e)
        }
    }
};

module.exports = UserService;

3)Controller 설정하기

class UserController {
    constructor({ UserService }){
        this.UserService = UserService;
    };
    async PostSignUp(req,res,next){
        try{
            const { userid, userpw, username } = req.body;
            const response = await this.UserService.SignUp({ userid,userpw,username });
            res.status(201).json(response);
        }catch(e){
            throw new Error(e);
        };
    };
};

module.exports = UserController;

 

각각의 구성에서 이전과 크게 다른부분은 없습니다.

기존에는 mysql.query() 문을 사용해서 SQL Query 구문을 입력하던것에 비해, ORM의 특성답게, Object, 즉 객체화하여 코드를 작성하는것이 기존의 Query 문을 사용하는것에 비해 코드가 직관적으로 보여지기 시작합니다.

 

다음 포스팅에서는 CRUD 기본 작성을 다루어보도록 하겠습니다.

 

감사합니다.

반응형

댓글