TIL 51- ORM

Churro.·2021년 12월 23일
0

ORM을 왜 사용하는 걸까?

LEFT : JavaScript로 만든 수도코드(OOP) | RIGHT : 관계형 데이터베이스

LEFT : person.phone이 배열형태로 나타남! 어라랏 원래 OOP에서는 객체로 나타내는데!

✅ 객체지향에서 데이터를 다루는 방법(객체)과 관계형 데이터베이스(relational database) 에서 데이터를 다루는 방법(배열)이 달라요!

즉, 관계형 데이터베이스에 익숙하지 않거나 JS코드가 익숙하다면, ORM을 이용해 관계형으로 사고하지 않고도 JS코드상으로(SQL문 없이도) 데이터베이스에 접근할 수 있다.

추후 프로젝트에 ORM 사용함 - Sequelize (a promise-based Node.js ORM)

Sequelize는 RDBMS를 다 다룰 수 있다 (호환된다)

RDBMS : mysql, mariaDB, PostgreSQL, SQLite 등

예를 들어 mysql에서는 int, varchar를 사용하는데 mariaDB에선 어떤형식으로 표현하는지 모른다.

Sequelize는 integer, string 으로 용어를 정했으며, 이 용어는 RDBMS와 호환되어 다 말이 통한다고 보면 된다.


./ 와 ../ 👉 파일 위치 나타내기
💡  ./ 지금 위치의 파일 (같은 깊이에 있는, 같은 파일 안에 들어있는)
💡  ../ 이전 위치의 파일 (이전 깊이에 있는, 한 단계 밖+)





shortly-mvc sprint

  • 생성할 db의 이름은 database_development
  • migration 문서 참조 : Sequelize

✅ npm test가 뭔소린지 모를때는 test파일 보면서 하나씩 해결하기


url → urls 가 된다고?

                             2️⃣db:migrate 명령어 사용해 이동

📌  1️⃣Sequelize로 'url'을 만듦 —————————————————>>>3️⃣mysql에는 빈 db 였는데 채워짐

(url은 내 PC에 VsCode상으로 보이는 파일로 만들어져 있기만 함)

1️⃣ url은 Model 이다. 생성과정은 터미널에 npx sequelize-cli model:generate --name url --attributes firstName:string,lastName:string,email:string

그러면 vscode상에 파일이 새로 생성된다

2️⃣ migrate 하면 vscode상에 migration 파일 생성됨

3️⃣ Model이름은 url로 만들면, mysql db에는 urls 라는 이름으로 바뀌어 table이 생성된다 ❗️

(table은 아직 empty set / desc urls; 치면 스키마 나옴)

파일 구조와 설명

models/url.js

Models 를 정의해주는 설정 파일

models/index.js

url 코드가 실제로 실행되는 파일

여기서 db라는 객체가 생성되고, 그 안에 url이라는 modelName을 property 로 가져온다.

그래서 controllers → links → index.js 상단에서 models/index.js 를 require 해야 하는 것이다.

modules/utils.js

rValidUrl 통해 client가 body에 싣어보낸 url이 진짜 url형태를 띄고 있는지 검사함

valid한 url이다, request 로 const request = require('request');

해당 서버에 request 보내고 (getUrlTitle함수 안에 request 사용됨)

controller 구조

📌  controllers폴더 ——→ links폴더 —> index.js파일

📌 controller와 model이 하는 역할은 어제 스프린트와 동일, but 오늘 model은 이미 짜여져있고, 어제는 우리가 직접 짰음. (어제 model부분은 SQL문법 사용해서 select , insert into... 했던. db와 제일 가까웠던)



코드 해석

controllers/links/index.js

✅ utils는 post할때 사용해야 하고

✅ url은 get, post, redirect 다 사용해야 하기 때문에 불러온다.

☑️ models의 url.js는 index.js에 불러가있다. 그래서 index.js만 불러도 url.js 내용도 같이 불러와진다.

const utils = require('../../modules/utils')
const { url } = require('../../models')  
(const Url = require('../../models').url 로 써줄 수도 있다.)

☑️ ../../models 는 ../../models/index.js와 동일! commonJS: 폴더이름만 불러와도 그 안의 첫번째 파일을 자동으로 불러온다.

const { getUrlTitle, isValidUrl } = require('../../modules/utils');
const { url: URLModel } = require('../../models');  💡URLModel은 변수!

❓ {url:URLModel} 이렇게 구조분해할당 하는것 보니까 models = {index: , url : } 파일구조가 되어있나?

⚠️ NO

→ 이것보다는, models/index.js의 db[modelName]부분과 연관있다고 보는게 맞을듯.

db = { modelName : url } 이렇게.

왜 ❓ 👉 우리가 맨 첨 sequelize로 db에 Model을 생성했는데 url이라는 이름으로 생성함



📌 { url } 은 뭐고 { url : URLModel } 은 뭘까

 models → index.js 를 보면

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
...
module.exports = db;     // db를 export 하고 있다.

✅ db[modelName] ➡️  db 객체의 key는 modelName 이다. modelName= url

그래서 controllers/links/index.js파일 상단 require로 models/index.js파일에서 { url } 만 불러온 것

근데 URLModel이라는 이름으로 사용하고 싶다면 { url : URLModel } 이라고 표현해야 함



GET 부분

module.exports = {
    get: (req, res) => {
      // SELECT * FROM urls 를 sequelize문법으로 나타내면 :
      url.findAll().then(data => res.status(200).json(data))
      💡 url은 첨에 우리가 만든 url table 의 정보 (db정보)
      💡sequelize의 findAll메서드: 반환값이 promise  (그래서 .then 사용)
module.exports = {
  get: async (req, res) => {
    const result = await URLModel.findAll();
    res.status(200).json(result);
  },

sequelize의 findAll()사용하여 전체record 조회한 다음에 json으로 파싱하여 client에게 응답으로 보내준다.

POST 부분

post: (req, res) => {
        utils.getUrlTitle(req.body.url, (err, title) => {   
            url
            .create({ 
	              url: req.body.url,
                title: title,
            })
            .then(data => res.status(201).json(data))
        })
        },

💡sequelize의 create메서드: 반환값이 promise  (그래서 .then 사용)

create 말고, findOrCreate 메서드를 쓰면 urls table 의 결과는 달라짐 (둘다 test 통과에는 상관X)

post부분의 req.body.url

👉  위치 : controllers → links → index.js

 /:id             -> 이게 있으니까 어제는 req.params.id를 다뤄준거고

**post /links -> 오늘 post 부분엔 : 없어서 req.params 다루지 않는다.

post니까 body 필요 (get은 body X) 그래서 req.body 를 사용한다.

근데 req.body.url 은 뭐냐 -> url은 req.body의 key이다. url key의 value값을 우린 사용하고 싶은 것.



REDIRECT 부분

redirect: (req, res) => {
        url.findOne({ where: { id: req.params.id } }).then(data => {
          url.update({ visits: data.visits + 1 }, { where: { id: req.params.id } })
          res.redirect(data.url)   //여기 redirect는 express의 http메서드 -> res.send res.json 과 같은 애들이 express의 http메서드임
          res.status(302).send()
        })
      },

💡sequelize의 findOne메서드: 반환값이 promise  (그래서 .then 사용)

req.params.id 로 url table의 id

해당 id값으로 데이터베이스 조회

조회한 데이터의 url필드값으로 redirect

profile
I, sum of records.

0개의 댓글