본문 바로가기
나의 공부

디자인패턴-빌더 패턴(Builder)

by 이숴 2023. 3. 23.
반응형

객체(엔티티)를 초기화할땐 여러가지 방법이 존재합니다.

 

생성자 패턴, 정적 메소드 패턴, 수정자 패턴, 빌더 패턴 을 사용해 객체를 생성하는데요.

 

저는 보통 다양한 방법 중에서도 직관적이고, 변경 가능성을 최소화하는 빌더 패턴을 많이 채용해서 객체를 생성하곤 합니다. 

그래서 도대체 빌더 패턴이 무엇인지, 그리고 객체를 생성할때는 빌더 패턴을 사용해서 작성해야하는 이유를 함께 알아보겠습니다.

 

빌더 패턴??

빌더 패턴 클래스 다이어그램

정보처리기사-수제비에는 빌더패턴에 대해 이렇게 적혀있습니다.

- 복잡한 인스턴스를 조립하여 만드는 구조로, 복합 객체를 생성할 때 객체를 생성하는 방법(과정)과 객체를 구현(표현)하는 방법을 분리함으로써 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있는 디자인 패턴

- 생성과 표기를 분리해서 복잡한 객체를 생성

빌더 패턴은 보통 객체를 생성할 때 생성자를 사용할때 발생할 수 있는 문제를 개선하기 위해 고안되었다고 합니다.

 

생성 예시

기본 생성자 예시

자바코드로 예시를 들어보도록 하겠습니다. 

어떠한 객체는 인원의 정보로 이름, 나이, 주소를 저장합니다.

public class Member {
    String name;
    Long age;
    String address;
}

 

저(필자)라는 객체가 존재한다고 했을때, 일반적인 생성자로는 어떻게 초기화를 할까요? 아래와 같이 진행됩니다.

```Member

    public Member(String name, Long age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

```Main
	Member member = new Member("수호", 25L, "서울시");

이렇게 구성이 되면 무슨 오류가 발생할까요??


객체의 인자들의 현재 순번은 name, age, address 순입니다.

그러나 사용자가 age, name, address 순이거나 age ddress, name 순으로 작성을 잘못하는 경우,

 

같은 변수형이어서 오류 자체를 찾을 수 없는 경우


현재는 코드가 짧아서 빠르게 오류지점을 찾을 수 있겠지만, 실무같이 코드의 양이 어마무시한 상황에서는 그마저도 쉽지 않습니다.

 

이제 빌더 패턴 구현 방식을 살펴보겠습니다.

 

빌더 패턴 적용 예시

public class MemberBuilder {

    private String name;
    private Long age;
    private String address;

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

    public MemberBuilder setAge(Long age) {
        this.age = age;
        return this;
    }

    public MemberBuilder setAddress(String address) {
        this.address = address;
        return this;
    }

    public Member build() {
        return new Member(name, age, address);
    }
}

빌더 패턴을 적용하게되면 코드는 살짝 다르게 구성됩니다. Member객체 이외에 Builder를 진행할 객체가 따로 필요하구요. 입력받은 값들을 Member 객체로 생성해주는 build 메소드 또한 필요합니다.

 

이 객체를 가지고 새로운 Member 객체를 생성해보겠습니다.

Member member = new MemberBuilder()
            .setName("수호")
            .setAge(26L)
            .setAddress("서울시")
            .build();

아까의 객체와 무슨점이 다를까요? 보기만 했을때 매우 높은 가독성을 가지고 있지 않나요??

 

맞습니다. 빌더 패턴을 이용하면 우린 객체에 넘길 인자를 보다 가독성있는 코드로 보여주면서 생성할 수 있게되고, 객체를 생성한다는 점은 같지만 인자들이 Member 객체에 먼저 생성되기보다는 빌더 객체에서 인자들을 받은 뒤에 생성 객체에 전달한다는 점입니다.

 

그리고 영역이 지정되어있다보니, Member 객체의 필요한 데이터를 위치에 맞게 잘들어가고 어떻게 넣어야하는지 바로 알 수 있습니다.

 

이외에도 큰 장점이 하나 있는데,

Member 객체에 현재에는 name, age, address 인자만 존재하지만, 이후에 Member의 키, 몸무게가 추가된다고 생각해봅시다. 그럴때마다 이미 생성자가 초기화가 되어있다면 새롭게 추가되는 인자 때문에 기존의 코드를 수정해야하는 상황이 발생할 수도 있어 번거로운 작업이 추가될 수도있습니다. 하지만 빌더 패턴이 적용된 객체에서는 유연하게 set과 인자를 추가만 하면 손쉽게 변경할 수 있다는 점에서 유연성을 확보하고 있다고 볼 수 있습니다.

물론 현재 빌더객체에서는 저희도 인자를 추가해야하긴 하지만요.

(이것은 마지막 Spring @Builder에서 다시 얘기하겠습니다.)

 

Lombok에서 지원하는 빌더 어노테이션?

현재 제가 사용중인 언어-프레임워크에서는 Lombok 플러그인에서 @Builder라는 어노테이션을 지원해줍니다. 이 어노테이션이 붙어있는 객체에서는 따로 빌더 객체를 만들지 않아도 자동으로 빌더객체를 생성해서 생성자를 호출해주기 때문에 @Builder 어노테이션이 붙어있다면 해당 객체는 바로 builder를 호출해서 사용하시면 됩니다.

 

예시

```Member

    @Builder
    public class Member {

        private String name;
        private Long age;
        private String address;
    }


```Main

    Member member = Member.builder()
                .name("수호")
                .age(25L)
                .address("서울시")
                .build();

이 어노테이션을 사용한다면, 이전에 얘기했던 유연성 장점은 우리가 따로 새로이 인자의 set, builder를 생성하지 않아도 @Builder 어노테이션이 붙어진 객체의 인자들을 @Builder 어노테이션을 확인하면서 빌더 객체를 만들때 프로그램이 알아서 생성해주기 때문에 손쉽게 수정할 수 있게됩니다.

 

결론

따라서 객체를 생성할때는 빌더패턴의 장점을 가지고 작성해보는게 좋지 않을까..하고 생각만 해보기에는 좋은 장점을 가지고 있기 때문에, 조금더 빌더 패턴이 무엇인지 확인해보시고 빌더 패턴을 적용해서 객체의 생성자를 구현해보시는 걸 추천드립니다.

반응형

댓글