Sequelize ORM

🐶·2021년 8월 1일
0

개념 정리

목록 보기
33/41

이전 포스팅에서 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);
profile
우당탕탕 개발일기📝🤖

0개의 댓글