(Object Relational Mapping)
객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해주는 것을 말한다.
객체를 통해 간접적으로 데이터베이스 데이터를 다룰수 있게 해준다.
영속성 API(Persistant API)라고도 부른다.
시퀄 라이즈는 Database 작업을 쉽게 할 수 있도록 도와주는 ORM 라이브러리이다.
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 파일이 입력되어 있는지 확인
short.ly라는 애플리케이션은 bit.ly 와 같이 긴 URL을 짧게 단축시켜주는 앱이다.
여기에는 urls 라는 테이블을 만들어, 원본 URL과 단축 URL의 방문 횟수를 기록한다.
ORM을 이용해 아래와 같은 테이블을 만든다.
Field Type Null Key Default Extra id int NO PRI NULL auto_increment url varchar(255) YES NULL title varchar(255) YES NULL visits int YES NULL createdAt datetime NO NULL updatedAt datetime NO NULL
mysql -u root -p
mySQL 접속
mysql> create database database_development;
위에서 지정한 config.json의 개발환경 데이터베이스명으로 데이터베이스를 생성한다.
mysql> use database_development;
데이터베이스 사용
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으로 설정한다.
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/links/index.js
module.exports = {
get: (req, res) => {
res.sendStatus(200)
},
post: (req, res) => {
res.sendStatus(201)
},
redirect: () => {}
}
기본적인 문만 작성했다.
/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 컨트롤러의 메소드가 실행되도록 만들었다.
다음 세 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 증가해야 합니다
SQL, Node.js, MVC 디자인 패턴
Express res.redirect() 도큐먼트와 Sequelize Model Querying 도큐먼트를 살펴본다.