1. SQL 에러
1.1. ERROR 1005: Can't create table `book-shop`.`new_table` (errno: 121 "Duplicate key on write or update")
새롭게 만든 cartItems 테이블에 FK 제약 조건을 설정해주려고 했는데 에러가 났다.
이 에러는 이미 존재하는 제약조건의 이름을 또 사용하려고 했을 때 발생하는 에러이기 때문에, 제약 조건의 이름을 바꿔주면 에러가 나지 않는다.
이런 에러를 방지하기 위해 제약조건의 이름도 규칙에 따라 지을 수 있다.
fk_기준 테이블명_참조테이블명_참조키
앞에 fk 제약 조건을 표시하기 위해 fk 를 붙이고, 기준 테이블명 참조테이블명을 차례로 써 준 뒤에 참조하는 키의 컬럼명을 써주면 된다.
예시를 들어보자면, 아래와 같이 지으면 된다.
cartItems 테이블의 user_id 가 users 테이블의 id 를 참조하는 경우: fk_cartItems_users_id
likes 테이블의 user_id 가 users 테이블의 id 를 참조하는 경우: fk_likes_users_id
1.2. ERROR 1061: Duplicate key name
fk 제약 조건의 이름을 바꿔주니 ERROR 1061: Duplicate key name 라는 새로운 에러가 발생했다.
이 에러는 같은 이름의 인덱스나 키를 두 번 정의하려고 할 때 발생하는 에러인데, 나의 경우 같은 이름의 인덱스가 존재해서 에러가 났다.
book_id_idx, user_id_idx 라는 인덱스가 이미 존재하는 이름이어서 에러가 난 것이기 때문에 인덱스 이름 앞에 테이블 이름을 붙여 에러가 나지 않도록 고쳐주었더니 에러가 나지 않았다.
book_id_idx -> cartItems_book_id_idx
user_id_idx -> cartItems_user_id_idx
2. 장바구니 API 구현
2.1. 장바구니 담기
// CartController.js
const addToCart = (req, res) => {
// 장바구니 담기
const {book_id, quantity, user_id} = req.body;
let sql = `INSERT INTO cartItems (book_id, quantity, user_id) VALUES (?, ?, ?)`;
let values = [book_id, quantity, user_id];
conn.query(sql, values,
(err, results) => {
if (err) {
console.log(err);
return res.staus(StatusCodes.BAD_REQUEST).end();
}
res.status(StatusCodes.OK).json(results);
}
)
};
2.2. 장바구니 목록 조회
// CartController.js
const getCartItems = (req, res) => {
const {user_id} = req.body;
let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price FROM cartItems LEFT JOIN books ON cartItems.book_id = books.id WHERE user_id = ?`;
conn.query(sql, user_id,
(err, results) => {
if (err) {
console.log(err);
return res.staus(StatusCodes.BAD_REQUEST).end();
}
res.status(StatusCodes.OK).json(results);
}
)
};
2.3. 장바구니 아이템 삭제
// CartController.js
const removeCartItem = (req, res) => {
// 장바구니 아이템 삭제
const {id} = req.params;
let sql = `DELETE FROM cartItems WHERE id = ?`;
conn.query(sql, id,
(err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
res.status(StatusCodes.OK).json(results);
}
)
};
2.4. 장바구니에서 선택한 아이템 목록 조회

장바구니에 여러 상품이 담겨있을 때, 일부 상품만 골라서 결제하는 상황이 있을 수 있는데, 이때 장바구니 전체 목록에서 선택한 일부 상품만 조회하는 API 를 만들려고 한다. 근데 생각해보면, 장바구니에 담은 전체 상품을 조회하는 API 를 살짝만 고치면 장바구니에서 선택한 상품만을 조회할 수 있기 때문에 기존의 코드를 고쳐서 사용하려고 한다.
selected 라는 배열에 선택한 상품의 id 값을 담아서 보낼 수 있는데, request body 에 selected 가 담겨오면 선택한 장바구니 상품 목록 죄회를 담겨오지 않으면 장바구니 전체 아이템 목록 조회를 할 수 있도록 만들었다.
- request body 에 user_id, selected 배열을 담아서 보냄 -> 장바구니에서 선택한 상품 목록 조회
- request body 에 user_id 만 담아서 보냄 -> 장바구니 전체 목록 조회
// CartController.js
const getCartItems = (req, res) => {
// 장바구니 아이템 목록 조회 & 선택한 장바구니 상품 목록 조회
const {user_id, selected} = req.body;
let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price
FROM cartItems LEFT JOIN books
ON cartItems.book_id = books.id
WHERE user_id = ?`;
let values = [user_id];
if (selected) {
sql += 'AND cartItems.id IN (?)';
values.push(selected);
}
conn.query(sql, values,
(err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
res.status(StatusCodes.OK).json(results);
}
)
};
sql 쿼리문을 살펴보자.
출력할 컬럼들 고르기
SELECT cartItems.id, book_id, title, summary, quantity, price
cartItems 테이블과 books 테이블을 cartItems.book_id = books.id 의 조건으로 조인하기
FROM cartItems LEFT JOIN books ON cartItems.book_id = books.id
user_id 가 ? 이고 cartItems.id 값이 ?(배열) 조건일 때
WHERE user_id = ? AND cartItems.id IN (?)
※ 여기서 IN 은 특정 조건을 만족하는 여러 값을 비교할 때 사용하는 연산자로 (...) 괄호 안에 들어가는 여러 값들 중 하나인 모든 행을 조회한다.
'TIL with Programmers' 카테고리의 다른 글
[회고록] 풀 사이클 개발 데브코스 8주차 회고 (5) | 2024.10.12 |
---|---|
[TIL] 10/11 주문 기능 구현 (2) | 2024.10.11 |
[TIL] 10/8 좋아요 기능 구현, 서브쿼리-count(), EXISTS,AS (4) | 2024.10.08 |
[TIL] 10/7 API 구현, LEFT JOIN, DATE_ADD, DATE_SUB, 페이징 (0) | 2024.10.07 |
[회고록] 풀 사이클 개발 데브코스 7주차 회고 (1) | 2024.10.05 |