**@NoArgsConstructor(access = PROTECTED)**를 사용하는 이유는 주로 객체 생성에 관한 제어를 위해 사용됩니다. 이 어노테이션은 해당 클래스의 파라미터가 없는 protected 접근 제한자를 가진 생성자를 생성하도록 지시합니다. 이렇게 생성된 생성자는 클래스 외부에서 직접적으로는 호출할 수 없지만, 하위 클래스에서는 호출할 수 있습니다.
Java 클래스에는 생성자(Constructor)라는 특별한 메서드가 있습니다. 생성자는 객체를 생성할 때 호출되며, 객체의 초기화 작업을 수행합니다. 클래스 내부의 필드를 초기화하거나, 초기화 블록을 실행하거나, 다른 객체와의 연결 등을 설정하는 등의 작업을 수행합니다.
그런데 때때로 모든 필드를 직접 설정하는 생성자를 사용하는 대신, 특정한 필드를 초기화하거나 복잡한 초기화 로직을 가진 생성자를 생성하고자 할 수 있습니다. 이때 @NoArgsConstructor(access = PROTECTED) 어노테이션을 사용합니다.
보호된(protected) 생성자란, 같은 패키지 내부의 클래스와 해당 클래스를 상속한 하위 클래스에서만 호출할 수 있는 생성자를 의미합니다. 외부에서는 직접 호출할 수 없습니다.
여기서 두 가지 상황을 생각해보겠습니다.
ORM을 사용하는 경우: 주로 객체 지향 프로그래밍에서는 클래스 간의 상속 관계를 설정할 수 있습니다. 그리고 데이터베이스 테이블과 객체 사이에 매핑을 하는 ORM 프레임워크를 사용하는 경우, 이런 상속 구조가 관계를 복잡하게 만들 수 있습니다.
상속 관계가 복잡해지면서 초기화 작업 역시 복잡해질 수 있습니다. 이런 경우에 **@NoArgsConstructor(access = PROTECTED)**를 사용하여 하위 클래스에서 부모 클래스의 초기화 작업을 수행하거나, 부모 클래스에 정의된 protected 생성자를 호출하여 필요한 초기화를 할 수 있습니다. 이렇게 함으로써 초기화 작업을 중복으로 작성하지 않으면서도 객체의 무결성을 유지할 수 있습니다.
불변 객체 유지: 불변 객체(Immutable Object)는 한 번 생성된 후에는 내부 상태가 변경되지 않는 객체를 의미합니다. 불변 객체는 다양한 멀티스레드 환경에서 안정성을 보장하고 예측 가능한 동작을 제공할 수 있습니다.
이런 불변 객체를 만들 때 **@NoArgsConstructor(access = PROTECTED)**를 사용하여, 외부에서 객체를 직접 생성하지 못하도록 합니다. 이렇게 함으로써 객체 내부 상태가 생성 시점 이후 변경되지 않도록 보장할 수 있습니다.
요약하면, **@NoArgsConstructor(access = PROTECTED)**는 주로 객체의 초기화와 무결성 유지를 위해 사용되며, 주로 ORM과 상속 관계에서 유용하게 쓰입니다. 이렇게 함으로써 객체의 생성과 관련된 복잡한 로직을 효과적으로 관리하고 객체의 무결성과 예측 가능한 동작을 유지할 수 있습니다.