🎯 μž₯λ°”κ΅¬λ‹ˆ APIλ₯Ό μ„€κ³„ν•˜κ³  μ½”λ“œμ— μ μš©ν•©λ‹ˆλ‹€.


πŸ“™ Today I Learned

λ°μ΄ν„°λ² μ΄μŠ€ cartItems μΆ”κ°€

id INT
book_id INT
quantity INT
user_id INT

SQL IN μ—°μ‚°μž μ‚¬μš©λ²•

IN μ—°μ‚°μžλ‘œ λ¦¬μŠ€νŠΈκ°’μ„ λ°›μ•„ 데이터λ₯Ό μ‘°νšŒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

SELECT μ—΄_이름 FROM ν…Œμ΄λΈ” WHERE 컬럼_이름 IN (?);



🚨 μ™Έλž˜ν‚€ 쀑볡 였λ₯˜ λ°œμƒ 및 ν•΄κ²°

⚠️ λ°œμƒν•œ 였λ₯˜

μ™Έλž˜ν‚€ μ§€μ • μ‹œμ— error: 121 Duplicate key on write or update 였λ₯˜κ°€ λ°œμƒν•˜μ˜€μŠ΅λ‹ˆλ‹€.
λ™μΌν•œ μ΄λ¦„μ˜ FK μ œμ•½ 쑰건이 이미 μ‘΄μž¬ν•˜μ—¬ 생긴 였λ₯˜μ˜€μŠ΅λ‹ˆλ‹€.

πŸ’‘ ν•΄κ²° κ³Όμ •

FK μ œμ•½μ‘°κ±΄ 넀이밍 κ·œμΉ™μ„ μ •ν•˜μ—¬ λ™μΌν•œ 이름이 생기지 μ•Šλ„λ‘ ν•΄μ€λ‹ˆλ‹€.

fk_ν…Œμ΄λΈ”λͺ…_μ°Έμ‘°ν…Œμ΄λΈ”λͺ…_컬럼λͺ…




μž₯λ°”κ΅¬λ‹ˆ API 섀계

πŸ‘‰ μˆ˜μ •ν•œ 뢀뢄은 주황색 κΈ€μ”¨λ‘œ λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

μž₯λ°”κ΅¬λ‹ˆ λ‹΄κΈ°

  • Method : POST

  • URL : /carts

  • HTTP Status Code : 200 Ok

  • Request Body

  {
    "bookId" : λ„μ„œ id,
    "quantity" : μˆ˜λŸ‰,
    "userId" : μœ μ € id
  }
  • Response Body : x

  • TODO : ν˜„μž¬λŠ” ν† ν°μœΌλ‘œ ν•˜μ§€ μ•Šκ³ ,userIdλ₯Ό bodyκ°’μœΌλ‘œ λ°›μ•„μ„œ 처리


μž₯λ°”κ΅¬λ‹ˆ 쑰회 / 선택 μƒν’ˆ 쑰회(μ£Όλ¬Έμ„œ μž‘μ„±)

  • Method : GET

  • URL : /carts

  • HTTP Status Code : 200 Ok

  • Request Body :

{
   "userId" : μœ μ € id,
   "selected" : [cartItemId, cartItemId ...]
}
  • Response Body
 [
  { 
    "id" : μž₯λ°”κ΅¬λ‹ˆ id,
    "bookId" : λ„μ„œ id,
    "title" : "λ„μ„œ 제λͺ©",
    "summary" : "μš”μ•½ μ„€λͺ…",
    "quantity" : μˆ˜λŸ‰,
    "price" : 가격
  },
  {
    "id" : μž₯λ°”κ΅¬λ‹ˆ id,
    "bookId" : λ„μ„œ id,
    "title" : "λ„μ„œ 제λͺ©",
    "summary" : "μš”μ•½ μ„€λͺ…",
    "quantity" : μˆ˜λŸ‰,
    "price" : 가격
  },
 ]
  • TODO : ν˜„μž¬λŠ” ν† ν°μœΌλ‘œ ν•˜μ§€ μ•Šκ³ ,userIdλ₯Ό bodyκ°’μœΌλ‘œ λ°›μ•„μ„œ 처리

μž₯λ°”κ΅¬λ‹ˆ μ‚­μ œ

  • Method : DELETE

  • URL : /carts/:cartItemId

  • HTTP Status Code : 200 Ok

  • Request Body : x

  • Response Body : x




