[Database] ORM, im-sprint-shortly-mvc

윤태영 | Taeyoung Yoon·2022년 5월 19일
0

TIL (Today I Learned)

목록 보기
41/53
post-thumbnail

ORM

(Object Relational Mapping)
객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해주는 것을 말한다.

  • 객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다.
  • 객체 모델과 관계형 모델 간에 불일치가 존재하는데 ORM은 SQL을 자동으로 생성하여 불일치를 해결해준다.

객체를 통해 간접적으로 데이터베이스 데이터를 다룰수 있게 해준다.

  • 데이터베이스 데이터 - 매핑 - 객체 필드

영속성 API(Persistant API)라고도 부른다.

Sequelize

시퀄 라이즈는 Database 작업을 쉽게 할 수 있도록 도와주는 ORM 라이브러리이다.

sequelize 및 sequelize-cli 설치

Sequelize 공식사이트 에서 sequelize를 설치한다.

npm install --save sequelize

Sequelize Migrations을 통해 sequelize-cli를 설치할 수 있다.

CLI 설치
npm install --save-dev sequelize-cli

빈 프로젝트 만들기
npx sequelize-cli init

  • config, models, migrations, seeders 폴더가 생성된다.

config/config.json에 각 환경의 데이터베이스 정보가 나열되있다.
사용할 데이터베이스 명과 mysql 비밀번호를 입력해준다.
.gitignore에 config.json 파일이 입력되어 있는지 확인

im-sprint-shortly-mvc

short.ly라는 애플리케이션은 bit.ly 와 같이 긴 URL을 짧게 단축시켜주는 앱이다.

여기에는 urls 라는 테이블을 만들어, 원본 URL과 단축 URL의 방문 횟수를 기록한다.
ORM을 이용해 아래와 같은 테이블을 만든다.

FieldTypeNullKeyDefaultExtra
idintNOPRINULLauto_increment
urlvarchar(255)YESNULL
titlevarchar(255)YESNULL
visitsintYESNULL
createdAtdatetimeNONULL
updatedAtdatetimeNONULL

mysql 접속 데이터베이스 생성

mysql -u root -p

mySQL 접속


mysql> create database database_development;

위에서 지정한 config.json의 개발환경 데이터베이스명으로 데이터베이스를 생성한다.


mysql> use database_development;

데이터베이스 사용


Model 생성

npx sequelize-cli model:generate --name url --attributes url:string,title:string,visits:integer

모델(데이터베이스의 테이블로, 객체형태이다)을 생성해준다.
url, title, visits 필드를 생성한다.


npx sequelize-cli db:create

config.json에 지정해준 데이터베이스 정보를 토대로 데이터베이스를 생성한다.


