트리플 클론 코딩을 하면서 여행지 추천 기능을 구현해야했다.
이때, 추천받은 여행지에 대해 사용자는 좋아요(찜) 을 할 수 있어야 했으며, 자신에게 달린 리뷰들을 저장해야 했다,
따라서 추천받은 여행지는 자신을 좋아요를 누른 사용자들의 id값을 List형식으로 가지고 있어야 하고, 자신에게 달린 Review들을 List형식으로 가지고 있어야 했다.
엔티티에 List를 저장하기 위해서는 @OneToMany를 통해 연관관계 매핑을 하거나 @ElementCollection을 사용, @Convert의 사용 이 3가지를 들 수 있으며 @Convert는 List를 String 형식으로 변환하여 저장하는 기능이고, 이번에는 @Convert를 제외한 @OneToMany와 @ElementCollection의 장단점들을 알아보고자 했다.
1. @OneToMany
장점
- 강력한 관계 표현:
- @OneToMany는 두 엔티티 간의 일대다 관계를 명확하게 표현합니다. 부모 엔티티는 여러 자식 엔티티를 가질 수 있다.
- 추가 정보 저장 가능:
- 연관된 엔티티와 함께 추가 정보를 저장할 수 있습니다. 예를 들어, 조인 테이블을 사용하여 추가 컬럼을 정의하거나, 자식 엔티티에 추가 정보를 저장할 수 있다.
- 유연한 조인(JOIN) 기능:
- 연관된 엔티티를 조인하여 한 번에 쿼리를 실행할 수 있습니다. 이를 통해 필요한 정보를 더욱 효율적으로 가져올 수 있다.
- 양방향 관계 지원:
- @OneToMany는 양방향 관계를 설정할 수 있습니다. 부모 엔티티와 자식 엔티티 간의 관계를 양쪽으로 매핑할 수 있다.
단점
- 조인(JOIN)으로 인한 성능 저하:
- @OneToMany는 조인을 사용하여 데이터를 가져오기 때문에, 조인의 사용에 따라 성능 저하가 발생할 수 있습니다. 특히 대량의 데이터를 처리할 때 조인은 성능에 영향을 줄 수 있다.
- 양방향 관계 설정의 복잡성:
- 양방향 관계를 설정할 때 상호 참조로 인해 실수하기 쉽습니다. 양쪽 엔티티 간의 관계를 올바르게 설정하고 유지하는 것이 어려울 수 있다.
- 데이터 무결성 유지의 어려움:
- 데이터 무결성을 유지하기 위해 부모 엔티티의 변경이나 삭제 시 자식 엔티티에 대한 관리가 필요합니다. 이를 실수로 인해 데이터 무결성이 깨질 수 있다.
- 복잡성 증가:
- 복잡한 데이터 모델에서는 @OneToMany 관계의 설정과 유지가 복잡해질 수 있습니다. 특히 다양한 연관성과 조인이 필요한 경우 더 복잡해질 수 있다.
@OneToMany에 대한 사용법은 다루지 않도록 하겠다.
2. @ElementCollection
장점
- 간단한 구현:
- @ElementCollection은 단순한 값(Primitive나 Embeddable 타입)을 저장할 때 간단하고 직관적입니다. 별도의 엔티티를 만들 필요가 없다.
- 조인(JOIN) 없는 성능:
- @ElementCollection을 사용하는 경우에는 별도의 조인이 발생하지 않습니다. 때때로 이는 성능 상 이점을 가져올 수 있다.
단점
- 제한된 관리 기능:
- @ElementCollection을 사용하면 컬렉션의 요소에 대한 추가적인 관리 및 쿼리 작업이 제한될 수 있습니다. 엔티티와는 달리 컬렉션에 대한 독립적인 쿼리 작성이 제한된다.
- 추가 정보의 관리 어려움:
- @ElementCollection을 사용하면 컬렉션에 저장되는 값 외에는 추가적인 정보를 저장하기 어려울 수 있습니다. 이는 @OneToMany와 비교하여 제한적인 부분이다.
- 복잡한 관계의 제한:
- @ElementCollection은 단순한 값 타입의 컬렉션을 저장하기에 적합하며, 복잡한 연관 관계에는 부적합할 수 있습니다. 또한 양방향 관계를 설정하는 기능이 제한된다.
@ElementCollection을 사용하면 @OneToMany와 같이 새로운 테이블이 생성된다. 하지만 @OneToMany와 다른점은 이 테이블은 오직 부모테이블을 통해서만 접근이 가능하며, 부모테이블에서 이 테이블로 접근할 때 join이 발생하지 않는다.
또한 @CollectionTable를 함께 사용해준다면, 이 테이블은 부모테이블에 종속되어 관리된다.
사용법
위와 같이 List의 위에 @ElementCollection과 @CollectionTable을 명시해 줌으로써 이를 사용할 수 있으며, 따로 별도의 클래스는 생성하지 않아도 된다.
이를 사용하면 @ElementCollection의 단점에서 보다시피 제약이 존재한다.
- 값 타입은 엔티티와 다르게 식별자 개념이 없기 때문에 값을 변경하면 추적이 어렵다.
- 값 타입 컬렉션에 변경 사항(저장, 삭제)이 발생하면, 소유하는 엔티티와 연관된 모든 데이터를 삭제하고, 현재 남아있는 값을 모두 다시 저장한다.(예제에서는 삭제를 예로 들었지만, 저장도 마찬가지)
- 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본키를 구성해야 함 → null 입력 X, 중복 저장 X
따라서 @ElementCollection은 복잡한 연관관계가 아닌 단순히 값타입 컬렉션만을 구현하고자 할 때에 사용한다면 @OneToMany보다 더 간결하고 성능적으로도 이득을 볼 수 있다.
하지만 만약 식별자가 필요하고, 지속해서 값을 추적, 변경해야 한다면 값 타입이 아닌 엔티티로 사용해야 한다.
'백엔드 멘토링' 카테고리의 다른 글
좋아요 기능 성능 개선해보기 (2) (0) | 2024.02.22 |
---|---|
좋아요 기능 성능 개선해보기 (1) (1) | 2024.02.16 |
단축 url 서비스 Base62으로 리팩터링하기 - 회고록 (1) | 2023.10.08 |
자바의 신 - 복습 정리(2) (0) | 2023.09.23 |
Transaction이란? (0) | 2023.09.23 |