인프런 김영한 강사님의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 을 수강하고 정리한 글입니다.
📌 기본값 타입
✅ JPA 데이터 타입 분류
엔티티 타입
- @Entity로 정의하는 객체
- 데이터가 변해도 식별자로 지속 추적 가능
값 타입
- int, Integer, String 처럼 단순 값으로 사용하는 자바 기본 타입 또는 객체
- 식별자가 없고 값만 존재하므로, 변경 시 추적 불가능
✅ 기본값 타입
예시 ) String, int
생명 주기를 엔티티에 의존한다.
예를 들어, 회원을 삭제하게 되면 이름과 나이 필드도 함께 삭제되는 것과 같다.
값 타입은 공유하면 안된다.
예를 들어, 회원 이름 변경 시, 다른 회원의 이름도 같이 변경되면 안된다.
📌 임베디드 타입
✅ 임베디드 타입
새로운 값 타입을 직접 정의하는 것을 말한다.
주로 기본 값 타입을 모아서 만들기 때문에 복합 값 타입이라고도 부른다.
어쨌든 기본 값 타입의 모임이므로 임베디드 타입 또한 값 타입이라고 부를 수 있다.
@Embeddable : 값 타입을 정의하는 곳에 표시
@Embedded : 값 타입을 사용하는 곳에 표시
✅ 임베디드 타입의 장점
- 높은 재사용성
- 높은 응집도
- 해당 값 타입만을 사용하는 의미 있는 메소드를 만들 수 있다.
- 값 타입을 소유한 엔티티에 생명주기를 의존한다.
✅ 임베디드 타입과 테이블 매핑
임베디드 타입도 어쨋든 엔티티의 값의 일부다. 즉, 임베디드 타입을 사용하든 그렇지 않든 테이블 매핑에서 바뀌는 것은 없다.
잘 설계한 ORM 애플리케이션은 매핑한 테이블 수 보다 클래스의 수가 더 많게 된다.
✅ 임베디드 타입과 연관관계
임베디드 타입은 임베디드 타입을 가질 수 있고, 엔티티 타입도 가질 수 있다.
그저 외래 키 값만 가지고 있으면 된다.
참고로 임베디드 타입의 값이 null이라면 매핑한 컬럼 값은 모두 null이 된다.
✅ 속성 재정의
한 엔티티에서 같은 값 타입을 사용하면 컬럼 명이 중복된다.
따라서 @AttributeOverrides, @AttributeOverride를 활용하여 컬럼 명 속성을 재정의할 수 있다.
📌 값 타입과 불변 객체
✅ 값 타입 공유 참조
임베디드 타입과 같은 값 타입을 여러 엔티티에서 공유하게 되면 위험 요소가 있다.
변경이 일어났을 때 의도치 않은 다른 엔티티에 영향력이 전파되어 Side Effect가 발생한다는 것이다.
✅ 값 타입 복사
값 타입의 실제 인스턴스 값을 공유하는 것은 위험하다.
따라서 인스턴스를 복사해서 사용한다.
✅ 객체 타입의 한계
값을 복사함으로써 공유 참조로 인한 부작용을 막을 수 있다.
문제는 값 타입이 아니라 객체 타입인데, 객체 타입은 참조 값을 직접 대입하는 것을 막을 방법이 없다.
즉, 객체의 공유 참조는 피할 수 없다는 것이다.
기본 타입의 값 복사는 아래와 같다.
int a = 10;
int b = a; // 기본 타입은 값을 복사
b = 4;
그리고 객체 타입의 복사는 아래와 같다.
Address a = new Address("Old");
Address b = a; // 객체 타입은 참조를 전달
b.setCity("New");
결국 객체의 공유 참조를 피할 수 없다.
✅ 불변 객체
애초에 객체 타입을 수정할 수 없게 만들어 부작용을 차단할 수 있다.
불변 객체란, 생성 시점 이후 절대로 값을 변경할 수 없는 객체이다.
생성자로만 값을 성정하고, 수정자 (Setter)를 만들지 않음으로서 값을 변경하지 못하도록 하는 것이다.
✅ 값 타입 비교
값 타입은 인스턴스가 달라도 그 안의 값이 같다면 같은 것으로 봐야 한다.
동일성(Identity) 비교 : 인스턴스의 참조 값을 비교한다. == 을 사용한다.
동등성(Equivalence) 비교 : 인스턴스의 값을 비교한다. equals()를 사용한다.
결국 값 타입은 동등성 비교(equals())를 해야 한다.
✅ 값 타입 컬렉션
값 타입을 하나 이상 저장할 때 사용한다.
@ElementCollection, @CollectionTable 어노테이션을 활용한다.
그러나 DB에는 컬렉션을 같은 테이블에 저장할 수 없으므로, 컬렉션을 저장하기 위한 별도의 테이블이 필요해진다.
다만, 값 타입 컬렉션에는 치명적인 문제가 있다.
값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장하는 번거로운 과정을 거친다.
이것은 성능적으로도 좋지 않기 때문에 사용하지 않는 것을 권장한다.
실무에서는 상황에 따라 값 타입 컬렉션 대신 일대다 관계를 활용하는 것을 고려한다.
일대다 관계를 위한 별도의 엔티티를 생성하고, 여기에 값 타입을 사용하는 것이다.
영속성 전이 + 고아 객체 제거를 활용하여 값 타입 컬렉션처럼 사용하자.
값 타입은 그냥 간단한 경우에만 사용하자.
'Backend > JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 11. 객체지향 쿼리 언어 2 (1) | 2024.01.05 |
---|---|
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 10. 객체 지향 쿼리 언어 1 (0) | 2024.01.05 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 8. 프록시와 연관관계 관리 (0) | 2024.01.05 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 7. 고급 매핑 (0) | 2024.01.04 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 6. 다양한 연관관계 매핑 (0) | 2024.01.04 |
개발자가 되고 싶어요.