🚨 port 였λ₯˜ λ°œμƒ 및 ν•΄κ²°

⚠️ λ°œμƒν•œ 였λ₯˜

μ½”λ“œ μ‹€ν–‰ μ‹œμ— Error: listen EACCES: permission denied 0.0.0.0:9999 였λ₯˜κ°€ λ°œμƒν•˜μ˜€μŠ΅λ‹ˆλ‹€.
포트 좩돌 였λ₯˜λ‘œ μΈν•΄μ„œ λ°œμƒν•œ 였λ₯˜μ΄μ§€λ§Œ, ν¬νŠΈκ°€ μ‚¬μš© 쀑이지 μ•ŠμŒμ—λ„ 접근이 μ°¨λ‹¨λ˜λŠ” 였λ₯˜μ˜€μŠ΅λ‹ˆλ‹€.

πŸ’‘ ν•΄κ²° κ³Όμ •

Windowsμ—μ„œ WinNAT(Windows Network Address Translation) μ„œλΉ„μŠ€λ₯Ό μ€‘μ§€ν•˜λŠ” λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•΄μ„œ 포트 μΆ©λŒμ„ ν•΄κ²°ν•΄μ€λ‹ˆλ‹€.


cmdλ₯Ό κ΄€λ¦¬μž κΆŒν•œμœΌλ‘œ μ—΄κ³  ν•΄λ‹Ή λͺ…λ Ήμ–΄λ₯Ό μž…λ ₯ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

$ net stop winnat
$ net start winnat



CartController.js

const conn = require('../mariadb');
const { StatusCodes } = require('http-status-codes');

const addToCart = (req, res) => {
  const { bookId, quantity, userId } = req.body;

  const sql =
    'INSERT INTO cartItems (book_id, quantity, user_id) VALUES (?, ?, ?)';
  const values = [bookId, quantity, userId];
  conn.query(sql, values, (err, result) => {
    if (err) {
      console.log(err);
      return res.status(StatusCodes.BAD_REQUEST).end();
    }

    return res.status(StatusCodes.CREATED).json(result);
  });
};

const getCartItems = (req, res) => {
  const { userId, 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 (?)';
  const values = [userId, selected];
  conn.query(sql, values, (err, result) => {
    if (err) {
      console.log(err);
      return res.status(StatusCodes.BAD_REQUEST).end();
    }

    return res.status(StatusCodes.OK).json(result);
  });
};

const removeCartItems = (req, res) => {
  const id = parseInt(req.params.id);

  const sql = 'DELETE FROM cartItems WHERE id = ?';
  conn.query(sql, id, (err, result) => {
    if (err) {
      console.log(err);
      return res.status(StatusCodes.BAD_REQUEST).end();
    }

    return res.status(StatusCodes.OK).json(result);
  });
};

module.exports = { addToCart, getCartItems, removeCartItems };
  • addToCart : bookId, quantity, userIdλ₯Ό λ°›μ•„μ„œ μž₯λ°”κ΅¬λ‹ˆμ— μΆ”κ°€ν•©λ‹ˆλ‹€.

  • getCartItems : cartItems ν…Œμ΄λΈ”κ³Ό books ν…Œμ΄λΈ”μ„ LEFT JOINν•˜μ—¬, userId의 μž₯λ°”κ΅¬λ‹ˆ ν•­λͺ© 쀑 selected에 ν¬ν•¨λœ cartItems.id λͺ©λ‘μ„ μ‘°νšŒν•˜κ³ , ν•΄λ‹Ή book_id의 title, summary, quantity, price 정보λ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€.

  • removeCartItems : id 값을 λ°›μ•„μ„œ μž₯λ°”κ΅¬λ‹ˆμ—μ„œ ν•΄λ‹Ή ν•­λͺ©μ„ μ‚­μ œν•©λ‹ˆλ‹€.




✏️ ν•œ 쀄 회고

였늘 였λ₯˜κ°€ 많이 λ‚˜μ„œ μ’€ μ• λ₯Ό λ¨Ήμ—ˆμ§€λ§Œ, 잘 ν•΄κ²°ν–ˆλ‹€. 쿼리에 배열을 λ°›μ•„μ„œ ν™œμš©ν•˜λŠ” 방법을 μ•Œμ•˜λ‹€!

profile
🌱개발 기둝μž₯

0개의 λŒ“κΈ€