2025. 4. 22. 22:31ㆍBack-End/JAVA
Java로 코드를 작성하다 보면 종종 이런 선언을 보게 된다.
@RequiredArgsConstructor
public class Worker {
private final String id;
private final List<Info> paths;
private final LogicService logicService;
}
처음 보면 궁금해진다.
왜 final을 붙이고, @RequiredArgsConstructor를 쓰는 걸까?
이번 글에서는 이 조합이 가지는 의미와 철학을 정리해보려 한다.
final 필드란?
자바에서 final은 딱 한 번만 값을 할당할 수 있다는 의미를 가진다.
즉, 아래 코드는 컴파일되지 않는다.
public class Example {
private final String name;
public Example() {
// 컴파일 에러: final 필드는 생성자에서 반드시 초기화되어야 함
}
}
하지만 아래처럼 생성자에서 초기화하면 문제 없다.
public class Example {
private final String name;
public Example(String name) {
this.name = name;
}
}
요약하면 final 필드는 생성자에서 반드시 초기화해야 하며, 그 이후에는 절대 바꿀 수 없다.
불변성(Immutable)이 왜 중요할까?
- 객체가 생성된 이후 상태가 바뀌지 않으므로, 안정성이 높아진다.
- 동시성 환경에서 스레드 간 경쟁이 줄어든다.
- 읽기 쉽고, 예측 가능한 코드가 된다.
즉, 설계가 명확해진다. 생성자에서만 모든 상태가 결정되기 때문에 객체는 더 이상 변하지 않는다.
그렇다면 @RequiredArgsConstructor는?
Lombok에서 제공하는 @RequiredArgsConstructor는 말 그대로
"필수 생성자"를 자동으로 만들어주는 어노테이션이다.
@RequiredArgsConstructor
public class FileWatchWorker {
private final String id;
private final LogicService logicService;
}
이렇게 선언하면, Lombok은 다음과 같은 생성자를 자동으로 생성해준다.
public FileWatchWorker(String id, LogicService logicService) {
this.id = id;
this.logicService = logicService;
}
중요한 점은, final 또는 @NonNull이 붙은 필드만을 대상으로 생성자를 만든다는 점이다.
이건 단순한 문법적 편의가 아니라, 객체 설계 철학과도 맞닿아 있다.
그럼 @AllArgsConstructor와 차이는?
@NoArgsConstructor | 모든 필드를 무시하고 기본 생성자만 생성 |
@AllArgsConstructor | 모든 필드를 포함한 생성자 생성 |
@RequiredArgsConstructor | final 또는 @NonNull 필드만 포함 |
즉, @RequiredArgsConstructor는 필수값만 받는 생성자를 만들어주며,
이는 객체 생성 시점에 꼭 필요한 값만을 명시적으로 드러낼 수 있다는 점에서 의미가 깊다..
왜 이렇게 쓸까?
이 조합은 객체지향에서 아주 중요한 개념인 불변성과 의존성 명확화를 담고 있다.
- 불변성: final로 인해 객체가 한 번 만들어지면 상태가 바뀌지 않는다.
- 의존성 주입의 명시성: 생성자를 통해 어떤 의존성이 필요한지 명확하게 드러난다.
- 자동 생성자의 편의성: Lombok이 반복적인 코드를 대신 작성해준다.
결론
final 필드 + @RequiredArgsConstructor 조합은
단순한 문법 편의가 아니라, "이 객체는 생성 시점에 모든 상태가 결정되고, 이후엔 절대 바뀌지 않는 객체다" 라는 철학을 코드로 표현하는 방법이다.
참고로
Spring Boot에서는 이런 방식으로 서비스나 컴포넌트 객체를 선언하는 것도 일반적이다.
@RequiredArgsConstructor
@Service
public class ArticleService {
private final ArticleRepository articleRepository;
}
이렇게 하면, 의존성이 명확하고 안전한 구조의 컴포넌트를 구성할 수 있다.
'Back-End > JAVA' 카테고리의 다른 글
@RequiredArgsConstructor와 @Builder와의 차이 (0) | 2025.04.22 |
---|---|
자바 enum, 상수가 전부가 아니었다 (0) | 2025.04.17 |
Runnable이란? 비동기 워커 설계에서 마주친 첫 스레드 인터페이스 (0) | 2025.03.23 |
메서드 참조 :: (0) | 2024.11.22 |
Stream() (0) | 2024.11.22 |