Sequelize ORM

18465 단어 MVCORMSequelizeMVC

이전 포스팅에서 MVC 모델에 대하여 간략히 정리하였다.

ORM

ORM은 바로 Model을 기술하는 도구이다. 이를 통해 데이터베이스 세계와 프로그래밍 언어 사이의 개념의 간극을 줄여준다(개발자들에겐 객체지향적 프로그래밍이 익숙하므로). 이전에 쇼핑몰 데이터베이스 구축 시 SQL 명령문을 직접 사용하였다면, 이번엔 ORM을 이용하여 SQL 문을 직접 작성하지 않고 엔티티를 객체로 표현하는 방법을 학습해보았다.

Sequelize

  1. Node.js 기반의 ORM으로 PostgreSQL, MySQL, MariaDB, SQLite, MS-SQL을 지원한다.
  2. 프로미스 기반의 ORM이기 때문에 비동기 처리에 용이하다.
  3. table 대신 modeling을 통해 객체 형태로 table을 짠다.

환경 세팅

  1. git clone, npm install 을 한다.

  2. Sequelize ORM 통해 sequelize 설치
    npm install --save sequelize
    package.json에 최신버전(v6)으로 설치됐는지 확인한다.
    dependencies 항목에 추가되어 있다.

  3. Sequelize - Migrations 통해 sequelize-cli 를 설치
    npm install --save-dev sequelize-cli
    마이그레이션을 할 수 있도록 돕는 툴로, CLI에서 모델을 생성해주거나, 스키마 적용을 할 수 있도록 돕는다.

ORM 설정

공식문서를 참고하여 cli를 통해 ORM을 잘 사용할 수 있도록 bootstraping(프로젝트 초기 단계를 자동으로 설정할 수 있도록 도와주는 일)을 해주었다.
npx sequelize-cli init 명령어를 입력하면 네 개의 폴더들이 생성된다.

config/config.json
models/
migrations/
seeders/

그리고 config.json 파일에서 비밀번호를 변경한다.
개발용, 테스트용, 배포용 환경중 개발용 환경을 기본적으로 사용한다.
models폴더 index.js 를 보면
const env = process.env.NODE_ENV || 'development'; 해당 코드를 확인할 수 있다.
export NODE_ENV=production 하면 다른 환경으로 바꿀 수 있다.

{
  "development": {
    "username": "root",
    "password": null, // 비밀번호 변경
    "database": "database_development",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

모델 생성

모델은 엔티티를 객체로 표현한 형태로, 데이터 구조를 기술하고, 데이터에 수행할 수 있는 명령의 모음을 의미한다.
1. 데이터베이스 생성
mysql -u root -p mysql 을 실행
CREATE DATABASE database_development; DB생성
USE database_development; 해당 DB를 사용

  1. 모델 생성
    npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string

해당 명령어(예시)로 모델을 생성하였다. 모델명과 속성들을 각각 정의해주었다. url, title, visits 필드를 생성하였고, id, createdAt, updatedAt 필드는 자동으로 생성되었다.

마이그레이션

npx sequelize-cli db:migrate 명령어를 실행하여,
마이그레이션을 실행함으로써 데이터베이스에 해당 테이블을 생성해주었다.

  • 수정할 사항 있는 경우(기본값 등)
    npx sequelize-cli db:migrate:status 해서 상태가 up이면
    npx sequelize-cli db:migrate:undo 로 실행취소 , down으로 해놓고 수정후 다시 1번 명령어 실행한다.
    models/url.js 에서 init() 부분 내용 수정하고,
    migrations/ 파일에서도 내용을 수정해야 한다.
    스키마 변경이 있을 때마다 마이그레이션을 실행해줘야 한다.

bitly model 구현해보기

https://bitly.com/ bitly는 긴 url을 축약해서 짧게 만들어주는 어플리케이션니다. 이 어플리케이션의 모델파트를 구현해보았다.

일단 구현해야 하는 내용을 간단히 하자면 아래와 같다.

스프린트에서 직접 사용하였던 sequlize 기본 메소드

sequlize 메소드는 기본적으로 모두 promise 객체를 반환한다. 따라서 객체 내 result 값을 꺼내오려면 .then이나 async/await을 사용해야 한다.

fineAll();

GET/links 요청을 처리할 때 사용하였다. sql구문에서 SELECT * FROM TABLE 과 똑같은 처리를 한다.


const { url: URLModel } = require("../../models"); //먼저 모델폴더에서 url 모델객체를 가져온다


 get: async (req, res) => {
    const result = await URLModel.findAll();
    res.status(200).json(result);
  },

findOrCreate();

POST/links 요청을 처리할 때 사용하였다. 요청의 payload에 아래와 같이 단축시키고 싶은 URL이 url 속성에 담겨있다. findOrCreate 메소드는 해당데이터를 찾고 그 조회 결과가 없는 경우에 엔트리를 테이블에 추가한다. create는 sql 구문에서 INSERT INTO ___ VALUES___와 똑같은 처리를 한다.

{
  "url": "https://www.github.com"
}
const [result, created] = await URLModel.findOrCreate({
          where: {
            url,
          },
          default: {
            title,
          },
        });
if (created) {
          return res.status(201).json(result); // 새로 생성된 경우 create
        }
        res.status(201).json(result); // 조회한 경우 find

findOne();

GET /links/:id 요청을 처리할 때 사용하였다. findOne 메소드는 조건을 만족하는 첫번째 엔트리를 찾아낸다.
해당 id 값 바탕으로 url 모델을 찾아 리디렉션해주었다.
ex) 원본 URL이 https://www.github.com 인 모델 id가 1일 경우, http://localhost:3000/links/1 로 접속하면 원본 URL로 리디렉션

const result = await URLModel.findOne({
      where: {
        id: urlId,
      },
    });

update();

/links/:id URL로 접근할 경우 visits 필드에 카운트가 1씩 증가해줘야 하는데 그 때 필드값을 업데이트 해주는 해당 메소드를 사용하였다.

await result.update({
        visits: result.visits + 1,
      });

association을 이용한 join table 구현

1. users 테이블 생성 & 마이그레이션

npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string cli 명령어를 입력하여 새로운 모델을 생성하고, npx sequelize-cli db:migrate 명령어를 실행하여, 마이그레이션 해주었다.

2. 새 마이그레이션 파일을 생성하여 urls 테이블에 필드추가 & FK 설정하기

npx sequelize-cli migration:create --name addUserIdColumn 명령어를 입력하여 새로운 마이그레이션 파일을 생성하였다. up/down 속성이 비워진 상태로 새 마이그레이션 파일(Migration Skeleton)이 생성되었다.

해당 마이그레이션 파일내에서 아래와 같이 up/down 속성을 정의해주었다.(field 추가 & FK 설정)

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    // field 추가
    await queryInterface.addColumn('urls', 'userId', Sequelize.INTEGER);

    // foreign key 연결
    await queryInterface.addConstraint('urls', {
      fields: ['userId'],
      type: 'foreign key',
      name: 'FK_any_name_you_want',
      references: {
        table: 'users',
        field: 'id'
      },
      onDelete: 'cascade',
      onUpdate: 'cascade'
    });

  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.removeConstraint('urls', 'FK_any_name_you_want');
    await queryInterface.removeColumn('urls', 'userId');
  }
};

3. 1:N 관계 만들기

/models/index.js 파일에서 아래와 같이 associations를 설정해주었다. (user:url = 1:N)

const { url, user } = sequelize.models;
url.belongsTo(user);
user.hasMany(url);

좋은 웹페이지 즐겨찾기