상세 컨텐츠

본문 제목

장바구니와 상품의 관계, Sequelize로 구현하기(다대다 관계)

데이터베이스/RDBMS

by moonionn 2020. 9. 11. 06:41

본문

Photo by David Veksler on Unsplash

 

한명의 고객은 하나의 장바구니를 가지고 있습니다. (일대일)

하지만 하나의 장바구니는 여러 개의 상품을 담습니다.

반대로, 하나의 상품 종류는 여러 고객의 장바구니에 포함될 수 있습니다.

그렇다면 장바구니와 상품의 상관관계를 어떻게 설정해야 할까요.

 

우선 예시를 위해 장바구니와 상품 모델을 각각 생성해 봅니다.

const Sequelize = require('sequelize');	// 시퀄라이즈 패키지
const sequelize = require('../util/database');	// 인스턴스


// creating carts table
const Cart = sequelize.define('cart', {
  id: {
    type: Sequelize.INTEGER,
    autoIncrement: true,
    allowNull: false,
    primaryKey: true
  }
});

//creating products table
const Product = sequelize.define('product', {
  id: {
    type: Sequelize.INTEGER,
    autoIncrement: true,
    allowNull: false,
    primaryKey: true
  },
  name: {
    type: Sequelize.STRING,
    allowNull: false
  },
  price: {
    type: Sequelize.DECIMAL(13, 2),
    allowNull: false
  },
  description: {
    type: Sequelize.STRING,
    allowNull: false
  }
});

sequelize에서는 다양한 associations 설정 옵션을 제공합니다.

(hasOne, belongsTo, hasMany, belongsToMany)

그 중 이 상황에서는 다대다(ManyToMany) 관계에 해당합니다.

따라서 belongsToMany 로 관계를 설정해 주어야 합니다.

 

연결을 위한 테이블 생성

상품과 장바구니의 연결역할을 해줄 CartItem이라는 새로운 모델을 생성합니다.

// 👇 a single cart contains multiple products,  
Cart.belongsToMany(Product, { through: CartItem });

// 👇 a single type of product can be contained in multiple carts.
Product.belongsToMany(Cart, { through: CartItem });

 

이렇게 되면 cartItems라는 테이블이 자동으로 생성되는데,

연결해줘야 하는 테이블들의 id(PK) 정보를 필드로 탑재합니다.

위 예시의 cartItems 테이블은 자신의 id, cartId, productId를 지닙니다.

 

하지만 장바구니는 상품의 종류뿐 아니라 상품을 몇개 담을지도 알아야 합니다.

이런 추가정보는 cartItems 테이블에서 직접 지정해줍니다.

const Sequelize = require('sequelize');
const sequelize = require('../util/database');

const CartItem = sequelize.define('cartItem', {

  id: {
    type: Sequelize.INTEGER,
    autoIncrement: true,
    allowNull: false,
    primaryKey: true
  },
  
  // 👇quantity info
  quantity: {
    type: Sequelize.INTEGER,
    allowNull: false
  }
  
});

필드값이 제대로 생성된 모습

 

hasMany / belongsToMany 차이점

Sequelize의 관계 설정을 문자 그대로 받아들이다보면

'Cart.hasMany(Product)이 맞지 않나..?' 라는 생각이 들 수 있습니다.

Cart.hasMany(Product, { through: CartItem });

// ???

 

실제로 많은 사람들이 헷갈려 하는 부분이기도 합니다.

하지만 hasMany는 쓴다면 source(여기서는 Cart)

여러 target(여기서는 Product)을 가질 수는 있지만,

target은 단 하나의 source에만 속할 수 있게 됩니다.

 

ex)

생수통이 여러개 냉장고에 진열되어 있는데,

홍길동이라는 고객이 이 생수통을 하나만 가져가도

다른 고객은 이제 이 상품을 못 가져가게 된다!

-> 논리적 오류!

 

belongsToMany 의 기능

Cart.belongsToMany(Product, { through: CartItem });
Product.belongsToMany(Cart, { through: CartItem });

이렇게 관계를 설정해주고 나면, 특별한 기능을 사용할 수 있게 됩니다.

바로 Cart.getProducts(), Cart.addProduct()... 등과 같은 메소드입니다.

연결된 테이블끼리 서로의 테이블이름을 통해 데이터 조작/조회가 가능합니다!

정말 놀라운 기능이지 않습니까...

 

예를 들어, 장바구니에서 특정 상품이 있는지 없는지 확인하고 싶으면

Cart.getProducts({ where: { id: productID  } });

 

또는 장바구니에 새로운 상품을 넣고 싶다면

Cart.addProduct(product, { through: { quantity: 1  } });

 

(경우에 따라 복수형인지 단수형 구분도 해주어야 합니다.)

관련글 더보기

댓글 영역