2023.07.28

빌더 패턴

빌더 패턴이란, 복합 객체의 생성과 표현을 분리해서 동일한 생성 절차에서 다른 결과를 만들수 있는 패턴이다. 객체 생성을 라이브러리로 위임하거나 생성 시 변경이 없는 경우는 빌더를 사용할 필요가 없다. 변경이 없는 경우에는 정적 팩토리 메소드가 더 좋을 수 있다.


구현

생으로 구현하는 경우 getter, setter 등 보일러 플레이트 메서드가 많기 때문에 Lombok 을 이용한다. 롬복을 통해서 @Builder 어노테이션을 사용할 수 있다.

@Builder
@AllArgsConstructor
public class User {

	private String name;
	private int gender;
	private int age;

}

// 빌더를 이용해서...
User sara = User.builder().name("sara").age(23).build();

이런식으로 빌더를 이용해서 sara라는 객체를 생성할 수 있다. 필요하지 않은 값이거나 입력받지 않은 경우 작성하지 않으면 된다. 위에서는 gender 라는 값이 없을 것이다. (null)


빌더의 장점

새로운 속성 추가 시 기존 코드와 차이점은 아래와 같다. score 라는 값을 나중에 추가한다고 하자.

// - 빌더를 사용하지 않은 코드
User user1 = new User("sara", 1, 23);
// 모든 객체 생성 코드에서 score에 해당하는 값을 넣어주어야 한다.
User user1 = new User("sara", 1, 23, 100);


// - 빌더를 사용한 코드
User sara = User.builder().name("sara").age(23).build();
// 굳이 수정하지 않아도 된다. 필요한 코드에 .score() 를 추가하면 된다.
User sara = User.builder().name("sara").age(23).build();

위와 같이 코드 수정 면에서 유연하게 추가할 수 있다. 또 가독성 면에서도 장점이 있기 때문에 상황에 따라서 유용하게 사용하면 된다. alias 를 통해서 list 나 컬랙션 자료 구조를 전달해서 객체를 생성하는 방식도 있다.


주의 사항

Lombok을 이용하면 클래스의 모든 변수에 대한 생성자 메소드가 자동으로 구성된다. 하지만 때로는 값을 지정하는 것이 아니라 자동적으로 생성해주는 값이 있을 수 있다. (ex: id, create_at 등) 하지만 어노테이션 하나로 자동으로 id 를 지정할 수 있는 메소드가 열리기 때문에 잘못된 값이 지정될 위험이 있다. 그렇기 때문에 아래와 같이 작성하여서 이를 방지 할 수 있다.

@Builder
public User(String name, int age) {
	this.name = name;
	this.age = age;
	this.gender = 1; // gender는 매개 변수에 없기 대문에 .gender() 메소드로 접근되지 않는다.
}

// 가능
User sara = User.builder().name("sara").age(23).build();

// 실패
User sara = User.builder().name("sara").age(23).gender(1).build();


빌더 메소드 이름을 변경하는 경우 다음과 같이 작성할 수 있다.

@Builder(builderMethodName = "userSetUp")
User sara = User.userSetUp().name("sara").age(23).build();



주의 사항에도 작성되어있듯이 Lombok 은 자동으로 생성해주는 것이 많기 때문에 편리하지만, 그만큼 접근 제한이 필요하다. 아래 참고하면 좋은 포스트를 참고해서 빌더 패턴을 제대로 활용하면 좋을 것 같다. 빌더는 유지 보수면에서 좋지만 접근 제한 등 제약 사항을 설정해주어야 하기 때문에 오히려 구성 면에서 복잡해질 수 있다. 이런 패턴에 대해서 팀과 의논 후에 잘 사용하는 것이 좋을 것 같다.


참고하면 좋은 포스트

실무에서 Lombok 사용법 - Yun Blog 기술 블로그



Leave a comment