온라인 쇼핑몰 예제 - sql 쿼리문 이해하기

Creating the dots·2021년 8월 31일
0

SQL

목록 보기
5/21

models > index.js

const db = require("../db");

module.exports = {
  orders: {
    get: (userId, callback) => {
      const sql = `SELECT o.id, o.created_at, o.total_price, i.name, i.price, i.image, oi.order_quantity FROM items as i
      INNER JOIN order_items as oi ON (oi.item_id = i.id)
      INNER JOIN orders as o ON (o.id = oi.order_id)
      WHERE (o.user_id = ?)`;
      const params = [userId];
      db.query(sql, params, (err, result) => {
        if (err) {
          return callback(err);
        } else {
          callback(null, result);
        }
      });
    },
    post: (userId, orders, totalPrice, callback) => {
      const sql = `insert into orders (user_id,total_price) values(?,?)`;
      const params = [userId,totalPrice];
      db.query(sql, params, (err, result) => {
        if (err) {
          callback(err);
        } else {
          const sql2 = `insert into order_items(order_id,item_id,order_quantity)values ?`;
          
          //method1 
          const params = [
            orders.map((order) => [result.insertId, order.itemId, order.quantity])
          ];
          db.query(sql2, params, (err, result)=>{
            if(err){callback(err)}
            else{callback(null,result)};
          });
          
          //method2
          const params = orders.map((el) => {
            return [result.insertId, el.itemId, el.quantity];
          });
          db.query(sql2, [params], (err, result) => {
            if (err) {
              callback(err);
            } else {
              callback(null, result);
            }
          });
        }
      });
    },
  },

  items: {
    get: (callback) => {
      const sql = `select * from items`;
      db.query(sql, (err, result) => {
        if (err) {
          callback(err);
        } else {
          callback(null, result);
        }
      });
    },
  },
};

models 객체 이해하기

models는 객체 형태이고, 2개의 키(orders, items)를 갖는다. orders는 객체를 키값으로 갖는데, get이라는 메소드와 post라는 메소드를 갖는다. items도 객체를 키값으로 갖는데, get 메소드를 갖는다.

이렇게 export된 models는 controller 폴더의 index.js 파일에서 require 되어 사용된다.

db 가져오기

const db = require("../db"); //생성한 데이터베이스를 가져와서 

db.query(sql, (err, result) => { //데이터베이스에 쿼리문으로 데이터를 get/post 한다
        if (err) {
          callback(err);
        } else {
          callback(null, result);
        }
});

get 요청 이해하기

  • 전체 아이템 데이터를 가져오는 models.items.get은 콜백함수만 인자로 받는다.
  • 주문(구매) 내역 데이터를 가져오는 models.orders.get은 params = [userId]와 (비동기로 처리하기 위한) 콜백함수를 인자로 받는다.
  • 데이터베이스에 query 함수를 사용해 첫번째 인자로 문자열 형태의 요청문을 넣고, 두번째 인자로 params를, 세 번째 인자로 콜백함수를 넣어준다.
    • models.orders.get의 쿼리문은 테스트 케이스를 통과시키기 위해 7개의 컬럼을 선택하고 그 데이터를 가져오기 위해 총 3번의 JOIN과 WHERE문으로 컨디션을 만들어주었다.
    • 요청이 실패하면 콜백함수에 에러를 인자로 넣어준다.
    • 요청이 성공하면 성공결과 생성된 result를 콜백함수에 인자로 넣어준다.

post 요청 이해하기

유저가 1개 이상의 상품에 대해 장바구니에 담기 버튼을 클릭했고, 장바구니 페이지로 이동했다고 생각해보자.

그때 유저가 보게 될 화면은 아래와 같다.

현재 총 3개의 상품이 담겨있고, 오른쪽에는 주문합계가 표시된다.

이때, 3개 상품 구매하기를 클릭하고 주문내역 페이지로 이동하면, 다음과 같은 화면을 보게 된다.

나(user)가 총 29번의 구매를 진행했는데, 29번째(order.order_id) 구매 목록에는 개구리안대, 뜯어온 보도블럭, 2020년 달력이 있고, 총 19800원(order.total_price)이다.

조금 더 생각해보면, 유저가 구매를 했을때 앞서 생성했던 테이블들을 떠올려보면,
orders 테이블에 29번째 주문 데이터가 추가되어야하고, order_items테이블에 해당 주문목록에 3개의 아이템들의 데이터들이 추가되어야 한다.

따라서 먼저 orders 테이블에 데이터를 추가하는 쿼리를 실행하고, 이것이 성공했을때 order_items 테이블에 아이템(들)을 한번에 추가해주어야 한다.

여러개의 레코드를 한 번의 쿼리로 테이블에 저장하려면 (bulk insert) [[[data,data,data],[data,data,data],[data,data,data]]]의 삼중배열 형태로 쿼리함수의 두 번째 인자에 전달해줘야한다.

기존 orders는 (spec 폴더 > server-spec.js 파일) [{},{},{}]와 같이 객체를 요소로 갖는 배열이다. 그런데 bulk insert하기 위해 orders를 이중배열인 [[],[],[]]로 만들어줘야하므로 map 메소드를 사용할 수 있다. (이후 인자에서 한 번 더 대괄호를 씌워 삼중배열로 만들어줄 것임)

따라서 order 테이블에 데이터를 성공적으로 추가했다면, 다음과 같은 두 번째 쿼리를 실행해야한다.

const sql2 = `INSERT INTO order_items (order_id,item_id,order_quantity) VALUES ?`;
const params = orders.map((order) => {
  return [result.insertId, order.itemId, order.quantity]
})
db.query(sql2, [params], (err,result)=>{
  if(err){callback(err);}
  else{callback(null,result)}
});
profile
어제보다 나은 오늘을 만드는 중

0개의 댓글