본문 바로가기
Category/Note

[Lombok] 유연한 객체 생성 방법 @Builder

by Corinee 2024. 12. 31.
728x90
반응형

빌더(Builder) 생성은 객체를 생성할 때 유연하고 가독성 높은 방법을 제공하는 디자인 패턴입니다. 특히 많은 필드를 가진 객체를 생성하거나 선택적으로 일부 필드만 설정해야 하는 경우 유용합니다.

Lombok에서 제공하는 @Builder 어노테이션을 사용하면, 빌더 패턴을 쉽게 구현할 수 있습니다.

 

빌더 패턴의 필요성

  1. 가독성 향상
    생성자의 매개변수가 많거나 순서를 헷갈릴 수 있을 때, 필드 이름을 명시적으로 사용해 객체를 생성합니다.
  2. 유연한 객체 생성
    선택적으로 필요한 필드만 설정해 객체를 생성할 수 있습니다.
  3. 불변성 유지
    생성 후에는 객체를 수정할 수 없도록 할 때 유용합니다.

예제: Lombok의 @Builder

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Long id;
    private String username;
    private String email;
    private String password;
}

객체 생성 방식 비교:

1. 생성자 사용

  • 단점: 필드의 의미를 코드에서 바로 이해하기 어렵고, 매개변수 순서를 실수할 가능성이 있음.
User user = new User(1L, "john_doe", "john@example.com", "password123");

 

2. 빌더 사용

  • 장점:
    • 필드 이름이 명시되어 가독성이 높음.
    • 순서를 헷갈릴 염려가 없음.
    • 필요한 필드만 설정 가능.
User user = User.builder()
                .id(1L)
                .username("john_doe")
                .email("john@example.com")
                .password("password123")
                .build();

빌더 사용의 주요 장점

1. 필드 선택적 초기화
객체를 생성할 때 모든 필드를 초기화하지 않아도 됩니다.

User user = User.builder()
                .username("john_doe")
                .email("john@example.com")
                .build();
  • ex) password는 설정하지 않아도 기본값(null)로 생성됩니다.

2. 읽기 쉬운 코드
빌더 메서드가 각 필드 이름과 동일하기 때문에, 생성자 매개변수에 비해 읽기 쉽습니다.

 

3. 불변 객체 생성
객체 생성 후에는 필드를 변경하지 못하도록 설계할 수 있습니다(필드에 final 추가).

 

Lombok 없이 빌더 패턴 구현

만약 Lombok을 사용하지 않는다면, 아래와 같이 구현해야 합니다.

public class User {
    private final Long id;
    private final String username;
    private final String email;
    private final String password;

    private User(Builder builder) {
        this.id = builder.id;
        this.username = builder.username;
        this.email = builder.email;
        this.password = builder.password;
    }

    public static class Builder {
        private Long id;
        private String username;
        private String email;
        private String password;

        public Builder id(Long id) {
            this.id = id;
            return this;
        }

        public Builder username(String username) {
            this.username = username;
            return this;
        }

        public Builder email(String email) {
            this.email = email;
            return this;
        }

        public Builder password(String password) {
            this.password = password;
            return this;
        }

        public User build() {
            return new User(this);
        }
    }
}
 

객체 생성:

User user = new User.Builder()
                    .id(1L)
                    .username("john_doe")
                    .email("john@example.com")
                    .password("password123")
                    .build();

 

빌더 생성의 활용 사례

  • DTO 클래스
    클라이언트와 데이터 교환 시 데이터를 안전하고 명확하게 전달.
  • 복잡한 객체 생성
    필드가 많거나, 생성자 오버로드가 많아지기 쉬운 경우 빌더 패턴으로 단순화.
  • 테스트 코드
    객체를 쉽게 조합하여 테스트 데이터 생성.

 

정리

@Builder를 사용하면 객체 생성 코드의 가독성과 유지보수성을 높일 수 있습니다. 특히 필드가 많은 객체를 유연하게 생성하거나, 생성자 사용이 어렵고 혼란스러운 경우에 매우 유용합니다.