Spring | Builder 패턴

Wonhee 📘·2022년 6월 1일
0

Spring

목록 보기
4/6
post-thumbnail

객체를 생성하기 위해서는 생성자 패턴, 정적 메소드 패턴, 수정자 패턴, 빌더 패턴 등을 사용할 수 있습니다.
이중에서 빌더 패턴에 알아보려 합니다.
빌더패턴을 사용하는 것이 좋다고는 하지만 상황에 맞게 사용하는 것이 적합하다고 생각합니다.

📘 빌더 패턴(Builder Pattern)의 장점

  • 필요한 데이터만 설정할 수 있다.
  • 유연성을 확보할 수 있다.
  • 가독성을 높일 수 있다.
  • 변경 가능성을 최소화할 수 있다.

📃 필요한 데이터만 설정할 수 있다.

예를 들어 User 객체를 생성하는데 age라는 parameter가 필요 없는 상황이라고 가정한다면,
생성자나 정적 메소드를 이용하는 경우라면 우리는 age에 더미 값을 넣어주거나 age가 없는 생성자를 새로 만들어주어야 합니다.

// 1. 더미값을 넣어주는 방법
User user = new User("이름", 0, 180, 150)

// 2. 생성자 또는 정적 메소드를 추가하는 방법
@NoArgsConstructor 
@AllArgsConstructor 
public class User { 
    private String name;
    private int age;
    private int height;
    private int iq;

    public User (String name, int height, int iq) {
        this.name = name;
        this.height = height;
        this.iq = iq;
    }
    
    public static User of(String name, int height, int iq) {
        return new User(name, 0, 180, 150);
    }
    
}

이러한 작업이 한 두번이면 번거로워도 작업을 해줄 수 있다. 하지만 결국 요구사항은 계속 변하게 되어있고, 반복적인 변경을 필요로 하면서 시간 낭비로 이어진다. 하지만 빌더 패턴을 이용한다면, 이를 동적으로 처리할 수 있습니다.

User user = User.builder()
             .name("이름")
             .height(180)
             .iq(150).build();

그리고 이렇게 필요한 데이터만 설정할 수 있는 빌더의 장점은 생성자 또는 정적 메소드와 비교하여 테스트용 객체를 생성할 때 용이하게 해주고, 불필요한 코드의 양을 줄이는 등의 장점이 있습니다.

📃 유연성을 확보할 수 있다.

예를 들어 User 클래스에 몸무게를 나타내는 새로운 변수 weight를 추가해야 한다고 하자. 하지만 이미 다음과 같이 생성자로 객체를 만드는 코드가 있다고 하자.

// ASIS
User user = new User("망나니개발자", 28, 180, 150)

// TOBE
User user = new User("망나니개발자", 28, 180, 150, 75)

그러면 우리는 새롭게 추가되는 변수 때문에 기존의 코드를 수정해야 하는 상황에 직면하게 된다. 기존에 작성된 코드의 양이 방대하다면 감당하기 어려울 수 있다. 하지만 빌더 패턴을 이용하면 새로운 변수가 추가되는 등의 상황이 생겨도 기존의 코드에 영향을 주지 않을 수 있다.

📃 가독성을 높일 수 있다.

빌더 패턴을 사용하면 매개변수가 많아져도 가독성을 높일 수 있다. 생성자로 객체를 생성하는 경우에는 매개변수가 많아질수록 코드 리딩이 급격하게 떨어진다. 예를 들어 다음과 같은 코드가 있다고 하자.

User user = new User("이름", 28, 180, 150)

위와 같은 코드를 보면 28와 180 또는 150이 무엇을 의미하는지 바로 파악이 힘들고, 클래스 변수가 4개 이상만 되어도 코드를 읽기 힘들어진다. 하지만 다음과 같이 빌더 패턴을 적용하면 직관적으로 어떤 데이터에 어떤 값이 설정되는지 쉽게 파악하여 가독성을 높일 수 있다.

User user = User.builder()
             .name("망나니 개발자")
             .age(28)
             .height(180)
             .iq(150).build();

또한 매개변수의 순서와 상관없이 객체를 생성할 수 있습니다.

📃 변경 가능성을 최소화할 수 있음

많은 개발자들이 수정자 패턴(Setter)를 흔히 사용한다. 하지만 Setter를 구현한다는 것은 불필요하게 변경 가능성을 열어두는 것이다. 이는 유지보수 시에 값이 할당된 지점을 찾기 힘들게 만들며 불필요한 코드 리딩 등을 유발한다. 만약 값을 할당하는 시점이 객체의 생성뿐이라면 객체에 잘못된 값이 들어왔을 때 그 지점을 찾기 쉬우므로 유지보수성이 훨씬 높아질 것이다. 그렇기 때문에 클래스 변수는 변경 가능성을 최소화하는 것이 좋다.
변경 가능성을 최소화하는 가장 좋은 방법은 변수를 final로 선언함으로써 불변성을 확보하는 것이다. (불변성을 확보해야 하는 이유에 대해 이해가 부족하다면 이 포스팅을 참고해주세요)

위의 User 클래스를 다음과 같이 수정할 수 있다.

@Builder
@RequiredArgsConstructor
public class User {

    private final String name;
    private final int age;
    private final int height;
    private final int iq;

}

하지만 경우에 따라서 클래스 변수에 final을 붙일 수 없는 경우가 있을 수 있다. 이러한 경우라면 final이 없어도 Setter를 구현하지 않음으로써 동일한 효과를 얻을 수 있다. 중요한 것은 변경 가능성을 열어두지 않는 것인데, final로 강제할 수 있다면 가장 바람직하지만 final을 붙일 수 없는 경우라면 Setter를 넣어주지 않으면 된다.

@Builder
@AllArgsConstructor
public class User {

    private String name;
    private int age;
    private int height;
    private int iq;

}
profile
오늘 걷지 않으면 내일은 뛰어야한다 🚶‍♂️ 🏃‍♀️

0개의 댓글