스프링에서 엔티티를 생성했을 때 @NoArgsConstructor가 필수인 이유
엔티티를 다루다보면 생성자를 만들어야 할 때가 생기기 마련입니다.
그럴 때 코드 수를 줄이고, 개발자의 편의를 위해 Lombok 친구를 자주 쓰기 마련입니다.
보통 우리가 많이 쓰는 생성자 어노테이션은
- @AllArgsConstructor
- @RequiredArgsConstructor
- @NoArgsConstructor
정도일 것이라고 생각합니다.
1. Class 'SomeEntity' should have [public, protected] no-arg constructor
에러 위에 마우스 커서를 가만히 두고 있다 보면 no-args constructor가 없어서 에러가 나오는 것이라고 IDE가 친절하게 알려줍니다.
미리 오늘의 결론을 정리하자면
엔티티는 무조건 NoArgsConstructor를 가져야 합니다.
이제 그 이유를 알아봅시다.
2. 왜 다른 생성자가 있을 때만 이 에러가 발생할까?
2-1. 자바는 생성자가 없으면 자동으로 No-Args-Constructor를 생성한다.
- 위 예시에서 보이는 것 처럼, Test 클래스는 생성자가 없지만 new 호출이 가능합니다.
- 자바에서는 생성자가 없을 때 자동으로 No Args Constructor가 생성되기 때문입니다.
2-2. 생성자가 있으면 No-Args-Constructor는 자동으로 생성되지 않는다.
2-3. 따라서 엔티티에서 다른 생성자를 만들면, NoArgsConstructor를 직접 정의해야 한다.
- 다른 생성자가 있으면 NoArgsConstructor가 자동으로 생성되지 않기 때문에, 직접 정의해주지 않는 한 자동으로 생성되지 않기 때문에 에러가 발생했던 것입니다.
3. NoArgsConstructor는 왜 필요할까
이유는 Proxy 패턴 때문!
- Jpa에서는 자주 Lazy Loading을 통해서, 객체를 프록시 형태로 조회합니다.
3-1. 프록시가 적용되는 방식
- 엔티티를 상속하는 프록시 객체를 정의.
- 이 프록시 객체를 초기화하기 위해 부모 객체, 즉 엔티티의 NoArgsConstructor를 호출.
- 그래서 NoArgsConstructor가 필요한 것!!
3-2. NoArgsConstructor의 access level이 protected 이상이어야 하는 이유
-
위에서 설명한 것 처럼 자식 객체가 부모 객체의 생성자를 호출해야 하기 때문입니다.
-
private으로 설정된 경우, 자식 객체는 부모 객체의 생성자에 접근할 수 없기 때문에 에러가 발생합니다.
-
이에 대해 예시와 함께 굉장히 잘 정리된 블로그가 있어 공유합니다.
https://erjuer.tistory.com/106