[Database] im-sprint-cmarket-database (db, models)

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

TIL (Today I Learned)

목록 보기
40/53
post-thumbnail

이전 과정에 이어서 model을 작성해본다.

server/db/index.js 파일에서는 데이터베이스와 서버 인스턴스를 연결하기 위해 mysql 모듈을 사용한다.
server/models/index.js 파일에는 controller 에서 사용할 orders, items 모델을 정의해야 한다.
기본적인 구조만 제공되며 server/db/index.js 의 함수를 불러온 뒤, SQL 쿼리문으로 DB의 정보를 처리한다. 데이터베이스 쿼리는 비동기 요청인 점을 반드시 고려해야 한다.


mysql 연결

/db/index.js

const mysql = require('mysql'); // mysql 라이브러리를 불러옴
const dotenv = require('dotenv');
const config = require('../config/config'); 
dotenv.config();

const con = mysql.createConnection( //mysql객체를 config정보로 환경을 구분하여 con 객체를 만듬
  config[process.env.NODE_ENV || 'development']
);

//mysql을 nodejs에 연결해 js로 mysql을 조회할 수 있게 해줘야 한다.
con.connect((err) => { //서버와 데이터베이스를 연결하는 과정
  if (err) throw err;
});

module.exports = con;

데이터베이스와 models를 연결하는 역할을 하는 파일이다.


Model

/models/index.js

const db = require('../db');
//데이터베이스에 메서드를 보낼 수 있다.
module.exports = {
  items: {
    get: (callback) => {
      // 모든 상품을 가져오는 함수
      const queryString = `SELECT * FROM items`;

      db.query(queryString, (error, result) => {
        callback(error, result);
      });
    },
  },
  orders: {
    get: (userId, callback) => {
      // 해당 유저가 작성한 모든 주문을 가져오는 함수
      const queryString = `
      SELECT orders.id, orders.created_at, orders.total_price, items.name, items.price, items.image, order_items.order_quantity 
      FROM items
      INNER JOIN order_items ON (order_items.item_id = items.id)
      INNER JOIN orders ON (orders.id = order_items.order_id)
      WHERE (orders.user_id = ?)
      `; 

?에 파라미터값이 들어간다.
id는 다른 테이블에도 존재하므로 id가 덧씌워질수 있으므로 필드를 일일이 지정해 select 했다

     const params = [userId];
     db.query(queryString, params, (error, result) => {
       callback(error, result);
     });
   },
   post: (userId, orders, totalPrice, callback) => {
     // 해당 유저의 주문 요청을 데이터베이스에 생성하는 함수
     // order_items에 order_id를 FK로 가지고 있으므로 테이블을 순차적으로 채워야 한다 
     //(orders 테이블을 채우고 생성된 record의 id를 orders_items의 FK로 넣어 record 생성)
     const queryString = `
     INSERT INTO orders (user_id, total_price) VALUES (?, ?)
     `;
     const params = [userId, totalPrice];

     db.query(queryString, params, (error, result) => {
       if(error){
         callback(error, null); // 첫번째 쿼리가 성공하고 두번째 쿼리가 실패할 경우 첫번째 쿼리를 롤백해줘야 되지만 생략
       } else {
         const queryString = `
           INSERT INTO order_items (order_id, item_id, order_quantity) VALUES ?
         `;

생성해야하는 레코드의 갯수가 매 요청마다 달라진다.
묶어서 요청을 보내 여러개의 record를 한번의 쿼리로 생성해야 서버에 부하를 덜 수 있다. (bulk insert)
[{}, {}, {}] 를 [[], [], []] 로
params = [[[값],[값]...],[[값],[값]...]...]
param = [[값],[값]...]
param = [[order_id, item_id, order_quantity], [order_id, item_id, order_quantity]...]

          const params = orders.map(order => [
            result.insertId,
            order.itemId,
            order.quantity,
          ]);
          
          db.query(queryString, [params], callback);
        }
      })
    }
  },
};

테스트가 통과 되었다.🫠

🗄  Cmarket Database
    🗺 -------- Cmarket Router
dd
      🚀 Server is starting on 4000
      ✓ users router 파일이 존재해야 합니다
      ✓ orders controller에는 get, post 메소드가 각각 존재해야 합니다
      GET /users/1/orders 200 2 - 2.076 ms
      ✓ GET /users는 orders controller의 get 메소드를 실행합니다
      POST /users/1/orders 201 7 - 6.014 ms
      ✓ POST /users는 orders controller의 post 메소드를 실행합니다
    🕹 -------- Cmarket Controller
      GET /items 200 617 - 0.827 ms
      ✓ GET /items 요청에 성공했을 경우 상태코드 200을 보내야합니다.
      GET /users/1/orders 200 2 - 0.714 ms
      ✓ GET /users/:userId/orders 요청에 성공했을 경우 상태코드 200을 보내야합니다.
      POST /users/1/orders 400 - - 0.230 ms
      ✓ POST /users/:userId/orders 요청에서 클라이언트가 잘못된 요청을 했을 경우 상태코드 400을 보내야합니다.
      POST /users/1/orders 201 7 - 1.304 ms
      ✓ POST /users/:userId/orders 요청에 성공했을 경우 상태코드 201을 보내야합니다.
    ✨-------- Cmarket Model
      GET /items 200 617 - 0.719 ms
      ✓ 데이터베이스에 저장된 상품 목록을 가져와야합니다.
      POST /users/1/orders 201 7 - 1.232 ms
      ✓ 주문내역을 데이터베이스에 저장해야합니다.
      POST /users/1/orders 201 7 - 1.932 ms
      POST /users/1/orders 201 7 - 1.005 ms
      GET /users/1/orders 200 622 - 0.537 ms
      ✓ 데이터베이스에 저장된 주문내역을 가져와야합니다.


11 passing (482ms)

메타인지

🎯 오늘의 학습목표

스프린트를 통해 데이터베이스를 구축하고 인메모리 형태가 아닌 영속적 데이터를 가질 수 있도록 데이터베이스를 이용할 수 있다.

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

SQL, Node.js, HTTP 요청

✏️ 오늘 새롭게 학습한 것

  • 데이터베이스와 서버인스턴스를 mysql 모듈을 이용해 연결하는 법
  • controller에서 사용할 models 작성법
  • SQL 쿼리문으로 DB의 정보를 처리하는 법 (데이터베이스 쿼리는 비동기 요청이다)

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

  • express의 app.use와 app.get의 차이점
  • result.insertId

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

express 도큐먼트Node.js의 Insert Into 도큐먼트를 살펴본다.

0개의 댓글