땡글이LAB

[Lombok] @NoArgsConstructor / @RequiredArgsConstructor / @AllArgsConstructor 의 차이 본문

Framework & Library/Spring & SpringBoot

[Lombok] @NoArgsConstructor / @RequiredArgsConstructor / @AllArgsConstructor 의 차이

땡글이B 2022. 8. 23. 21:27

스프링 & 스프링부트는 많은 개발자들이 오래전부터 이용한 프레임워크이고, 대부분의 프로젝트에서 롬복 라이브러리를 사용해서 많은 개발자들이 단순 노동을 대신해서 효율적으로 코드를 짜고 있다. 

 즉, 스프링 & 스프링부트로 개발한다면, 자주 사용되는 롬복 라이브러리에 대해서도 잘 이해해둘 필요가 있다. 최근 개발자들은 매번 스프링 빈들간에 의존성 주입을 해주거나 특정 Class의 생성자를 만드는 것을 단순 노동이라 여겨 위의 3가지 어노테이션을 잘 활용해서 중복되는 코드를 작성하는 것을 지양하고 있다. 

 이제 본론으로 들어가서, 각 어노테이션이 의미하는 바를 알아보자. 

 

@NoArgsConstructor 의미

 스프링에서 사용되는 대부분의 어노테이션은 해당 어노테이션이 동작하는 것을 잘 표현하는 어노테이션 이름을 가진다. 이름에서 알 수 있듯이, 이 어노테이션은 파라미터가 없는 생성자를 만들어준다. 코드로 설명해보겠다.

@Getter
@NoArgsConstructor
public class TestData {
    private String data;
}
@SpringBootTest
public class TestDataTest {
    @Test
    public void NoArgsConstructorTest() {
        TestData testData = new TestData();
        System.out.println(testData.getData());
    }
}

 결과는 다음과 같다. 테스트 코드에서 알 수 있듯이 NoArgsConstructor 어노테이션이 있다면, 파라미터가 없어도 생성자가 알아서 생기는 것이다. 즉, 위에서 @NoArgsConstructor가 있는 것은 아래와 같은 파라미터 없는 생성자가 생기는 것이다.

@Getter
public class TestData {
    private String data;

    public TestData() {}
}

@NoArgsConstructor를 사용할 때 주의해야할 점

  • 클래스 내 필드 중 final로 생성되어 있는 경우에는 필드를 초기화 할 수 없기 때문에, 생성자를 만들 수 없고 에러가 발생한다.
    • 이 때는 @NoArgsConstructor(force = true) 옵션을 이용해서 final 필드를 0, false, null 등으로 초기화를 강제로 시켜서 생성자를 만들 수 있습니다.
  • @NonNull 같이 필드에 제약조건이 설정되어 있는 경우, 생성자 내 null-check 로직이 생성되지 않습니다.
    • 후에 초기화를 진행하기 전까지 null-check 로직이 발생하지 않는 점을 염두하고 코드를 개발해야 합니다.

 

@AllArgsConstructor 의미

 해당 어노테이션이 있으면, 클래스 내 존재하는 모든 필드에 대한 생성자를 자동으로 생성해준다. 변수를 파라미터로 가지는 생성자를 생성하는 것이다. 또한, 필드 중에서 @NonNull 어노테이션이 적혀있다면 생성자 내에서 null-check 로직을 자동적으로 생성해준다.

 

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class TestData {
    @NonNull
    private String name;
    private String email;
    private String phoneNumber;
    private String description;

}

정상적으로 동작하는 코드

    @Test
    public void AllArgsConstructorTest() {
        TestData testData = new TestData("손흥민", "aaa@naver.com", "010-1111-1111", "축구 잘해요!");
        System.out.println(testData.getName());
        System.out.println(testData.getEmail());
        System.out.println(testData.getPhoneNumber());
        System.out.println(testData.getDescription());
    }

 

비정상적으로 동작하는 코드 

    @Test
    public void AllArgsConstructorTestNullCheck() {
        TestData testData = new TestData(null, "aaa@naver.com", "010-1111-1111", "축구 잘해요!");
        System.out.println(testData.getName());
        System.out.println(testData.getEmail());
        System.out.println(testData.getPhoneNumber());
        System.out.println(testData.getDescription());
    }

 

@RequiredArgsConstructor 의미

 이 어노테이션은 아직 초기화되지 않은 모든 final 필드, @NonNull이 마크돼있는 모든 필드들에 대한 생성자를 자동으로 생성해준다. 즉 이름에서 알 수 있듯이, 필요한 생성자를 자동으로 생성해주는 어노테이션이다.

 

 @NonNull로 마크 돼있는 필드들은 null-check가 추가적으로 생성되며, @NonNull이 마크되어 있지만, 파라미터에서 null값이 들어온다면 생성자에서 NullPointerException이 발생한다. 파라미터의 순서는 클래스에 있는 필드 순서에 맞춰서 생성된다. 코드로 예시를 들어보겠습니다.

@Getter
@RequiredArgsConstructor
@AllArgsConstructor
public class TestData {
    @NonNull
    private String name;

    private String email;
    private String phoneNumber;
    private String description;

    private final String rData1;
    private final String rData2;
    private final String rData3 = "pre-initialized";

}
    @Test
    public void RequiredArgsConstructorTest() {
        /**
         * 초기화 되지 않은 final 필드와 NonNull 어노테이션이 붙어 있는 필드에 대한 생성자를 만들어준다.
         */
        TestData testData = new TestData("name", "rd1", "rd2");

        System.out.println(testData.getName());
        System.out.println(testData.getRData1());
        System.out.println(testData.getRData2());

    }

 위의 결과를 보면 알 수 있듯이, 이미 초기화돼있는 필드에 대한 생성자가 생기는 것이 아니라, 초기화되지 않은 final 필드와 @NonNull 어노테이션이 붙어있는 필드에 대한 생성자가 생기게 된다.

 

Conclusion

 스프링 & 스프링부트를 사용해서 개발할 때, 해당 어노테이션에 대해서 자세히 알아야 왜 @RequiredArgsConstructor 어노테이션을 붙였을 때 의존성 주입이 되는지 혹은 @NoArgsConstructor 와 @AllArgsConstructor를 도메인 클래스나 DTO 클래스에서 어떻게 사용할지에 대한 고민을 해결해줄 수 있을 것이다.

 

 

References

 

 

Comments