model/url.js

  url.init({
    url: DataTypes.STRING,
    title: DataTypes.STRING,
    visits: {
      type: DataTypes.INTEGER,
      defaultValue: 0
    }

visits 필드의 기본값을 0으로 설정한다.


Migration

npx sequelize-cli db:migrate

데이터베이스에 sequelize 데이터를 반영한다.

undo

npx sequelize-cli db:migrate:undo

model의 기본값을 잘못 입력했을 경우나 반영을 되돌릴때 사용한다.
migration 폴더안의 파일을 삭제하면 안된다.

npx sequelize-cli db:migrate    

변경 후 재반영 해준다.


migration/...-create-url.js

'use strict';
module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.createTable('urls', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      url: {
        type: Sequelize.STRING
      },
      title: {
        type: Sequelize.STRING
      },
      visits: {
        type: Sequelize.INTEGER,
        defaultValue: 0
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable('urls');
  }
};

Controllers 생성

테스트케이스에서 controllers가 어디에 위치해야하는지 알려주고 있다.
폴더와 파일을 생성해준다.

/controllers/links/index.js

module.exports = {
  get: (req, res) => {
    res.sendStatus(200)
  },
  post: (req, res) => {
    res.sendStatus(201)
  },
  redirect: () => {}
}

기본적인 문만 작성했다.


Router 연결

/routes/links.js

const express = require('express');
const router = express.Router();
const linkController = require('../controllers/links')

/* GET links listing. */
router.get('/', linkController.get);
router.get('/:id', linkController.redirect);
router.post('/', linkController.post);

module.exports = router;

GET 또는 POST 요청을 보낼 경우, links 컨트롤러의 메소드가 실행되도록 만들었다.


Controllers 구현

구현 정보

다음 세 endpoint에 대한 각기 다른 구현이 필요합니다. 다음 API를 참고하여 구현하세요.

POST /links

  • content-type: application/json
  • payload: 단축시키고 싶은 URL을 url 속성에 담습니다.
{
  "url": "https://www.github.com"
}
  • status code: 201 (성공적으로 생성했을 시)
  • response: 방금 생성한 모델의 JSON
{
  "id": 1,
  "url": "https://www.github.com",
  "title": "The world’s leading software development platform · GitHub",
  "visits": 1,
  "createdAt": "2020-07-25T20:07:15.000Z",
  "updatedAt": "2020-07-25T20:07:15.000Z"
}
  • POST 요청을 구현할 때, 웹사이트의 제목을 가져오기 위해 modules/utils.js를 이용할 수 있습니다.

GET /links

  • content-type: application/json
  • status code: 200 (성공적으로 조회했을 시)
  • response: URL 모델의 목록 (array of objects)

GET /links/:id

  • status code: 302 (성공적으로 리디렉션했을 시)
  • 해당 id 값 바탕으로 url 모델을 찾아 리디렉션합니다.
    원본 URL이 https://www.github.com 인 모델 id가 1일 경우
    http://localhost:3000/links/1 로 접속하면 원본 URL로 리디렉션
  • /links/:id URL로 접근할 경우 visits 필드에 카운트가 1씩 증가해야 합니다.

/controllers/links/index.js

const model = require('../../models')
const { getUrlTitle, isValidUrl } = require('../../modules/utils')

모델에서 데이터를 가져온다.
modules의 utils에서 필요한 함수를 가져온다.

module.exports = {
    get: async (req, res) => {
        const result = await model.url.findAll();
      	if(!result){
            return res.sendStatus(204)
        }
        res.status(200).json(result)
    },
    post: (req, res) => {
        const originalUrl = req.body.url;
        if(!isValidUrl(originalUrl)){
          res.sendStatus(400);
        }
        getUrlTitle(originalUrl, async (err, result)=>{
          if(err){
            res.sendStatus(500);
          }
          const [url, created] = await model.url.findOrCreate({
            where: {url: originalUrl},
            defaults:{title: result}
          });
          if(created) {
            res.status(201).json(url);
          }
          res.status(201).json(url);
        });
      },
    redirect: async (req, res) => {
        const urlId = req.params.id;
        const result = 
        await model.url.findByPk(urlId);
        await result.update({
            visits: result.visits + 1
        })
        const redirectUrl = result.url;
        res.redirect(redirectUrl);
    }
}

Sequelize Model Querying-Finders 를 참고하여 sequlize 메서드를 사용했다.

테스트 케이스를 통과하였다.

  🚀 (1-1) ORM 설정
    ✓ cli를 통해 필요한 파일이 자동으로 만들어졌는지 확인합니다
    ✓ model/index.js 파일이 유효한지 확인합니다
    ✓ mysql에 접속할 수 있는지 확인합니다

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

  🚀 (1-2) 모델 생성
    ✓ url 모델이 존재해야 합니다
    ✓ url 모델은 요구하는 필드를 갖고 있어야 합니다
    ✓ url 모델의 각 필드는 정해진 타입으로 생성되어야 합니다
    ✓ url 모델의 visits 필드는 기본값이 0이어야 합니다

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

  🚀 (1-3) 마이그레이션
    ✓ 마이그레이션을 했다면, urls 테이블이 존재해야 합니다

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

  🚀 (2-1) controller 작성
    ✓ links controller 파일이 존재해야 합니다
    ✓ links controller에는 get, post 메소드가 각각 존재해야 합니다 (123ms)

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

  🚀 (2-2) router 연결
    ✓ POST /links는 links controller의 post 메소드를 실행합니다 (388ms)
    ✓ GET /links는 links controller의 get 메소드를 실행합니다

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

  🚀 (2-3) controller 구현
    ✓ POST /links은 url을 받아 단축 url로 만듭니다 (275ms)
    ✓ GET /links는 urls 테이블의 목록을 JSON의 형태로 반환합니다
    ✓ GET /links/:id 을 요청하면 url 필드값으로 리디렉션합니다
    ✓ GET /links/:id 을 요청하면, 해당 레코드의 visit count가 1 증가해야 합니다

메타인지

🎯 오늘의 학습목표

  • ORM을 이해한다.
  • Sequelize를 이용해 모델을 작성하고 마이그레이션을 할 수 있다.

😎 학습할 내용 중에 알고 있는 것

SQL, Node.js, MVC 디자인 패턴

✏️ 오늘 새롭게 학습한 것

  • Sequelize를 이용해 데이터베이스를 다루는 법

🧷 오늘 학습한 내용 중 아직 이해되지 않은 부분

  • express의 redirect
  • Sequelize Model Query 문

💡 이해되지 않은 내용을 보완하기 위해 무엇을 할까

Express res.redirect() 도큐먼트Sequelize Model Querying 도큐먼트를 살펴본다.

0개의 댓글