프로젝트/도서구매사이트

1024 주문 API 구현 - insertId 활용, 다중 인서트 구현

thinktank911 2025. 10. 23. 17:32

<주문 API 구현>

주문 DB ERD 설계

  • 배송정보. 주문한 책, 주문내역 ERD 설계

주문 DB 생성

  • FK 제약조건 등 전체 제약조건을 규칙에 따라 걸기
코딩 컨벤션
- 가독성과 유지보수성을 높이기 위해 정해진 코딩 스타일 규약
- SQL 컨벤션 또한 가독성 좋은 SQL 코드를 작성하기 위한 규칙을 의미
- 주요 내용으로는 명명 규칙, 들여쓰기, 대소문자 통일, 주석 사용, 코드 구조화 등이 있으며,
  팀 또는 프로젝트의 규약을 따르는 것이 중요

 

주문하기 SQL문 작성하기

  • 주문하기 로직을 완성하기 위해서는 delivery → orders → orderedBook 테이블 순으로 인서트가 이루어져야 한다.
  • 여기에서 orders 테이블에 데이터를 넣으려면 참조키인 delivery_id를 delivery에서 가져와야 한다.
  • 마찬가지로 orderedBook 또한 orders 테이블의 갓 만들어진 id를 읽어와 order_id로 넣어줘야 한다.
  • 그렇다면 갓 만든 데이터의 PK값 가져오려면 어떻게 해야 할까?

방금 insert한 데이터 PK 가져오는 방법

  • LAST_INSERT_ID()
    • mysql 함수로 테이블의 마지막 auto_increment값을 반환
    • 시간차 공격 >> 이전 값을 들고오는 오류가 간간히 남
      : 다른 컴퓨터에서 동시에 insert하면 에러 남
  • MAX() : 가장 큰 값(최근에 추가된 값) 반환
SELECT max(id) FROM orders;
  • insertId 활용
    • 반환하는 results 내용 안에 포함된 insertId는 추가된 데이터의 키 id값이다.

배송정보(delivery) insert하기

  • req.body에서 delivery 객체를 가져와 values로 넣어준다.
  • delivery_id 변수에 results.id를 넣어준다.

req.body의 delivery 객체

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

    let delivery_id;
    // 배송 정보
    let sql = `INSERT INTO delivery (address, receiver, contact) VALUES (?, ?, ?)`;
    let values = [delivery.address, delivery.receiver, delivery.contact];
    // INSERT 쿼리문
    conn.query(sql, values,
        function (err, results) {
            if(err){
                console.log(err)
                return res.status(StatusCodes.BAD_REQUEST).end();   // Bad Request(400)
            }

            delivery_id = results.insertId; // 생성 PK id

            return res.status(StatusCodes.CREATED).json(results);  // 201
        }
    );

주문정보(orders) insert하기

  • 위에 선언한 변수 delivery_id를 values에 넣어 셋팅해준다.
  • 나머지는 req.body에서 받아온 값 셋팅
  • order_id 변수에 results.insertId를 넣어준다.
// 주문 정보
    sql = `INSERT INTO orders (rep_book_title, total_quantity, total_price, user_id, delivery_id)
                VALUES (?, ?, ?, ?, ?);`;
    values = [repBookTitle, totalQuantity, totalPrice, userId, delivery_id];
    conn.query(sql, values,
        function (err, results) {
            if(err){
                console.log(err)
                return res.status(StatusCodes.BAD_REQUEST).end();   // Bad Request(400)
            }

            order_id = results.insertId; // 생성 PK id

            return res.status(StatusCodes.CREATED).json(results);  // 201
        }
    );

 

주문한 책(orderedBook) insert하기

  • 인서트 여러 개 하는 방법
  • 이차원 배열로 다중 인서트 : bulk(묶음)로 인서트한다.
  • values를 이차원 배열로 push해서 만들어준 다음, 쿼리 보낼 때 [values]로 보내줘야 함
  • sql 구문에서 'VALUES ' 뒤 '?'를 하나로 셋팅한다.
// 주문한 책
    sql = `INSERT INTO orderedBook (order_id, book_id, quantity)
            VALUES ?`;
           
    // items.. 배열 : 요소들을 하나씩 꺼내서 (foreach문 돌려서)
    values = [];    // 초기화
    items.forEach((item) => {
        values.push([order_id, item.book_id, item.quantity]);
    });
   
    conn.query(sql, [values],
        function (err, results) {
            if(err){
                console.log(err)
                return res.status(StatusCodes.BAD_REQUEST).end();   // Bad Request(400)
            }

            return res.status(StatusCodes.CREATED).json(results);  // 201
        }
    );