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