[Spring] @NoArgsConstructor

차_현·2023년 7월 31일
1

@NoArgsConstructor가 필요할까?


생성자와 기본 생성자의 역할

클래스에 생성자를 정의하지 않으면, 자바는 기본 생성자를 자동으로 만듭니다. 하지만 만약에 다른 생성자를 정의하게 되면, 기본 생성자는 자동으로 만들어지지 않습니다.

예시 1:

public class AA{
    private String ss;
}

class BB{
    void function() {
        AA a = new AA();
    }
}

위의 코드는 오류가 나지 않는다. 자동으로 기본 생성자를 만들어주기 때문에
하지만 아래 코드는 생성자 AA(String ss)가 정의되어 있기 때문에,
기본 생성자는 자동으로 만들어지지 않는다.

그래서,아래 코드처럼 new AA( ), 기본 생성자를 호출하려고 하면 오류가 발생함.

public class AA{
    private String ss;
    public AA(String ss){
        this.ss=ss;
    }
}

class BB{
    void function() {
        AA a = new AA();     // 이 부분은 오류를 발생시킵니다!
    }
}

왜 @NoArgsConstructor가 필요할까? (feat. JPA...)

  • JPA에서는 '지연 로딩'(Lazy loading) 때문에, Proxy 패턴을 사용함
    • Proxy 객체는 실제 엔티티 객체를 상속받아서 만들어지는데, 이때 기본생성자를 필요로 한다. 따라서 기본 생성자가 없으면 Proxy 객체를 생성할 수 없어서 지연 로딩이 불가능함
  • JPA는 기본생성자를 이용해서 객체를 생성하고 데이터를 넣는다. 클래스에 다른 생성자가 정의되어 있으면, 기본 생성자는 자동으로 생성되지 않기 때문에 이때 '@NoArgsConstructor'를 사용하여 기본 생성자를 추가하면, JPA와 호환성을 보장할 수 있음
  • @NoArgsConstructor를 사용하면 기본 생성자를 직접 작성하지 않아도 되기 때문에 편리함

(추가)NoArgsConsturctor의 access level이 protected이어야 하는 이유?

당연한 얘기지만, 객체 지향 프로그래밍에서 객체의 상태(state)는 그 객체의 필드(field)에 의해 결정되고, 객체의 행동(behavior)은 그 객체의 메서드(method)에 의해 결정된다. 객체를 생성하려면 생성자(constructor)가 필요하고 객체가 생성될 때 생성자는 호출되며 객체의 초기화를 수행한다.

Java에서 클래스에 생성자를 정의하지 않으면, 컴파일러는 기본 생성자를 자동으로 생성하는데, 기본 생성자는 매개변수가 없는 생성자를 의미한다. 이 기본 생성자는 보통 객체의 초기화 된 필드를 기본값으로 초기화하는 작업을 수행합니다.

하지만, 클래스에 매개변수가 있는 생성자를 정의하면, 기본 생성자는 자동으로 생성되지 않는다. 이럴 때는 직접 기본 생성자를 정의해야 합니다.

Java Persistence API(JPA)는 자바의 ORM(Object-Relational Mapping) 기술로, 객체 지향 프로그래밍과 관계형 데이터베이스의 데이터를 매핑하는 역할을 한다. JPA를 사용하면 객체를 데이터베이스에 저장하거나, 데이터베이스의 데이터를 객체로 조회할 수 있다.

JPA는 엔티티 객체를 생성할 때 리플렉션(reflection)기술을 사용한다. 리플렉션은 실행 시간에 클래스의 정보를 접근하거나 수정할 수 있는 자바의 기능이다. JPA는 리플렉션을 사용하여 엔티티 클래스의 기본 생성자를 호출하고, 엔티티 객체를 생성할 수 있다.

하지만 기본생성자가 private으로 되어 있으면, 리플렉션을 통해 호출할 수 없다. 왜냐하면 private는 해당 클래스 내에서만 접근이 가능하기 때문이다.

그렇기 때문에, 엔티티 클래스의 기본 생성자는 protected 이상의 접근 제어자를 가져야 한다. protected는 동일 패키지 내의 클래스나 다른 패키지의 해당 클래스를 상속받는 자식 클래스에서 접근이 가능하기 때문에, JPA는 protected로 선언된 기본 생성자를 가진 엔티티 클래스의 인스턴스를 생성할 수 있다.

JPA는 프록시(proxy)기법을 사용한다. 프록시는 실제 객체를 대신해서 다른 객체에 접근하는 객체이다. JPA는 프록시를 사용하여 엔티티 객체를 지연 로딩(lazy loading)하거나, 다른 특별한 동작을 수행할 수 있다. 이 경우에도 엔티티 클래스의 기본 생성자가 필요합니다.

1개의 댓글

comment-user-thumbnail
2023년 7월 31일

정보 감사합니다.

답글 달기