임베디드 타입은 언제 사용하나요 ?
엔티티 내부에 주소, 기간, 생성일/수정일 등 여러 필드가 하나의 논리적인 묶음으로 사용되는 경우가 존재한다. 예를 들어, Member 엔티티에 city, street, zipcode 등을 개별 필드로 나열하기보다 논리적으로 관련된 필드들을 하나의 값 타입 (Value Type) 객체로 묶어서 관리한다.
@Embeddable & @Embedded 사용법
1) @Embeddable
값 타입으로 사용될 클래스 (예를 들어, Address)에 붙여 JPA에게 '이 클래스는 엔티티에 내장될 수 있는 타입입니다.' 라고 알려준다.
특징
- 기본 생성자가 필수이다.
- 엔티티가 아니므로 `@Id` 가 없다.
2) @Embedded
`@Embeddable` 클래스를 사용하는 엔티티의 필드에 붙어 '이 필드에 임베디드 타입을 사용합니다.' 라고 명시한다. 일반적으로는 `@Embeddable` 만 있어도 작동하지만 명시적으로 붙여주는 것을 권장한다.
임베디드 타입을 사용하는 이유
단순히 코드를 묶는 것을 넘어, 객체 지향적인 설계의 이점을 가져온다.
1) 높은 응집도
관련 있는 필드들을 하나의 클래스로 묶어 관리하여 엔티티의 응집도를 높이고, 코드의 가독성을 향상시킨다.
2) 재사용성
여러 엔티티에서 공통으로 사용할 수 있다.
3) 의미 있는 메서드 추가
값 타입 자체에 해당 값과 관련된 비즈니스 로직 메서드를 추가할 수 있다.
주의사항
1) 값 타입의 불변성
값 타입은 엔티티처럼 식별자가 없고, 여러 곳에서 공유되면 부작용이 발생할 위험이 높다.
-> 임베디드 타입을 불변 객체(Immutable Object)로 설계해야 한다. Setter를 제거하고 생성자를 통해서만 값을 설정하고, 값을 변경해야 할 경우에는 기존 객체를 수정하는 대신, 새로운 객체를 생성하여 갈아끼우는 방식으로 사용한다.
2) 속성 재정의 : `@AttributeOverride`
하나의 엔티티에서 같은 임베디드 타입을 여러 필드로 사용해야 하는 경우에 db 칼럼명이 중복되는 문제가 발생한다.
-> `@AttributeOverride` 와 `@AttributeOverrides`를 사용하여 사용하는 쪽에서 db 칼럼명을 다르게 지정해줄 수 있다.
예제
`Address` 임베디드 타입과 이를 사용하는 `Member` 엔티티 코드이다.
@Embeddable
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Address {
private String city;
private String street;
private String zipcode;
@Builder
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
public String getFullAddress() {
return city + " " + street + " (" + zipcode + ")";
}
}
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@Embedded
private Address homeAddress;
}
'Spring' 카테고리의 다른 글
| [Spring] @RequestBody JSON 바인딩 원리 (0) | 2025.11.28 |
|---|---|
| [Spring] Spring AI와 LangChain4j 비교 (0) | 2025.11.24 |
| [Spring] Lombok 이해하기 - @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor (0) | 2025.11.04 |
| [Spring] 데이터 유효성 검증 (Validation) 이해하기 (0) | 2025.11.04 |
| [Spring] DTO 활용 패턴 - toEntity(), from() 정적 팩토리 메서드 (0) | 2025.10.13 |
