[트러블 슈팅] [Node.js] SQL 바인딩 및 배열 전개

Young Min Kang·2024년 5월 29일

트러블 슈팅

목록 보기
1/5
post-thumbnail

쿼리문에 배열 넣기

다음은 장바구니 조회관련 API를 작성하다 생긴 이슈이다.

const getCartItem = (req, res) => {
    const {user_id, selected} = req.body;

    let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price, price*quantity as total_price
                FROM cartItems
                JOIN books ON(cartItems.book_id = books.id)
                WHERE user_id = ? AND cartItems.id IN (?)`;
    let values = [user_id, ...selected];

    conn.query(sql, values, (err, results) => {
        if (err) {
            console.log(err);
            return res.status(StatusCodes.BAD_REQUEST).end();
        }
        return res.status(StatusCodes.OK).json(results);
    })
}

보다시피 body로 2개를 받는데 유저의 아이디와 선택한 아이템들에 관한 아이디 값을 받는다.

문제😲

헌데 문제는 이 selected는 배열이기에 SQL 쿼리를 작성하기 애매하다는 것에 있다.
즉, 값이 몇 개가 올 지 모른다는 것이다. 일단 배열을 스프레드 연산자(Spread Operator)로 풀어서 넣는다면 ?(플레이스홀더)는 현재 하나이기에 값이 하나만 들어가는 결과가 발생한다.

?(플레이스홀더) 하나에 어떻게 배열의 모든 값들을 대입할까?

해결🚀

  1. 자동 : 그냥 배열을 넣으면 된다.

    mysql2 라이브러리는 플레이스홀더를 사용하여 배열의 값을 자동으로 처리할 수 있다. 때문에 배열의 길이에 따라 플레이스홀더가 자동으로 설정된다.

  2. 수동 : 플레이스홀더를 수동으로 설정

    아래와 같이 배열의 값에 따라서 플레이스홀더 개수를 설정하는 방법이 있겠다.

    let placeholders = selected.map(() => '?').join(',');
    
    // 쿼리 작성
    let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price, price*quantity as total_price
               FROM cartItems
               JOIN books ON(cartItems.book_id = books.id)
               WHERE user_id = ? AND cartItems.id IN (${placeholders})`;
    
    // 배열의 값을 플레이스홀더로 전달
    let values = [user_id, ...selected];

최종✔️

누가봐도 자동이 간편하다.

const getCartItem = (req, res) => {
    const {user_id, selected} = req.body;

    let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price, price*quantity as total_price
                FROM cartItems
                JOIN books ON(cartItems.book_id = books.id)
                WHERE user_id = ? AND cartItems.id IN (?)`;
    let values = [user_id, selected];

    conn.query(sql, values, (err, results) => {
        if (err) {
            console.log(err);
            return res.status(StatusCodes.BAD_REQUEST).end();
        }
        return res.status(StatusCodes.OK).json(results);
    })
}

무사히 2개가 출력되는 모습!

profile
꾸준히 한걸음씩

0개의 댓글