자바 스프링 환경에서 개발하게되면 습관적으로 Lombok을 주입받아 많이 사용하곤 한다.
그중에서 @Builder 어노테이션이 편한 사용성때문에 많이 쓰게되는데 오늘은 초기값을 설정했을 때 발생하는 오류를 공유하고자 한다.
@Builder
@Data
public class OrderListRequest {
private String market; // 마켓 아이디
private List<String> uuids; // 주문 UUID의 목록
private List<String> identifiers; // 주문 identifier의 목록
private OrderState state; // 주문 상태
private List<OrderState> states; // //미체결 주문(wait, watch)과 완료 주문(done, cancel)을 혼합하여 조회하실 수 없습니다.
private Integer page = 1;
private Integer limit = 100;
@JsonProperty("order_by")
private OrderByType orderBy = ASC;
}
이런 요청을 보낼 정보를 담는 OrderListRequest 클래스를 생성했고, 컴파일 시점에 아래와 같은 에러메시지가 발생한다.
warning: @Builder will ignore the initializing expression entirely.
If you want the initializing expression to serve as default,
add @Builder.Default. If it is not supposed to be settable during building,
make the field final.
private Integer page = 1;
warning: @Builder will ignore the initializing expression entirely.
If you want the initializing expression to serve as default,
add @Builder.Default. If it is not supposed to be settable during building,
make the field final.
private Integer limit = 100;
warning: @Builder will ignore the initializing expression entirely.
If you want the initializing expression to serve as default,
add @Builder.Default. If it is not supposed to be settable during building,
make the field final.
private OrderByType orderBy = ASC;
Lombok은 보통 런타임에서 에러가 발생하지 않고 컴파일 수준에서 에러를 뱉는다.
왜인지는 롬복 어노테이션을 열어보면 답을 알수 있다. 간단히 말하면 @Retension 어노테이션의 범위가 소스단에서만 영향을 받도록 해서 어느정도 컴파일이 되고난 후에는 런타임에러를 밷지는 않는다. 단지 NullPointerException을 뱉어서 디버깅이 어렵게 만들뿐...(@Builder 어노테이션을 붙인 후 클래스를 컴파일 했을때,, 런타임시에 결과적으로 초기값이 무시되는 것처럼 인스턴스화가 진행된다.)
암튼 클래스 변수에 초기값을 설정했고, @Builder 어노테이션을 활용하고 싶다면 2가지 방법이 있다.
1. 해당 warning 이 발생하는 필드에 @Builder.Default 어노테이션을 붙여준다.
2. 해당 warning이 발생하는 필드에 final 키워드를 붙여준다.
일단 둘다 결과는 동일하다. 클래스에 기재한 초기값이 클래스 인스턴스에 잘 들어있다. 하지만 차이는 final은 수정할 수 없을테고.. @Builder.Default를 써야 수정할 수 있는 변수로 적용되니.. 지저분하지만 일단 @Builder.Default 어노테이션을 활용하기로 결정했다!