java entity를 쓰다보면 Lombok annotation이 덕지덕지 붙게 된다.
요렇게 말이다. 👇🏻👇🏻
@AllArgsConstructor
@NoargsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class CartItem {
...
왜 annotation이 덕지덕지 붙게 되는건지, 왜 프로젝트마다 스타일이 다른건지
매번 까먹게 되어서 노션에 정리한걸 기록해보고자 한다.
Context
@Entity
Entity를 사용하려면 JPA Proxy 기능 때문에 매개변수가 없는 기본 생성자가 필요하다.
@Entity 어노테이션은 기본 생성자가 없는 경우, 알아서 기본 생성자를 만들어준다.
그래서 @NoArgsConstructor 어노테이션이 없어도 엔티티가 잘 돌아가는 경우가 있다.
@Builder
Lombok의 @Builder 어노테이션을 사용하려면, 클래스의 모든 속성을 매개변수로 받는 생성자가 필요하다.
@Builder 어노테이션을 사용하면, 내부적으로 알아서 모든 속성을 매개변수로 받는 생성자를 만들어준다.
그래서 일반 POJO 객체를 만들 때에는 @Builder 어노테이션 하나만 선언해도 된다 .
@Getter
@Builder
public class AddItemToCartCommand {
private final Long userId;
private final Long productId;
private final Integer quantity;
}
@AllArgsConstructor @NoArgsConstructor의 정체
entity, builder 모두 생성자를 자동으로 만들어준다고 했다. 그런데 왜 생성자를 만드는 어노테이션을 선언해줘야하는걸까?
그건 entity와 builder를 모두 사용하는 경우, 서로 생성자를 자동으로 만들어주려고 하기 때문이다.
entity는 builder에서 만든 생성자 때문에, 생성자가 이미 만들어진거로 판단한다.
반면, builder는 entity에서 만든 생성자 때문에, 생성자가 이미 만들어진거로 판단한다.
entity는 매개변수가 없는 생성자, builder는 모든 속성을 받는 매개변수가 있는 생성자를 필요로 한다.
그래서 서로 충돌하는 상황이 발생한거다.
결론
그래서!
entity에 builder 패턴을 사용하려면, @AllArgsConstructor @NoArgsConstructor을 붙여줘야한다.
자동으로 만들어주지마! 싸우지마! 내가 알아서 만들게! 전략이다.
번외 - NoargsConstructor에 access = AccessLevel.PROTECTED은 왜 붙이는거지?
오픈소스를 보다보면, NoargsConstructor에 접근 제어자를 걸어둔 경우가 있다. 접근 제어자가 추가된 이유는 다음과 같다.
JPA Proxy 때문에 어쩔 수 없이 매개변수가 없는 기본 생성자를 만들었는데, 이걸 어디선가 잘못사용하면 불완전한 객체가 만들어질 수 있다.
그래서 매개변수가 없는 기본 생성자를 다른 데에서 함부로 가져다 못쓰도록 막고 싶은 경우가 있다.
그러면 기본 생성자를 private으로 만들어야 할 것이다.
그런데 Entity에서는 public 혹은 protected으로 접근 권한을 설정하라고 가이드한다.
때문에.. public은 쫌 별로이니, 어쩔 수 없이 protected으로 선언하게 되는거다.
<끝>
JPA Proxy
https://cobbybb.tistory.com/14
https://pinokio0702.tistory.com/176
https://erjuer.tistory.com/105
'소프트웨어-이야기 > 프로그래밍 언어와 프레임워크' 카테고리의 다른 글
Enum 활용하기 (0) | 2023.01.07 |
---|---|
Lombok 기본 생성자와 Getter/Builder 어노테이션 (1) | 2022.11.12 |
[EDA] 이벤트 데이터 설계 (2) | 2022.07.16 |
[예외처리] notification pattern (0) | 2022.06.13 |
[Rule Engine] 비즈니스 규칙 엔진 (0) | 2022.06.11 |