@RequiredArgsConstructor

2023. 4. 17. 15:25Spring Boot/Annotations

1. 기본 개념: @RequiredArgsConstructor

@RequiredArgsConstructorLombok이 제공하는 어노테이션으로, 클래스에 있는 final 필드@NonNull로 표시된 필드를 위한 생성자를 자동으로 생성해 줍니다. 해당 필드들은 반드시 초기화되어야 하기 때문에, 생성자를 통해 의존성을 주입받거나 외부에서 값을 설정받는 경우에 유용합니다.

자동 생성되는 생성자

이 어노테이션이 적용된 클래스에는 다음과 같은 생성자가 자동으로 생성됩니다:

  • 클래스에 있는 모든 final 필드
  • @NonNull로 표시된 필드

이러한 필드들이 생성자의 파라미터로 추가되며, 생성자 내에서 필드 초기화가 자동으로 이루어집니다.

예시:

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;
    private String notificationMessage;

    // @RequiredArgsConstructor에 의해 다음과 같은 생성자가 자동 생성됩니다:
    // public UserService(UserRepository userRepository, EmailService emailService) {
    //     this.userRepository = userRepository;
    //     this.emailService = emailService;
    // }
}

위 예시에서, UserService 클래스에는 final로 선언된 userRepositoryemailService가 있습니다. @RequiredArgsConstructor는 이 두 필드를 파라미터로 받는 생성자를 자동으로 만들어 줍니다. notificationMessagefinal이 아니므로 생성자에서 제외됩니다.

2. @NonNull 필드 처리

@NonNull로 표시된 필드는 반드시 null이 아닌 값이 설정되어야 합니다. 이를 보장하기 위해, 해당 필드가 생성자의 파라미터로 포함되며, 생성자 내에서 null 체크가 자동으로 추가됩니다. 만약 null이 전달되면 NullPointerException이 발생하게 됩니다.

예시:

import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class AccountService {
    private final AccountRepository accountRepository;
    @NonNull private EmailService emailService;

    // 자동 생성된 생성자:
    // public AccountService(AccountRepository accountRepository, EmailService emailService) {
    //     if (emailService == null) {
    //         throw new NullPointerException("emailService is marked non-null but is null");
    //     }
    //     this.accountRepository = accountRepository;
    //     this.emailService = emailService;
    // }
}

3. staticName 속성: 정적 팩토리 메서드 생성

staticName 속성은 클래스에 정적 팩토리 메서드를 생성하기 위한 옵션입니다. 기본적으로 생성자는 new 키워드를 통해 호출되지만, 팩토리 메서드를 사용하면 객체 생성 방식을 보다 직관적이고 명확하게 표현할 수 있습니다.

@RequiredArgsConstructor(staticName = "of")와 같이 staticName 속성을 지정하면, 생성자 대신 정적 메서드를 호출하여 객체를 생성할 수 있습니다. 이 때, 메서드 이름은 of와 같이 지정한 이름으로 생성됩니다.

정적 팩토리 메서드 예시:

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor(staticName = "of")
public class User {
    private final String name;
    private final int age;
}

위 코드에서는 User 클래스에 대한 of 메서드가 생성되며, 이를 통해 객체를 생성할 수 있습니다.

사용 예:

public class Main {
    public static void main(String[] args) {
        // 정적 팩토리 메서드 of()를 통해 User 객체 생성
        User user = User.of("John", 25);
        System.out.println(user);
    }
}

이 예시에서 User.of("John", 25)을 호출하면, User 객체가 생성됩니다. 이렇게 정적 팩토리 메서드를 사용하면 객체 생성을 보다 직관적이고 의미 있는 이름으로 처리할 수 있습니다.

4. @AllArgsConstructor와의 차이점

Lombok의 다른 생성자 관련 어노테이션으로 @AllArgsConstructor가 있습니다. 이 어노테이션은 모든 필드를 파라미터로 받는 생성자를 자동으로 생성해 주지만, @RequiredArgsConstructorfinal 필드와 @NonNull 필드만을 생성자 파라미터로 포함합니다.

비교 예시:

import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;

@AllArgsConstructor
public class CompleteUser {
    private final String name;
    private int age;
}

// @AllArgsConstructor 생성자:
// public CompleteUser(String name, int age) {
//     this.name = name;
//     this.age = age;
// }

@RequiredArgsConstructor
public class PartialUser {
    private final String name;
    private int age;
}

// @RequiredArgsConstructor 생성자:
// public PartialUser(String name) {
//     this.name = name;
// }

5. 장점 및 사용 이유

  • 보일러플레이트 코드 제거: 필드 초기화를 위한 생성자를 수동으로 작성할 필요가 없어 코드가 깔끔해집니다.
  • 객체의 불변성: final 필드를 사용하는 생성자는 클래스가 불변(immutable) 객체로 설계되도록 돕습니다.
  • 명확한 의존성 주입: 클래스 생성 시 필요한 의존성을 명확히 드러내기 때문에, 의존성 주입 패턴에서도 매우 유용합니다.
  • 정적 팩토리 메서드 활용: staticName 속성을 통해 생성자보다 명확한 메서드 이름을 사용하여 객체 생성 방식을 좀 더 유연하고 직관적으로 할 수 있습니다.

종합 정리

  • @RequiredArgsConstructorfinal 또는 @NonNull 필드를 초기화하는 생성자를 자동으로 생성해 주는 Lombok 어노테이션입니다.
  • staticName 속성을 사용하면 정적 팩토리 메서드를 생성하여, 직접 생성자 호출 없이 메서드를 통해 객체를 생성할 수 있습니다.
  • 팩토리 메서드는 코드의 가독성과 객체 생성 방식을 명확히 해주는 장점이 있습니다.
  • @AllArgsConstructor와 달리, 필요한 필드만 포함된 생성자를 만들 수 있어 객체의 의존성 관리를 더 명확하게 할 수 있습니다.

'Spring Boot > Annotations' 카테고리의 다른 글

@SessionAttributes / @ModelAttribute 란?  (0) 2023.08.08
@Builder  (0) 2023.04.17