공부
# @Entity에서 @builder 사용법
KimMZ
2025. 2. 21. 14:09
1. JPA에서 사용할 수 있는 Entity와 builder에 대해 검색을 통한 학습 개념 정리와 실제 프로젝트에 적용하는 과정을 작성합니다.
@Entity
JPA가 관리하는 객체, 클래스 위에 어노테이션을 붙인다.
2. Entity 클래스에서 작성하는 어노테이션이 여러가지 있습니다.
- @Getter
- @Setter
- 객체 내 필드가 무분별하게 변경될 수 있다. → 언제 어디서 객체 변경이 됐는지 알 수 없어 객체의 안전성을 보장받기 어렵습니다.
- @NoArgsConstructor
- 기본 생성자의 접근 제어자가 불명확하다. → access=AccessLevel.PROTECTED 속성을 통해 매개변수가 없는 의미없는 객체 생성을 막아주는 역할입니다.
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {
private UUID orderId;
private UUID userId;
}
Order order = new Order(); // 오류 발생
- @AllArgsConstructor
- 모든 인스턴스멤버를 가지고 있는 생성자를 만듭니다.
- @Builder → 의미있는 객체, 객체의 안정성을 보장받으면서 확장성 있게 사용할 수 있습니다.
- 어노테이션 생성 방법
- 클래스 @Builder 붙이기
- @NoArgsConstructor 와 같이 사용하면 오류가 발생합니다. NoArgsConstructor는 객체의 값이 없어도 생성 가능한데, builder는 필드 중 사용하고 싶은 인스턴스멤버변수만 사용할 수 있기 때문입니다.
- 생성자 @Builder 붙이기
- @Builder는 빌더 클래스와 각 필드를 초기화 하는 생성자를 만듭니다. 이 때, @AllArgsConstructor를 같이 사용한다면 컴파일러의 혼동이 발생 할 수 있습니다.
- 생성자는 인스턴스 멤버의 선언 순서에 따라 생성자 입력값 순서도 달라지는 문제가 발생합니다.
- 빌더 패턴 적용하여 객체 생성 및 사용
- 모든 필드를 인자값으로 하는 생성자를 자동으로 만듭니다.
- 클래스 @Builder 붙이기
- 어노테이션 생성 방법
더보기
@Builder
public class Order {
private UUID orderId;
private UUID userId;
}
// @Builder의 역할은 아래 클래스의 동작을 뜻한다.
public class Order {
private UUID orderId;
private UUID userId;
Order(UUID orderId, UUID userId) {
this.orderId = orderId;
this.userId = userId;
}
public static Order.OrderBuilder builder() {
return new Order.OrderBuilder();
}
public static class OrderBuilder {
private UUID orderId;
private UUID userId;
OrderBuilder() {
}
public Order.OrderBuilder orderId(UUID orderId) {
this.orderId = orderId;
return this;
}
public Order.OrderBuilder userId(UUID userId) {
this.userId = userId;
return this;
}
public Order build() {
return new Order(this.orderId, this.userId);
}
public String toString() {
return "Order.OrderBuilder(orderId=" + this.orderId + ", userId=" + this.userId + ")";
}
}
}
3. 실전 - 프로젝트 적용
Entity 객체에서 만들어진 데이터를 layer 간에 이동할 때, 따로 requestDto 또는 responseDto를 만들어서 구현을 합니다.
이 때, dto의 매개변수 인자가 많을 경우 모든 인자를 가지는 생성자를 사용할 경우, 타입에 맞는 순서를 맞추고 필요없는 값이라도 넣어줘야하는 번거러움을 @builder 로 해결할 수 있었습니다.
필요한 인자만 객체를 초기화 하여 사용할 수 있고 객체의 데이터가 무작위로 변경되는 것을 미리 방지할 수 있는 장점이 있습니다. 또한, 코드 리뷰할 때 한 번에 코드를 파악하기 용이합니다.
Order order = Order.builder()
.orderId(requestDto.getOrderId())
.build();
팀프로젝트를 진행하면서 API 기능에서 데이터를 layer 간 주고 받을 때,
dto 객체 전달하는데 setter 보다 builder 를 이용할 수 있도록 리팩토링 하려고 한다.
※ 번외
- @Entity에서 @Column 속성에서 name, insertable, updatable, table 을 제외한 나머지 속성들은 DDL 생성 기능을 사용할 때만 사용되는 속성들이다.
- nullable 경우, null 허용 여부 설정으로 java 기본 타입(int, long)은 null 값 입력이 불가능하므로 false 설정으로 DB 컬럼에 Not Null 제약 조건을 지정하거나 직접 DB 컬럼에 Not Null 제약 조건을 추가한다.