MutableList vs MutableSet

최경현·2025년 6월 4일

프로젝트를 진행하면서 겪었던 문제중에서

MutableList vs MutableSet

에 관해 설명하려고 한다.

기본적으로 프로퍼티를 선언하면서 1:N or N:N 관계 매핑을 할 때 mutableList를 많이 사용하였다.

mutableList

  • 중복 허용 (같은 객체 여러 번 넣을 수 있음)
  • 순서 유지 (인덱스 순서대로 저장)
  • 검색 속도 느림
  • ArrayList

mutableSet

  • 중복 불가능
  • 순서 보장이 안 됨
  • 검색 속도 빠름
  • HashSet

mutableList를 사용하다가 mutableSet을 사용하면서 직면한 문제가 있었다.

프로젝트 진행중에 테이블에서 MenuCategoryMenuDetail은 다대다(@ManyToMany) 관계로 연결되어 있었고, MenuCategory 엔티티 안에는 다음과 같이 menuDetails라는 컬렉션이 있었다.

처음에는 특정 MenuDetail을 menuDetails에서 remove()한 뒤 다시 저장하면
DB에서 연관관계가 잘 제거될 줄 알았지만, 실제로는 아무 변화도 생기지 않았다.

문제의 원인

MutableSet은 내부적으로 객체를 비교할 때 equals()와 hashCode()를 기준으로 판단한다고 한다.

하지만 MenuDetail 엔티티에서 equals()와 hashCode()를 오버라이드하지 않았기 때문에,
JPA가 remove()를 해도 해당 객체가 기존 Set에 존재한다고 판단하지 못한 것이다.
즉, remove()가 실패한 것이고 → 그에 따라 DB에서도 삭제 쿼리가 발생하지 않은 것이다.

해결 방법

MenuDetail 엔티티에 다음과 같이 equals()와 hashCode()를 오버라이드해주었다.

override fun equals(other: Any?): Boolean {
    if (this === other) return true
    if (other !is MenuDetail) return false
    if (id == 0L || other.id == 0L) return false
    return id == other.id
}

override fun hashCode(): Int = id.hashCode()

이렇게 하면 JPA는 Set 안의 객체를 비교할 때 ID 기준으로 정확히 판단할 수 있게 되었고,
remove()도 정상적으로 작동하며, 그에 따라 DB의 연관관계도 제거되었다.

결론

MutableSet을 사용할 때는 객체의 고유성을 보장해줄 수 있는
equals()와 hashCode() 구현이 반드시 필요하다.
특히 JPA에서 엔티티 간의 관계를 다룰 때, 이 차이를 모르고 Set을 사용하면
변경이 적용되지 않거나 삭제가 안 되는 등 예기치 않은 문제가 발생할 수 있다.

profile
ㅇㅇ

0개의 댓글