@RequiredArgsConstructor란?
Lombok 라이브러리에서 제공하는 어노테이션 중 하나로, 필드에 초기값이 지정되지 않은 final 또는 @NonNull이 지정된 모든 필드에 대해 생성자를 자동으로 생성해주는 역할을 합니다. 이를 사용하면 반복적인 생성자 코드를 작성하지 않아도 되어 코드의 가독성을 높이고 유지보수를 용이하게 합니다.
최근 프로젝트를 하면서 이 @RequiredArgsConstructor를 사용하면서 에러가 발생한 적이 있어서 정리합니다.
실행을 하면 구동자체는 되는데 api를 호출할시 에러가 발생했습니다. 이유를 찾아보니 @RequiredArgsConstructor는 final일때만 생성자를 생성해준다고합니다.
에를 들어
public class Book {
private final String title;
private final String author;
}
가 있고
@RequiredArgsConstructor
를 사용하면 아래와 같이 자동으로 생성자를 만들어줍니다
public class Book {
@NonNull private final String title;
@NonNull private final String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
}
물론 이 부분은 자동으로 생성해주는것으로 이렇게 코드가 생긴다는 것은 아닙니다.
그러면 왜 final일때만 해주는 것 일까요?
final필드 또는 @NonNull 어노테이션이 지정된 필드에 대해서만 생성자를 자동으로 생성하는 이유는 다음 2가지 주요 원칙 때문입니다.
불변성(Immutability)
: final 키워드가 붙은 필드는 생성 시점에 한 번 초기화되고 이후에는 변경할 수 없습니다. 이렇게 만들어진 객체는 불변 객체로, 스레드 안전성(Thread-Safety)이 보장되며, 부작용(Side-Effect) 없이 사용할 수 있습니다. 이러한 불변성을 유지하기 위해서는 생성자에서 필수적으로 초기화가 이루어져야 합니다.2.객체의 완전성(Completeness)
: 생성자는 객체를 초기화하는 역할을 합니다. 즉, 생성자를 통해 객체가 완전한 상태(즉, 모든 필드가 적절한 값으로 초기화된 상태)가 되도록 해야 합니다. @NonNull 어노테이션이 붙은 필드는 Null을 허용하지 않으므로, 이 필드들도 생성자에서 반드시 초기화해야 합니다.
좀 더 자세하게 이야기해보겠습니다. final
필드에 대해서 생성자를 생성하는 이유는 Java 언어의 특성과 객체 지향 프로그래밍의 원칙에서 기인합니다.
Java의 final 필드 특성: Java에서 final 키워드가 붙은 필드는 한 번 초기화하면 그 이후에는 값을 변경할 수 없습니다. 따라서, final 필드는 객체가 생성될 때 반드시 초기화해야 합니다. 이는 생성자에서 이루어지며, 그렇지 않으면 컴파일 에러가 발생합니다.
불변 객체 (Immutable Object): final 키워드를 사용하면 불변 객체를 만들 수 있습니다. 불변 객체는 생성 후에 상태가 변하지 않기 때문에 여러 스레드에서 공유하여 사용해도 문제가 발생하지 않습니다. 이는 멀티스레드 환경에서의 프로그램의 안정성을 높이는 데 큰 장점입니다.
@NonNull 어노테이션을 사용하는 이유도 비슷합니다. @NonNull이 지정된 필드는 null 값을 허용하지 않습니다. 따라서 이런 필드는 객체가 생성될 때 반드시 초기화해야 하며, 그렇지 않으면 NullPointerException이 발생할 수 있습니다. Lombok의 @RequiredArgsConstructor는 이러한 필드에 대해 생성자를 만들어서 안전하게 초기화하도록 돕습니다.
따라서, @RequiredArgsConstructor는 객체의 불변성(Immutability)과 안전성(Safety)을 보장하고자 할 때 유용하게 사용됩니다. 이렇게 생성된 객체는 런타임 중에 상태가 변경되지 않으므로, 디버깅이 쉽고 코드를 이해하기도 더 쉽습니다.
사실 final이 아닌 필드에 대해서도 쓸 @RequiredArgsContructor를 쓸 수 있습니다. 그러나 final이나 @NonNull이 붙지 않은 필드는 생성자에서 반드시 초기화되어야하는 것은 아니기 때문에, @RequiredArgsContructor가 이러한 필드에 대해 생성자를 자동으로 만들어주지는 않습니다.
final이나 @NonNull이 붙지 않은 필드는 생성자에서 반드시 초기화되어야 하는 것은 아니기 때문에 -> 이거에 대해서 모를까봐 첨언을 하자면
Java에서 final 키워드가 붙은 필드는 반드시 초기화되어야합니다. final 필드는 한 번 초기화되면 그 이후에는 변경할 수 없습니다.
@NonNull 에노테이션도 비슷한 맥락입니다. 이 어노테이션은 해당필드가 null이 아니어야함을 의미합니다. 따라서 @NonNUll이 붙은 필드는 객체가 생성될 때 반드시 Null이 아닌 값으로 초기화 되어야합니다.
fianal
이나 @NonNull
이 붙지 않은 필드를 초기화하는 생성자를 만들여면 LomBok의 @AllargsContructor
를 사용할 수 있습니다.
이처럼 @RequiredArgsConstructor, @AllArgsConstructor 등의 Lombok 어노테이션은 편리하긴 하지만, 언제 어떻게 사용하는지를 잘 이해하고 사용해야 합니다. 필요한 필드만을 초기화하는 생성자를 만들고, 불필요한 상태 변경을 방지하려면 @RequiredArgsConstructor를 사용하는 것이 좋습니다. 반면, 모든 필드를 초기화하는 생성자를 만들려면 @AllArgsConstructor를 사용하면 됩니다.
좋은 글 감사합니다.!!!