티스토리 뷰
📗 내 코드
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder(access = AccessLevel.PRIVATE)
public class Book { ... }
Book 엔티티 코드를 살펴보자. 도서 관련 백엔드 서비스이므로 당연히 Book 엔티티는 존재한다.
여기서 살펴볼 것은
@NoArgsConstructor(access = AccessLevel.PROTECTED)
👆 이 부분이다.
왜 사용했나?
정말 솔직하게 말하면 이 프로젝트 이전 팀 프로젝트에서 팀원 분이 베이스 코드 작성 시에 위처럼 코드를 작성하셨다.
그 때는 내가 맡은 부분에만 정신이 팔려서 사실 저 코드 쓰임의 이유를 못 여쭤봤다.(내가 찾아봤어야 하는건데 말이다.)
그래서 좋은 게 좋은거지 라는 안일한 생각으로 버드북 프로젝트에 그대로 가져왔다.

그럼 왜 @NoArgsConstructor 어노테이션에 access 레벨을 proteced로 지정하는걸까?
@NoArgsConstructor
@NoArgsConstructor 어노테이션은 파라미터가 없는 디폴트 생성자를 생성하는 어노테이션이다.
즉, Book엔티티를 예시로 보면
public Book() {}
이 생성자를 알아서 만들어준다는 소리다.
JPA는 기본 스펙 상 기본 생성자를 요구한다. JPA는 리플렉션을 사용해서 내부적으로 엔티티를 생성하는데 이 때 동적으로 런타임 시점에 기본 생성자를 통해 클래스를 인스턴스화 한다.
즉, 직접 기본 생성자를 작성하든 어노테이션을 통해서 생성하든 해야한다는 소리다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
외부에서 무분별한 불완전한 객체 생성을 방지하기 위해 기본 생성자에 접근 제한을 건다.
그럼 일단 JPA를 사용하기 위해 기본 생성자가 필요하단 것은 이해했다.
그러면 왜 접근 제한을 두는걸까? 즉, AccessLevel을 왜 설정하는걸까?
외부에서 기본 생성자로 객체를 생성하는 것을 방지하기 위함이다.
기본 생성자 생성에 접근 제한을 걸지 않았을 때를 가정해보자
@Entity
@Getter
@NoArgsConstructor
public class Book { ... }
이렇게 되면 외부에서 기본 생성자를 통해 객체 생성이 자유로워진다.
그러면 아무런 필드 값을 가지지 못한 불완전한 Book 객체가 생성될 수 있고, 이는 비즈니스 로직이나 데이터베이스와의 상호작용에서 예외를 발생시킬 가능성이 높다.
또한, 완전한 객체를 만들기 위해서 setter를 함께 쓴다고 가정해보자.(위의 코드에서 @Setter 어노테이션을 추가했다고 가정한다.)
setter는 객체 생성 시 지양하는 방법이다. setXX()를 사용하면 어디든 객체의 값을 변경할 수 있다. 즉, 객체의 일관성을 유지하기가 어렵고 데이터베이스의 일관성 또한 깨지기 쉽다.
결국 기본 생성자에 접근 제한을 걸어서 외부에서 무분별한 불완전한 객체 생성을 방지하는 것이다.
access = AccessLevel.PROTECTED
접근 권한을 Protected로 설정하는 이유는 엔티티의 프록시 조회 때문이다.
위의 예시에서 접근 권한을 그냥 Public으로 해주면 안되는 이유를 살펴보았다.
그렇다면 왜 접근 권한이 Protected인가?
엔티티끼리 연관관계를 맺게되면 지연 로딩의 경우에 실제 엔티티가 아니라 프록시 객체를 조회한다.(프록시에 대해선 다음에 알아보자..)
암튼 JPA의 구현체는 실제 엔티티의 기본 생성자를 통해 프록시 객체를 생성한다.
이 때 접근 권한을 private으로 하면 프록시 객체를 생성할 수가 없다. 즉, 지연 로딩 시 값을 조회할 수가 없다.
결론은?
무분별한 객체 생성을 막고, 프록시 객체 생성을 통한 조회를 위해 기본 생성자 생성 @NoargsConstructor 어노테이션의 접근 제한은 Protected로 하자
고민할 지점을 알려주신 팀원 분께 감사드린다!
참고 자료
내가 @NoArgsConstructor (access = AccessLevel.PROTECTED)를 작성했던 이유
그 때 당시에는 Spring은 물론 Java에 대한 개념도 매우 약할 때라 지금도 약하지만레퍼런스의 코드를 가져다 사용하기에 급급했다.당시의 나는 해당 개념에 대한 정확한 이해보다는 기능 구현이
velog.io
https://erjuer.tistory.com/106
[JPA] Entity Class의 @NoargsConstructor (access = AccessLevel.PROTECTED)
실무에서 JPA를 활용하다보면 Entity 생성시 @NoargsConstructor (access = AccessLevel.PROTECTED) 이라는 Annotation을 붙여서 개발을 하게 된다. 이에 조금 더 정확히 이해하고자 이번 블로그 글로 언급하고자 한
erjuer.tistory.com
- Total
- Today
- Yesterday
- Java
- Thymeleaf
- springboot
- 유효성 검사
- id생성전략
- @NoArgsConstructor
- JPA
- null
- 일급컬렉션
- 동등성
- 오블완
- Spring
- 메인메소드
- 티스토리챌린지
- NPE
- uncheckedException
- upperBound
- 생성자
- ddl-auto
- checkedException
- 백준
- 이진탐색
- @Spring
- StreamAPI
- 자바
- @Value
- Optional
- @ConfigurationProperties
- lowerBound
- N+1문제
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |