1. JPA 스펙 준수
- JPA는 프록시 객체 생성 및 리플렉션을 통해 엔티티를 인스턴스화할 때,
파라미터가 없는 기본 생성자가 반드시 필요
- 이 생성자는 public 또는 protected 접근제어자여야 한다.
2. 불필요한 객체 생성을 방지
- 기본 생성자를 public으로 열어두면, 외부에서 불완전한 상태의 엔티티가 무분별하게 생성될 수 있다.
- 하지만 protected로 제한하면, JPA 내부(프록시, 리플렉션)에서는 접근 가능하고,
외부 코드에서는 접근이 불가능해 의도치 않은 객체 생성을 막을 수 있다.
3. 엔티티 일관성 보장
- 엔티티는 보통 필수 필드가 모두 채워진 상태로만 생성되어야 함.
- 생성자를 protected로 하면, 정상적인 비즈니스 로직(예: 빌더, 팩토리 메서드, 명시적 생성자 등)으로만 객체를 만들 수 있게 강제할 수 있다.
4. AccessLevel.PRIVATE가 아닌 이유
- JPA는 프록시 객체를 만들 때 리플렉션으로 기본 생성자에 접근하는데,
이때 private이면 접근이 불가능해 런타임 에러가 발생한다.
- JPA 스펙상 public 또는 protected만 허용되므로, AccessLevel.PROTECTED가 표준!
정리
- JPA 엔티티에는 반드시 public 또는 protected 기본 생성자가 필요하다.
- 외부에서 무분별하게 객체가 생성되는 것을 막기 위해
@NoArgsConstructor(access = AccessLevel.PROTECTED)를 사용.
"Entity 클래스는 매개변수가 없는 생성자의 접근 레벨이 public 또는 protected로 해야 한다.
기본 생성자의 접근 제어를 Protected로 설정해놓게 되면 무분별한 객체 생성에 대해 한 번 더 체크할 수 있는 수단이 된다."