📌 @Builder의 작동 과정 및 수행 방식
Lombok의 @Builder는 빌더 패턴을 자동으로 생성하여 객체를 보다 유연하게 생성할 수 있도록 해준다.
@Builder는 클래스에 붙일 수도 있고, 메서드에 붙일 수도 있으며, 각각의 수행 방식과 장단점이 다르다.
1. 클래스에 @Builder를 붙였을 때 수행 방식 및 연관 엔티티 초기화
작동 과정
1. Lombok이 정적 내부 클래스로 빌더 클래스를 생성한다.
2. 빌더 클래스는 해당 객체의 모든 필드를 포함한 Builder 메서드를 제공한다.
3. 객체를 생성할 때, build() 메서드를 호출하여 최종적으로 객체를 반환한다.
코드 예시
@Builder
@Getter
@AllArgsConstructor
public class Product {
private Long id;
private String name;
private int price;
private Category category; // 연관 관계 엔티티
}
엔티티 초기화 방식
• @Builder는 모든 필드를 포함하는 빌더 클래스를 생성하므로, 연관된 엔티티(Category 등)도 빌더를 통해 초기화해야 한다.
• 사용자가 명시적으로 연관 엔티티를 빌더에 포함하여 설정해야 한다.
객체 생성 예시
Category category = Category.builder().id(1L).name("전자제품").build();
Product product = Product.builder()
.id(100L)
.name("스마트폰")
.price(1000)
.category(category)
.build();
🔍장점
✔ 전체 필드를 설정 가능 → 객체를 완전한 형태로 생성할 수 있음.
✔ 불변 객체를 쉽게 생성 가능 → @AllArgsConstructor와 함께 사용하면 불변성을 유지할 수 있음.
✔ 필드가 많을 때 유용 → 생성자의 매개변수가 많아지는 문제를 방지.
단점
❌ 연관된 엔티티를 명시적으로 설정해야 함 → 실수로 초기화하지 않으면 null이 될 위험.
❌ 생성자 오버로딩이 어려움 → 필요한 경우 여러 개의 빌더를 정의해야 할 수도 있음.
2. 메서드에 @Builder를 붙였을 때 수행 방식 및 엔티티 초기화 방식
작동 과정
1. 해당 메서드의 매개변수를 기반으로 빌더 클래스를 생성한다.
2. 빌더를 호출하면 지정된 메서드가 실행되며, 특정 규칙에 따라 객체가 반환된다.
3. 클래스에 @Builder를 붙였을 때와 달리 특정 필드만 설정할 수 있는 맞춤형 빌더를 만들 수 있다.
코드 예시
@Getter
@AllArgsConstructor
public class Product {
private Long id;
private String name;
private int price;
private Category category;
@Builder
public static Product createProduct(String name, int price, Category category) {
return new Product(null, name, price, category);
}
}
엔티티 초기화 방식
• @Builder가 특정 메서드에만 적용되므로, 해당 메서드에서 객체를 초기화하는 방식으로 엔티티를 설정해야 한다.
• 연관 엔티티(Category)도 메서드의 인자로 전달해야 한다.
객체 생성 예시
Category category = Category.builder().id(1L).name("전자제품").build();
Product product = Product.createProduct()
.name("스마트폰")
.price(1000)
.category(category)
.build();
장점
✔ 여러 개의 빌더를 정의할 수 있음 → 특정한 객체 생성을 위한 다양한 방법 제공.
✔ 객체 생성 로직을 캡슐화 가능 → 특정한 초기화 로직을 내부에서 처리할 수 있음.
✔ 불필요한 필드를 설정하지 않아도 됨 → 꼭 필요한 필드만 빌더에서 제공할 수 있음.
단점
❌ 일반적인 빌더보다 활용성이 떨어질 수 있음 → 모든 필드를 빌더에서 설정할 수 있는 것은 아님.
❌ 여러 개의 빌더를 관리해야 할 수도 있음 → 객체 생성 방식이 많아질 경우 복잡해질 수 있음.
클래스 @Builder vs 메서드 @Builder 비교
구분클래스에 @Builder메서드에 @Builder
빌더 생성 방식 | 전체 필드를 포함한 빌더 클래스 생성 | 특정 메서드에 한정된 빌더 생성 |
초기화 방식 | 모든 필드를 포함하여 객체를 생성 | 특정 필드만 초기화 가능 |
연관 엔티티 초기화 | 명시적으로 모든 연관 엔티티를 빌더에 포함해야 함 | 메서드 내부에서 초기화 가능 |
유연성 | 필드가 많은 경우 유용 | 특정한 객체 생성 방법을 제어 가능 |
사용 편의성 | 일반적으로 사용하기 쉬움 | 특정 패턴을 따르는 경우 더 유용 |
객체 생성 방식 | 전체 필드 값을 채워야 함 | 필요한 값만 설정 가능 |
결론 및 선택 기준
사용할 상황추천 방식
모든 필드를 포함한 객체를 생성해야 할 때 | 클래스 @Builder |
특정한 초기화 로직을 포함하고 싶을 때 | 메서드 @Builder |
연관된 엔티티까지 함께 설정해야 할 때 | 클래스 @Builder |
특정 필드만 설정하도록 제한하고 싶을 때 | 메서드 @Builder |
• 클래스 단위 @Builder는 모든 필드를 포함하는 객체를 생성할 때 적합하며, 객체의 일관성을 유지하는 데 유용하다.
• 메서드 단위 @Builder는 특정 필드만 설정하고, 객체 생성 로직을 캡슐화하여 유연하게 관리할 때 더 적합하다.
• 연관 관계 엔티티를 초기화해야 할 경우, 클래스 단위 빌더는 직접 설정해야 하지만, 메서드 단위 빌더는 내부에서 초기화 가능하다는 차이점이 있다.
즉, 일반적인 DTO나 엔티티에서는 클래스 단위 @Builder가 편리하고, 비즈니스 로직이 포함된 객체 생성 시에는 메서드 단위 @Builder가 더 유용할 수 있다. 🚀
'Spring' 카테고리의 다른 글
[Spring AOP] JDK Dynaic Proxy에서 내부호출이 안되는 이유 (0) | 2025.03.11 |
---|---|
[Spring AOP] @Transactional의 Proxy 작동 방식 (0) | 2025.03.11 |
[Lombok] @Builder, DTO 접근제한자 적절한 설정 방법 (0) | 2025.03.11 |
[Lombok] @Builder를 클래스가 아닌 메서드에 적용하는 이유 (0) | 2025.03.11 |
[Spring/Serialization-Deserialization] Date, LocalDate, LocalDateTime 형변환 방법, 직렬화/역직렬화 문제 해결하기 (0) | 2025.03.07 |