Backend/Java

[Java] 빌더 패턴

누구세연 2024. 11. 23. 19:20

자바에서 객체를 생성할 때 `new` 키워드를 사용한 생성자 호출 외에도 빌더 패턴을 활용하면 더 가독성 있고 유연한 코드를 작성할 수 있습니다. 특히, 필드가 많은 객체나 옵션이 다양한 경우 빌더 패턴은 매우 유용합니다.

 

이번 글에서는 빌더 메서드의 기본 개념, 장점, 실무 활용법을 정리하겠습니다! 👩🏻‍💻

 

빌더 패턴이란?

빌더 패턴은 복잡한 객체의 생성 과정을 단순화하고, 가독성과 유지보수성을 높이기 위해 고안된 디자인 패턴입니다.

 

기본 빌더 패턴 코드 예제

public class User {
    private final String name;
    private final int age;
    private final String email;

    // Builder 클래스
    public static class Builder {
        private String name;
        private int age;
        private String email;

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

        public Builder age(int age) {
            this.age = age;
            return this;
        }

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

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

    private User(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.email = builder.email;
    }
}

 

객체 생성 예제

User user = new User.Builder()
                  .name("rosy")
                  .age(20)
                  .email("rosy@example.com")
                  .build();

 

 

빌더 패턴의 장점

  1. 가독성
    • 빌더 메서드 이름으로 각 필드가 어떤 값인지 명확히 알 수 있습니다.
    • 메서드 체이닝으로 코드를 깔끔하게 작성할 수 있습니다.
  2. 유연성
    • 필수 값과 선택 값의 조합을 쉽게 처리할 수 있습니다.
    • 불변 객체를 생성할 수 있어 동시성 문제가 줄어듭니다.
  3. 가독성 높은 생성자 대체
    • 필드가 많은 생성자는 호출 시 인자의 의미를 혼동할 수 있지만, 빌더는 이를 명확히 합니다.

 

Lombok으로 빌더 패턴 간단히 구현하기

Lombok은 빌더 패턴을 손쉽게 구현할 수 있는 @Builder 어노테이션을 제공합니다.

 

Lombok @Builder 예제

import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class User {
    private String name;
    private int age;
    private String email;
}

 

객체 생성 예제

User user = User.builder()
                .name("rosy")
                .age(20)
                .email("rosy@example.com")
                .build();

System.out.println(user); // User(name=rosy, age=20, email=rosy@example.com)

장점

  • 코드 양이 크게 줄어들고 유지보수가 편리합니다.

주의점

  • 필수 필드를 명확히 하고 싶다면, @Builder.Default 또는 @SuperBuilder와 함께 사용을 고려해야 합니다.

 

실무에서의 빌더 패턴 활용 팁

  • 필수 필드 처리
    • Lombok @Builder는 필수 필드에 대해 별도 검증 로직이 필요합니다. 이를 위해 @NonNull 또는 별도 생성 메서드를 추가하세요.
  • 상속 구조에서의 빌더
    • 상속된 클래스에서도 빌더를 사용하려면 Lombok의 @SuperBuilder를 활용하세요.

@SuperBuilder 예제

import lombok.Getter;
import lombok.experimental.SuperBuilder;

@Getter
@SuperBuilder
public class Parent {
    private String parentField;
}

@Getter
@SuperBuilder
public class Child extends Parent {
    private String childField;
}

사용 예제

Child child = Child.builder()
                   .parentField("Parent")
                   .childField("Child")
                   .build();
  • DTO 변환 시 빌더 활용
    • 서비스 계층에서 DTO 생성 시 빌더를 활용하면 읽기 좋은 코드를 작성할 수 있습니다.
UserDto userDto = UserDto.builder()
                         .id(user.getId())
                         .name(user.getName())
                         .build();

 

 

 

💡 빌더 패턴은 복잡한 객체 생성을 단순화하며, 특히 코드의 가독성과 유지보수성을 크게 향상시킵니다.
Lombok을 활용하면 더 쉽고 빠르게 빌더를 구현할 수 있으니 실무에서 적극적으로 활용해 보세요!