지난 시간 좋아요 API를 추가하고 책 API를 수정했어요. 이번에는 장바구니 API를 추가해 볼게요.
여러 조건을 확인하기 위해서 OR 을 사용할 수 있습니다. 하지만 조건이 간단한데 많아진다면 SQL만 길어지고 가독성이 떨어지게 돼요. OR 을 여러 번 사용하는 대신 IN 을 사용하면 간단하게 사용할 수 있어요.
-- 기존 방식
SELECT * FROM table WHERE id = 1 OR id = 2 OR id = 100;
-- IN 사용
SELECT * FROM table WHERE id IN (1, 2, 100);
장바구니 테이블을 만들면서 외래키 설정이 안 되는 문제가 발생했어요.
DataGrip은 외래키와 인덱스 이름을 자동으로 만들어주지만, 인강에서는 Workbench를 사용하다보니 작업하다가 외래키 이름이 중복되어서 Error 1005가 났고, 이름을 바꿨더니 이번엔 인덱스 이름이 중복되어서 Error 1061이 떴어요.
이름들이 겹치지 않게 잘 수정해서 해결했어요.
장바구니 추가는 INSERT 문을 이용해 테이블에 추가하는 방식으로 구현했어요.
export const addToCart = (req, res) => {
const { book_id, quantity,user_id } = req.body;
const sql = `INSERT INTO cartItems (book_id, quantity, user_id)
VALUES (?, ?, ?)`;
const values = [book_id, quantity, user_id];
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);
});
};
삭제는 DELETE 문을 이용해 테이블에서 삭제하는 방식이에요. 여기서 다른 사용자의 목록을 삭제하지 않도록user_id 를 조건으로 사용했어요.
export const removeCartItem = (req, res) => {
const { id } = req.params;
const sql = `DELETE FROM cartItems WHERE id = ?`;
conn.query(sql, id, (err, results) => {
if (err) return res.status(statusCode.INTERNAL_SERVER_ERROR).json({message: err.message});
return res.status(statusCode.OK).json(results);
});
}
원래라면 삭제할 때 사용자 확인(JWT)을 거쳐야 하지만, 아직 JWT를 적용하기 전이라 일단은 단순하게 삭제하는 것으로 진행했어요.
SELECT 문과 JOIN 을 활용해 프론트엔드에 필요한 정보를 정리해서 넘겨주기로 했어요.
이때 실제 테이블의 전체 목록이 아닌 user_id 를 통해 로그인한 유저의 목록만 보여주어야 해요.
SELECT baskets.id, book_id, title, summary, quantity, price
FROM baskets LEFT JOIN books
ON baskets.book_id = books.id
WHERE user_id = ?;
프론트엔드에서 요청을 할 때 선택된 장바구니 id를 배열에 담아서 넘겨주기로 했어요. 선택된 장바구니의 수가 얼마나 될지 모르기 때문에 OR로 하나하나 받아오는 것보다 앞서 살펴본 IN을 활용해 구현했어요.
SELECT baskets.id, book_id, title, summary, quantity, price
FROM baskets LEFT JOIN books
ON baskets.book_id = books.id
WHERE user_id = ? AND baskets.id IN (?);
이제 여기서 '배열로 받기로 했는데 IN 뒤의 ?는 한 개여도 괜찮은가?' 하는 의문이 들 수 있어요.
예전에는 반복문을 통해 ?의 개수를 추가해 주는 작업이 필요했는데,
2021년 이후부터는 IN의 ?에 배열을 그대로 집어넣어도 알아서 풀어서 넣어준다고 해요.
export const getCartItems = (req, res) => {
const { user_id, selected } = req.body;
const sql =
`SELECT cartItems.id, book_id, title, summary, quantity, price
FROM cartItems LEFT JOIN books
ON cartItems.book_id = books.id
WHERE user_id = ?
AND cartItems.id IN (?)`
conn.query(sql, [user_id, selected], (err, results) => {
if (err) return res.status(statusCode.INTERNAL_SERVER_ERROR).json({message: err.message});
return res.status(statusCode.OK).json(results);
});
};
결론적으로 만들어진 장바구니에서 선택된 아이템들을 반환하는 api에요.