jpa를 사용하면서 일대다(다대일)의 연관 관계에 있는 Entity를 구현하는 경우, 항상 아래와 같이 List
를 사용하여 구현하였다.
@OneToMany(mappedBy = "targetEntity")
List<Entity> entities = new ArraryList()
jpa는 java에서 기본적으로 제공하는 Collection, List, Set, Map을 지원하며 이를 Entity 연관 관계를 매핑하거나 ElementCollection을 사용할 때 이를 적용할 수 있다.
하지만 처음 jpa를 공부하고, 현업에서 사용하고 있는 지금까지 List만으로 Entity를 설계하였다. 그러다 문득 코드를 짜다 보면 성능상의 이유로 List
가 아닌 Set
을 사용하는 경우가 있다는 것이 생각났고 Entity를 설계하는 과정에서 List
만을 쓰는 이유가 궁금해졌다.
가장 큰 이유는 Set과 List의 근본적인 차이를 이해한다면 쉽게 파악할 수 있었다.
Set: 중복 불가
List: 중복 허용
얼핏 보기엔 Set을 사용하여 중복 체크 여부를 생략하고 값 타입 컬렉션을 사용할 때 발생하는 모든 Row [Delete -> Save] 과정 또한 해결할 수 있어 좋은 선택이 되는 것 같았다. 하지만 실제로 jpa를 쓰다 보면 대부분의 Entity 연관 관계는 Lazy Loading
으로 돼있는데 이 경우에 문제가 발생한다.
풀어서 설명하자면 Set의 경우 기존에 가지고 있던 Entity(값 타입)에 중복된 데이터가 있는지 비교를 해야 하는데 이 시점에 Set에 있는 모든 데이터를 로딩해야만 하고 이 때 Proxy가 강제로 초기화된다. 결론적으로는 Lazy Loading
을 사용할 수가 없어 성능적으로 좋지 못한 결과를 얻게 된다.
하나를 쓰더라도 제대로 알고 쓰는게 중요한 것 같다. 단순히 Set의 장점만을 생각하여 코드를 구현하는 것이 아니라 왜 List를 써야하는지, 썼을 때 어떤 이점을 가지는지 명확하게 알 수 있었다.