본문 바로가기

Develop/Java

Lombok

728x90

롬복

자바의 보일러 플레이트 코드를 줄여주는 라이브러리

롬복의 기능들

  • @Getter, @Setter : Java Bean 규약에 있는 getter, setter를 자동 생성
  • @ToString : Object에 기본 구현된 ToString 대신 객체의 데이터를 보여주는 ToString을 자동 생성
  • @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor : 객체 생성자를 자동으로 생성
  • @Data : Getter, Setter, ToString, Equals, hashCode 등 다양한 기능을 모두 제공
  • @Builder : 빌더 패턴을 자동 생성하여 제공
  • @Slf4j : 해당 클래스의 logger를 자동 생성
  • @UtilityClass : static method만 제공하는 유틸리티 성격의 클래스들의 생성자를 private로 만들어서 객체 생성을 할 수 없도록 함

@AllAgrsConstructor vs @RequiredArgsConstructor

일반적인 객체에서 변수 순서대로 파라미터로 받는 생성자를 생성하는 것은 @AllArgsConstructor 이고

@RequiredArgsConstructor는 final 이나 @Notnull 키워드가 붙은 필드에 대해서만 생성자를 만들어 줍니다.

@RequiredArgsConstructor는 단순히 생성자를 만들어주는것만으로 끝나지 않고 인젝션도 가능합니다.

즉 @RequiredArgsConstruntor를 사용하면 생성자를 활용한 주입도 가능합니다. (@Autowired 어노테이션 생략이 가능합니다.)

 

@AllAgrsConstructor, @RequiredArgsConstructor 단점

@AllArgsConstructor와 @RequiredArgsConstructor는 심각한 버그를 발생할 수 있어서 사용 시에 주의하거나,

아예 사용을 권하지 않는 경우도 있습니다.

@AllArgsConstructor
public class Order {
    private int cancelAmount;
    private int orderAmount;
}


// 취소수량 4개, 주문수량 5개
Order order = new Order(4, 5);

그런데 만약 프로그래머가 orderAmount와 cancelAmount가 선언된 순서가 마음에 들지 않아 아래처럼 바꾸게 된다면?

@AllArgsConstructor
public class Order {
    private int orderAmount;
    private int cancelAmount;
}

이 경우, IDE가 제공해주는 리팩토링은 작동하지 않게 되며 lombok도 변화를 알아채지 못합니다.

심지어 orderAmount, cancelAmount는 int라는 동일한 type을 갖고 있어 더욱 버그를 잡기 어렵습니다.

 

그래서 기존에 사용하던 new Order(4, 5)로 객체의 인스턴스를 만들어도 아무 에러없이 잘 동작할테지만

실제로 입력되는 값은 취소수량과 주문수량이 뒤바뀌어 들어가는 심각한 비즈니스 로직 에러를 발생시킵니다.

 

이 때문에 @AllArgsConstructor와 @RequiredArgsConstructor의 사용을 금지하는 것이 좋다는 주장도 있고

 

그 대신, IDE 자동 생성 기능 등으로 아래처럼 생성자를 직접 만들고

필요한 경우에는 직접 만든 생성자에 @Builder 어노테이션을 붙이는 것을 권장하기도 합니다.

이 방법은 파라미터 순서가 아닌 이름으로 값을 설정하기 때문에 리팩토링에 유연하게 대응이 가능합니다.

public class Order {
    private int cancelAmount;
    private int orderAmount;
    
    @Builder
    private Order(int cancelAmount, int orderAmount) {
        this.cancelAmount = cancelAmount;
        this.orderAmount = orderAmount;
    }
}


// field 순서를 변경해도 에러가 없다.
Order order = Order.builder().orderAmount(5).cancelAmount(4).build();