본문 바로가기
스프링

@NoArgsConstructor(access = AccessLevel.PROTECTED) 쓰는 이유

by 순원이 2024. 4. 6.
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PostComment extends BaseTimeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id")
    private Post post;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_comment_id")
    private PostComment parentComment;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    public String content;

    @Builder
    public PostComment(Post post, User user, String content) {
        this.post = post;
        this.user = user;
        this.content = content;
    }
}

 

@NoArgsConstructor(access = AccessLevel.PROTECTED) 쓰면

Protected 기본생성자가 만들어집니다.

protected PostComment() {}

 

왜 접근 권한을 Public이 아닌 Protected로 하였을까?

 

JPA가 Proxy 객체를 생성할 때 기본생성자가 필요합니다. 그러나 저는 기본생성자로 엔티티를 생성할 일이 없습니다. builder를 통해서만 엔티티를 생성합니다. 무분별한 기본생성자 사용을 막기 위해 Protected로 제한하는 것입니다. 

 

 

왜 접근 권한을 Private이 아닌 Protected로 하였을까?


Entity의 Proxy 조회때문이다.

정확히는 엔티티의 연관 관계에서 지연 로딩의 경우에는 실제 엔티티가 아닌 프록시 객체를 통해서 조회를 한다.

프록시 객체를 사용하기 위해서 JPA 구현체는, 실제 엔티티의 기본 생성자를 통해 프록시 객체를 생성하는데, 이 때 접근 권한이 private이면 프록시 객체를 생성할 수 없는 것이다.

이 때 즉시로딩으로 구현하게 되거나 엔티티가 영속성 컨텐츠에 있을시, 접근 권한과 상관없이 프록시 객체가 아닌 실제 엔티티를 생성하므로 문제가 생기지 않는다