[Spring] 빌더 패턴과 @Builder, @Builder와 생성자와의 관계

Euiyeon Park·2025년 2월 19일
0

Spring / SpringBoot

목록 보기
2/4
post-thumbnail

🍀 빌더 패턴(Builder Pattern)

  • 빌더 패턴은 객체의 생성 과정에서
    생성자의 매개변수가 많거나, 특정 필드만 선택적으로 초기화해야 할 때
    유용한 디자인 패턴

🤍 빌더 패턴을 사용하는 경우

  • 생성자의 매개변수가 많아 가독성이 떨어지는 경우
  • 필드 중 일부만 선택적으로 초기화하고 싶은 경우
  • 불변 객체를 만들고 싶은 경우

🍀 Lombok의 @Builder

  • Lombok의 @Builder는 빌더 패턴을 쉽게 사용할 수 있도록 해주는 어노테이션
  • 주로 DTO, Entity 클래스에서 자주 사용
  • @Builder 를 사용하는 이유는 빌더 패턴을 사용하는 경우와 같다.

🤍 @Builder를 사용하는 경우와 장점

1. DTO, Entity 클래스가 여러 필드를 가지는 경우
매개변수 순서를 헷갈리기 쉽고, 어떤 값이 어떤 필드에 해당하는지 한눈에 보기 어렵다.

  • 필드명을 직접 지정해 값을 설정하므로, 생성자 인수의 순서에 의존❌
  • 빌더를 통해 필드명을 명시적으로 작성하므로 가독성 향상
  1. 특정 필드만 초기화하고 싶은 경우
    필요한 필드만 초기화할 수 있어 유연한 객체 생성이 가능하다. - null을 명시적으로 사용❌
  • 필수 필드와 선택 필드가 섞인 객체를 생성할 때, 생성자 오버로딩이 많아질 수 있음
  • 생성자가 많아질수록 코드 관리가 복잡
  • 빌더를 통해 선택적으로 필드를 설정할 수 있어, 불필요한 생성자 오버로딩 제거
  1. Spring에서는 DTO를 불변 객체로 만들어 안전하게 다루는 것이 중요하다.
    @Builder를 활요하면 Setter를 만들지 않고도 값을 설정할 수 있어 불변성을 유지한다.
    final 키워드와 함께 사용해, 한 번 생성된 객체의 값이 변경되지 않도록 보장한다.
@Getter
@Builder
@ToString
public class PostCreate {
	
    @NotBlank(message = "title을 입력해주세요")
    private String title;
    
    @NotBlank(message = "content를 입력해주세요")
    private String content;
}
Post post = Post.builder()
		.title(postCreate.getTitle())
		.content(postCreate.getContent())
        .builder();

🍀 Entity와 @Builder

🤍 JPA 엔티티는 기본 생성자(@NoArgsConstructor)가 필요하다

  • JPA는 프록시(proxy) 기반으로 객체를 생성하기 때문에 기본 생성자가 필요.
  • 따라서, 엔티티에 @Builder를 적용할 경우 반드시 @NoArgsConstructor를 추가

🤍 @Builder와 생성자의 관계

-@Builder는 내부적으로 모든 필드를 매개변수로 받는 생성자 @AllArgsConstructor를 사용

  • 하지만 JPA는 기본 생성자를 필요로하므로, @NoArgsConstructor를 추가
  • 즉, JPA에서 @Builder를 사용하려면, 기본 생성자와 모든 필드를 받는 생성자를 함께 정의해야 함

🤍 @AllArgsConstructor를 별도로 선언할 필요가 있을까?

  • @Builder는 모든 필드를 포함하는 생성자를 자동으로 생성하기 때문에
    @AllArgsConstructor를 명시적으로 선언할 필요가 없다.
  • 하지만 특정 상황에서 @AllArgsConstructor를 추가로 선언해야 하는 경우가 있다.

🤍 @AllArgsConstructor를 별도로 선언해야 하는 경우

1. @Builder는 private 생성자를 생성한다.

  • 빌더 패턴은 내부적으로 private 생성자를 사용하여 객체를 생성한다.
    따라서 생성자를 직접 호출할 수 없다. - new로 객체 생성 불가❌
  • 그러나 특정 상황에서는 @AllArgsConstructor를 명시적으로 선언하여
    public 생성자도 제공하는 것이 필요할 수 있다.

2. JPA 엔티티에서 @AllArgsConstructor가 필요할 수도 있다.

  • JPA 엔티티에서는 @Builder만 사용하면 생성자가 private이므로 직접 객체 생성을 못 할 수도 있다.
  • 이 문제를 해결하려면 @AllArgsConstructor를 추가하여 public 생성자도 제공해야 한다.

🍀 DTO와 @Builder

  • DTO는 데이터베이스와 직접 연결되지 않는 단순 데이터 객체이므로,
    JPA처럼 기본 생성자를 강제할 필요가 없다.
  • 즉, @NoArgsConstructor 없이도 @Builder를 자유롭게 사용 가능하다.

🍀 @Builder의 위치 - 클래스 vs 생성자

🤍 클래스에 @Builder를 붙이는 경우

  • 클래스에 @Builder를 붙이면, 모든 필드를 대상으로 하는 빌더 생성
  • 모든 필드를 초기화해야 하는 경우 적합하다.

🤍 생성자에 @Builder를 붙이는 경우

  • 생성자에 @Builder를 붙이면, 해당 생성자의 파라미터를 기반으로 빌더 생성
  • 특정 필드만 포함하는 빌더 생성이 가능하다. - 필요한 필드만 빌더로 초기화
profile
"개발자는 해결사이자 발견자이다✨" - Michael C. Feathers

0개의 댓글