So2zy 프로젝트에서 장바구니 추가 api를 담당해서 개발을 했다. “야놀자”의 객실상품을 “장바구니”에 추가하는 로직을 구현해야하므로, ERD를 아래와 같이 작성해보았다. 🌱

처음에는 ERD를 짤 때, Room, Cart 테이블만 존재하면 될 줄 알았다.. 😲
근데, JPA 특성상 N:M관계는 최대한 지양하는 추세이므로 Room_cart와 Room_product라는 중간 테이블을 구현해야했다.
⚠️
왜 N:M관계는 최대한 지양해야할까 ?
- JPA에서는 @ManyToMany어노테이션을 제공해준다.
- 이 어노테이션은, 암묵적으로 중간 테이블을 생성해주어서 자기도 모르는 복잡한 조인 쿼리가 발생할 수도 있다. ⇒ 성능저하 발생 가능
- 암묵적으로 생긴 중간테이블에 칼럼을 추가할 수 없다.
⇒ 중간테이블(연결테이블) == 두 엔티티간의 관계를 나타내기 위한 용도
⇒ @ManyToMany를 직접 사용하기 보다, @ManyToOne, @OneToMany를 사용해서 직접 중간 테이블을 생성하는 방법이 선호된다.
중간 테이블 java 구조
N:M관계를 지양하므로, 일대다 양방향 관계와 일대다 단방향 관계로 model을 구축했다.
다대일 양방향 관계
- 관계형 데이터베이스에서 외래키는 항상 “다”쪽에 있기 때문에 @OneToMany를 사용하는 객체의 필드는 연관관계의 주인이 되지 않는다. 즉, 주인은 @ManyToOne에 있다.

RoomCart.java
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RoomCart extends BaseTimeEntity {
' '
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cart_id")
private Cart cart;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "room_product_id")
private RoomProduct roomProduct;
' ' '
}
@ManyToOne
어노테이션을 사용하여Cart
엔터티와의 다대일(N:1) 관계를 표현
@JoinColumn(name = "cart_id")
은 외래 키를 통해 두 엔터티 간의 관계를 매핑
@JsonBackReference
어노테이션은 양방향 관계에서 무한 루프를 방지🔗 관련된 Trouble Shooting : https://github.com/so2zy/so2zy_BE/discussions/23
Cart.java
@Slf4j
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Cart extends BaseTimeEntity {
' ' '
@JsonManagedReference
@OneToMany(mappedBy = "cart", fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL)
private List<RoomCart> roomCartList = new ArrayList<>();
' ' '
}
@OneToMany
어노테이션을 사용하여roomCartList
라는 리스트를 통해RoomCart
엔터티들과의 1:다(1:N) 양방향 관계를 표현
mappedBy = "cart"
로RoomCart
엔터티의cart
필드에 의해 매핑
@JsonManagedReference
어노테이션으로 양방향 관계에서 주인 측을 나타냄⇒ JSON 직렬화 시에 이 측만 직렬화되도록 함
다대일 단방향 관계

RoomCart.java
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RoomCart extends BaseTimeEntity {
' '
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cart_id")
private Cart cart;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "room_product_id")
private RoomProduct roomProduct;
' ' '
}
@ManyToOne
어노테이션을 사용하여RoomProduct
엔터티와의 다대일(N:1) 단방향 관계를 표현
@JoinColumn(name = "room_product_id")
은 외래 키를 통해 두 엔터티 간의 관계를 매핑
RoomProduct.java
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RoomProduct extends BaseTimeEntity {
' ' '
' ' '
}
- RoomProduct와 RoomCart는 다대일 단방향관계이다.
- RoomCart(N) ←RoomProduct(1)
- 관계형 데이터베이스에서 외래키는 항상 “다”쪽에 있기 때문에 @OneToMany를 사용하는 객체의 필드는 연관관계의 주인이 되지 않는다. 즉, 주인은 @ManyToOne에 있다.
- 주인이 아닌쪽은 ‘읽기’만 가능
- RoomCart(N) ←RoomProduct(1)
전반적인 코드는 GITHUB에서 확인할 수 있다.
https://github.com/so2zy/so2zy_BE/tree/main/src/main/java/com/aroom/domain/roomCart
Uploaded by N2T