[Week7] Node.js 기반의 REST API 구현(10)

Younha Lee·2026년 2월 26일

TIL

목록 보기
35/60

주문 API 추가하기

지난 시간 장바구니 API를 추가했어요. 이번 시간에는 주문 API의 결제하기(주문하기)를 어떻게 처리해야 할지 고민해 보고 코드로 직접 구현해 볼게요.

SQL LAST_INSERT_ID(), MAX(), MIN()

먼저 LAST_INSERT_ID() 는 이름 그대로 마지막으로 insert한 id를 불러오는 함수에요.

SELECT LAST_INSERT_ID();

하지만 이 함수를 사용할 때는 몇 가지 주의할 점(단점)이 존재해요.
1. 여러 번 insert한 결과와 bulk insert한 결과가 다르게 나와요.
2. 서버 연결 후 별도의 insert가 없었다면 0이 나와요.
3. 가장 마지막에 insert한 테이블의 auto_increment 된 값을 불러와요.

MAX()MIN() 은 자주 볼 수 있는 직관적인 함수로, 각각 가장 큰 값과 가장 작은 값을 반환해요.

SELECT MAX(칼럼명) FROM table;
SELECT MIN(칼럼명) FROM table;

주문하기 구현 순서 및 코드

주문하기 요청은 지금까지 만들었던 API들과 다르게 여러 테이블에 걸쳐 복합적으로 요청을 처리해야 해요.

  1. 테이블에 insert하는 순서: deliveryordersorderedBook
    왜냐하면 orders 에는 delivery 의 id가 필요하고, orderedBook 에는 orders의 id가 필요하기 때문이에요. 의존성에 맞게 순서대로 들어가야 해요.
  2. 이후 주문에 성공한 장바구니 목록은 삭제해 주어야 해요.

오늘 작업한 OrdersController.js 의 코드를 살펴볼게요.

import conn from '../db.js';
import statusCode from 'http-status-codes';

// 주문 하기
export const order = (req, res) => {
    const { items, delivery, totalQuantity, totalPrice, userId, firstBookTitle } = req.body;

    let delivery_id = 3;
    let order_id = 2;

    // 1. 배송 정보 INSERT
    let sql = `INSERT INTO delivery (address, receiver, contact) VALUES (?, ?, ?)`;
    let values = [delivery.address, delivery.receiver, delivery.contact];
    conn.query(sql, values, (err, results) => {
        if (err) return res.status(statusCode.INTERNAL_SERVER_ERROR).json({message: err.message});
        delivery_id = results.insertId;
    });

    // 2. 주문 정보 INSERT (위에서 받아온 delivery_id 사용)
    sql = `INSERT INTO orders (book_title, total_quantity, total_price, user_id, delivery_id)
            VALUES (?, ?, ?, ?, ?);`;
    values = [firstBookTitle, totalQuantity, totalPrice, userId, delivery_id];
    conn.query(sql, values, (err, results) => {
        if (err) return res.status(statusCode.INTERNAL_SERVER_ERROR).json({message: err.message});
        order_id = results.insertId;
    });

    // 3. 주문 상세 목록(orderedBook) 다중 INSERT
    sql = `INSERT INTO orderedBook (order_id, book_id, quantity) VALUES ?`;
    values = [];
    items.forEach((item) =>
        values.push([order_id, item.book_id, item.quantity])
    );
    conn.query(sql,[values], (err, results) => {
        if (err) return res.status(statusCode.INTERNAL_SERVER_ERROR).json({message: err.message});
        return res.status(statusCode.CREATED).json(results);
    });
};

위 코드를 보면 세 번째 orderedBook 에 값을 넣을 때, 기존 단일 값만 들어갔던 values 에 배열을 통째로 넣어서 사용하는 것을 볼 수 있어요.
이때 주의할 점은 쿼리에 넘겨줄 때 values[]로 한 번 더 감싸서 [values] 형태로 넣어줘야 동작한다는 것이에요

객체를 활용한 INSERT

INSERT문을 작성할 때 칼럼이 많아질수록 배열의 순서를 매핑하는 과정이 점점 복잡해져요.
이때 INSERT INTO 테이블 SET ? 구문을 활용하면 객체를 이용해 값을 편하게 입력할 수 있어요.

// 기존 사용 방법
sql = `INSERT INTO orders (delivery_id, book_title, total_price, total_quantity, user_id) VALUES (?)`;
values =[deliveryId, firstBookTitle, totalPrice, totalQuantity, userId];

// 새로운 사용 방법
sql = `INSERT INTO orders SET ?`;
values = {
  delivery_id: deliveryId,
  book_title: firstBookTitle,
  total_price: totalPrice,
  total_quantity: totalQuantity,
  user_id: userId,
};

오늘 생성한 ERD에요

profile
할 땐 하고 놀 땐 노는 일일놀놀입니다.

0개의 댓글