✏️Lombok @Builder 간단 정리

케이·2022년 8월 21일
0

학습기록

목록 보기
4/5
post-thumbnail

Lombok엔 유용한 어노테이션들이 정말 많지만 우리는 흔히 보일러플레이트라고 불리는 코드를 줄이기 위해 롬복의 @Builder 를 사용할 수 있다.
들어가기에 앞서 Builder 패턴은 무엇일까?

Builder pattern

빌더패턴은 디자인 패턴중의 하나로 생성자에 매개변수가 많을 때 사용하면 유용하다.

아래와 같은 형식으로 빌더를 작성할 수 있는데 롬복의 @Builder 를 사용하면 아래 코드로 작성한 것과 같은 기능을 사용할 수 있다.

public class Student {
		
		//필수 파라미터
		private int id;
		private String name;

		//선택 파라미터
		private String address;

		public Student(Builder builder) {
			this.id = builder.id;
			this.name = builder.name;
			this.address = builder.address;
		}

//빌더 클래스
		public static class Builder {

			//필수 파라미터
			private int id;
			private String name;

			//선택 파라미터
			private String address;

			public Builder(int id, String name) {
					this.id = id;
					this.name = name;
			}
			
			public Builder setAddress(String address) {
					this.address = address;
					return this;
		  }

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

@Builder 사용하기

@Builder 는 클래스 위에 선언하는 방법, 생성자에 선언하는 방법이 있다.

사실 나는 클래스 위에 선언하는 방법만 알고 사용하고 있었는데 코드스쿼드 과정 중에 리뷰어가 클래스 위에 선언하는 방법 말고도 생성자 위에 선언하는 방법이 있다고 귀띔 해주셔서 알게 되었다.

클래스 위에@Builder 선언하기

먼저 @Builder를 클래스 위에 선언하게 되면 아래와 같다.

@Builder
class Student {

		private int id;
		private String name;
		private String address;

		.. 중략
}

If a class is annotated, then a package-private constructor is generated with all fields as arguments (as if @AllArgsConstructor(access = AccessLevel.PACKAGE)
is present on the class), and it is as if this constructor has been annotated with @Builder
instead.

공식 문서에서 나와있듯이 클래스에 선언시 모든 파라미터를 받는 생성자가 자동으로 생성되고..

모든 매개변수가 생성자의 파라미터로 들어가게 되어 객체 생성 시 받지 않아야 할 파라미터들도 빌더에 노출이 된다. 이런 문제점을 해결하기 위해 생성자 위에 @Builder를 선언할 수 있다.

생성자 위에 @Builder 선언하기

class Student {

		private int id;
		private String name;
		private String address;

		@Builder
        public Student(String name, String address) {
        this.name = name;
        this.address = address;
        }
        
        ...중략
}

The effect of @Builder is that an inner class is generated named TBuilder, with a private constructor. Instances of TBuilder are made with the method named builder() which is also generated for you in the class itself (not in the builder class).

생성자 위에 빌더를 선언하게 되면 내부 빌더 클래스를 사용하게 된다.

클래스 위에 선언했을 때와 다르게 객체 생성 시 받지 않아야 할 파라미터들은 빌더에 노출 되지 않고 원하는 값에만 Builder 패턴을 적용할 수 있다.

만약 요구되는 필드를 특정화할 필요가 있을 때에는 builderMethodName을 사용해 빌더에 이름을 부여하고 그에 따른 책임을 부여할 수 있다. 또한 그 필수 인자값도 명확하게 할 수 있다.
예시)

public class Refund {
   private Long id;
   private Account account;
   private CreditCard creditCard;
   private Order order;

   @Builder(builderMethodName = "of", builderClassName = "of")
   private Refund(Account account, CreditCard creditCard, Order order) {
       this.account = account;
       this.creditCard = creditCard;
       this.order = order;
   }

   // 계좌 기반 환불
   @Builder(builderClassName = "byAccountBuilder", builderMethodName = "byAccountBuilder")
   public static Refund byAccount(Account account, Order order) {
       Assert.notNull(account, "account must not be null");
       Assert.notNull(order, "order must not be null");

       return Refund.of().account(account).order(order).build();
   }

   // 신용카드 환불
   @Builder(builderClassName = "byCreditBuilder", builderMethodName = "byCreditBuilder")
   public static Refund byCredit(CreditCard creditCard, Order order) {
       Assert.notNull(creditCard, "creditCard must not be null");
       Assert.notNull(order, "order must not be null");

       return Refund.of().creditCard(creditCard).order(order).build();
   }
}

또한 @NonNull 어노테이션을 사용해서 필드 존재여부를 확실하게 표시할 수 있다.

느낀 점

평소 무지성으로 썼을 때보다는 조금 더 builder와 친해졌다는 생각이 들었다. 하지만 내용이 깊어질 수록 잘 이해가 가지 않는 부분도 많아서 계획 했던 것 만큼은 정리를 하지 못했다. 꾸준히 살펴보고 학습해야겠다.

참고

https://www.baeldung.com/lombok-builder
https://projectlombok.org/api/lombok/Builder
https://github.com/cheese10yun/blog-sample/tree/master/lombok
https://projectlombok.org/features/Builder

profile
삽질하며 깨닫고 배웁니다. (a.k.a 프로삽질러) + 이 구역의 회고왕

0개의 댓글