Tech/Spring | Spring Boot

[Lombok][Java] @Builder 에 대해 알아보자 (Builder Pattern)

싱브이 2024. 9. 12. 13:13
728x90
반응형

스프링 프로젝트에서 entity, DTO 객체에 값을 넣을 때 @Builder를 사용하는데, 무의식적으로 사용하고 있다는 생각이 들어 한번 정리해두면 좋을 것 같았다!

 

객체 생성을 위해서 생성자 패턴, 자바 빈 패턴(Getter/Setter), 빌더 패턴 등을 사용할 수 있는데 왜 빌더 패턴을 사용해야하는지 한번 보자!

 


1. 생성자 패턴

 

객체 생성을 위해 생성자를 사용하는 것이다. 간단한 객체 생성에 효과적이지만, 생성자 매개변수가 많아지면 가독성 제로다.

public class User {
    private String name;
    private String email;
    private String password;

    public User(String name, String email, String password) {
        this.name = name;
        this.email = email;
        this.password = password;
    }
}
User user = new User("John", "john@example.com", "password");

 

 

2. 자바 빈 패턴 (Getter/Setter)

 

기본 생성자와 getter/setter 메서드를 이용하는 패턴이다. 객체의 상태를 설정하고 읽는데 유용하지만, 필드가 많은 객체라면 번거롭다.

public class User {
    private String name;
    private String email;
    private String password;

    // 기본 생성자
    public User() {}

    // getter와 setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
}
User user = new User();
user.setName("John");
user.setEmail("john@example.com");
user.setPassword("password");
  • @Getter, @Setter을 사용할 수 있다. (기본 생성자는 직접 추가해야한다.)
  • @Data를 사용할 수 있다. (@Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor 포함)

 

3. 빌더 패턴

 

객체를 단계별로 생성할 수 있다. 필드가 많은 객체를 생성할 때 유용하다!

public class User {
    private String name;
    private String email;
    private String password;

    // 기본 생성자
    private User(UserBuilder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.password = builder.password;
    }

    // Getter 메서드
    public String getName() { return name; }
    public String getEmail() { return email; }
    public String getPassword() { return password; }

    // UserBuilder 클래스
    public static class UserBuilder {
        private String name;
        private String email;
        private String password;

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

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

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

        public User build() {
            return new User(this);
        }
    }
}
User user = User.builder()
    .name("John")
    .email("john@example.com")
    .password("password")
    .build();
  • @Builder 을 사용할 수 있다.

@Builder

 

아무튼 쉽게 말해서 @Builder는 Builder Pattern을 사용할 수 있게 해주는 어노테이션이다.

위의 코드를 아래와 같이 줄일 수 있다. (편-안)

 

@Builder
public class User {
    private String name;
    private String email;
    private String password;
}
User user = User.builder()
    .name("John")
    .email("john@example.com")
    .password("password")
    .build();

 

 


(예제)

 

내가 프로젝트에서 @Builder를 적용한 부분은 Address-Member의 @ManyToOne 관계에서 사용했다.

회원(Member)은 여러 배송지를 선택할 수 있기 때문에 여러 개의 Address를 가질 수 있다. 

회원과 주소 엔티티에 필드가 꽤 있기 때문에 @Builder로 가독성을 높이고자 했고,

 @ManyToOne의 관계를 가지기 때문에 Address 객체 생성 후 Member와의 연결이 필요했다 !

 

. . .
// 새로운 Member 객체 생성
    Member member = Member.builder()
            .username(userFormDto.getUsername())
            .email(userFormDto.getEmail())
            .password(passwordEncoder.encode(userFormDto.getPassword()))
            .nickname(userFormDto.getNickname())
            .phoneNumber(userFormDto.getPhoneNumber())
            .role(Role.USER)
            .isSocial(false)
            .build();

    // Address 객체 생성 후 Member와 연결
    Address address = Address.builder()
            .street(userFormDto.getAddress())
            .city(userFormDto.getDetailAddress())
            .state(userFormDto.getExtraAddress())
            .zipCode(userFormDto.getPostcode())
            .member(member) // Address와 Member의 연결 설정
            .build();

    // Member 객체에 Address 추가
    member.getAddress().add(address);
. . .

 

 

728x90
반응형