[Week8] Node.js 기반의 REST API 구현(12)

Younha Lee·2026년 3월 3일

TIL

목록 보기
37/60

비동기를 활용한 주문 API 구현하기

지난 시간에는 비동기 처리에 대해 알아봤어요. 이번 시간에는 비동기 개념을 본격적으로 활용해 주문 API 를 구현해 볼게요

SQL 데이터 삭제 명령어 (DELETE, DROP, TRUNCATE)

본격적인 구현에 앞서 데이터를 지우는 3가지 SQL 명령어에 대해 먼저 정리해 볼게요.

  • DELETE: WHERE 조건을 사용해 조건에 맞는 데이터만 지울 때 써요. (조건을 안 적으면 데이터가 전부 삭제해요.)
  • DROP: 테이블 자체를 완전히 삭제해 버리는 명령어예요.
  • TRUNCATE: DELETE 에서 조건 없이 데이터를 전부 지우는 것과 같은 효과지만, auto_increment 옵션 값까지 깔끔하게 초기화시켜줘요.

DELETETRUNCATE 의 가장 큰 차이점은 Rollback 가능 여부인덱스 초기화 여부 예요.
그리고 데이터 전체가 아닌 일부 데이터만 골라서 지울 때는 무조건 DELETE 만 써야해요.

orders 의 데이터를 TRUNCATE sql 을 사용해 데이터를 삭제하려는 상황에서 FK 제약조건 이슈가 있었어요.
저라면 보통 참조키를 nullable로 바꿔서 해결하는데, 이번에는 다른 방법을 써봤어요.

TRUNCATE orders
Error Code: 1701.
Cannot truncate a table referenced in a foreign key constraint
(`BookShop`.`orderedBook`, CONSTRAINT `FK_orderedBook_orders_id`
FOREIGN KEY (`order_id`) REFERENCES `BookShop`.`orders` (`id`))

외래키 설정을 OFF 하고 삭제 한 다음 다시 ON 해서 해결했어요.

// 외래키 설정 OFF
SET FOREIGN_KEY_CHECKS = 0;

// 원하는 테이블 데이터 삭제

// 외래키 설정 ON
SET FOREIGN_KEY_CHECKS = 1;

간단한 테이블의 초기화이기에 가능했다는 느낌이었어요.
관련된 테이블이 많은 경우 추가적인 문제가 있을 수 있기에 설정을 건드리는 부분은 조심해야 할 필요가 있어보여요.

주문하기 API 구현

주문하기 요청은 지금까지 만들었던 기능들과 다르게 여러 SQL을 순서대로 처리해야 해요.
그래서 이번에는 Promiseasync / await 를 사용해서 비동기적으로 안전하게 구현해 봤어요.

1. 테이블 Insert 순서
테이블에 데이터를 넣을 때는 외래키 의존성에 맞춰 deliveryordersorderedBook 순서로 들어가야 해요.
(orders 에는 배송지 id가 필요하고, orderedBook 에는 주문 id가 하니까)

-- 1. 배송지 정보 추가
INSERT INTO delivery (address, receiver, ph_num) VALUES (?, ?, ?);

-- 2. 주문 정보 추가
INSERT INTO orders (delivery_id, book_title, total_price, total_quantity, user_id) VALUES (?, ?, ?, ?, ?);

-- 3. 주문 상세 목록(책들) 추가
INSERT INTO orderedBook (order_id, book_id, quantity) VALUES ?;

2. 주문에 성공한 장바구니 목록 삭제하기
주문이 끝났다면 장바구니에 들어있던 아이템들은 IN (?) 을 사용해서 한 번에 삭제했어요.

DELETE FROM baskets WHERE id IN (?);

비동기 에러 처리 로직

async / await 를 활용해 비동기로 구현했기 때문에, 중간에 쿼리가 실패했을 때 서버가 멈추지 않도록 예외 처리 로직도 조금 다르게 작성했어요.

const order = async (req, res) => { 
  // 에러 발생 시 공통으로 처리해 줄 함수를 만들었어요.
  const catchError = (error) => {
    res.status(StatusCodes.BAD_REQUEST).end();
    throw error;
  };
  
  // ... 생략 ...

  // await 뒤에 .catch()를 달아서 에러가 발생하면 catchError 함수가 실행되게 해요.
  // 이렇게 에러를 던져주면 서버가 강제 종료되지 않고 안전하게 400 에러를 응답해줘요.
  await addOrder(conn, values).catch(catchError);
  
  // ... 생략 ...
}

주문 목록 & 상세 조회 API

주문 내역을 확인하는 API는 JOIN 을 활용해서 프론트엔드에 필요한 데이터만 뽑아왔어요.

-- 주문 목록 조회 (orders + delivery)
SELECT orders.id, created_at, address, receiver, ph_num, book_title, total_quantity, total_price
FROM orders LEFT JOIN delivery
ON orders.delivery_id = delivery.id
WHERE user_id = ?;

-- 주문 상세 조회 (orderedBook + books)
SELECT book_id, title, img, price, author, quantity
FROM orderedBook LEFT JOIN books
ON book_id = books.id
WHERE order_id = ?;
profile
할 땐 하고 놀 땐 노는 일일놀놀입니다.

0개의 댓글