@AllArgsConstructor, @RequiredArgsConstructor 사용 주의

이수형·2022년 9월 2일
0

@AllArgsConstructor, @RequiredArgsConstructor 사용 주의

@AllArgsConstructor
public class User {
   private String nickName;
   private String name;
}

위의 코드를 보면 @AllArgsConstructor 를 선언하게 되면
자동으로 nickName 과 name 을 받는 생성자가 만들어집니다.

보통 인스턴스를 생성할 때 아래와 같이 만듭니다.

User user = new User("Hyuk", "진혁");
여기서 개발자가 리펙토링을 하면서 nickName 과 name 의 위치를 바꿔준다고 가정합니다.

@AllArgsConstructor
public class User {
   private String name;
   private String nickName;
}

name과 nickName 의 위치가 바뀌게 되면 @AllArgsConstructor 에서 생성되는 파라미터의 순서도 뒤바뀌게 됩니다. IDE 에서는 이 부분에 대해 리펙토링을 해주지 않기 때문에 기존 소스에서 인스턴스를 생성하는 로직을 확인하지 못하면 에러없이 인자가 뒤바뀌는 크리티컬한 문제를 야기할 수 있습니다.

// 생성자
public User(String name, String nickName) { ... }

// 기존 인스턴스 생성 코드
User user = new User("Hyuk", "진혁"); // name: Hyuk, nickName : 진혁 ..

@RequireArgsConstrutor 도 마찬가지이며,

@Data 에 @RequireArgsConstrutor 어노테이션이 포함되어 있기 때문에 @Data도 같이 주의하셔야 합니다.

@Data 에서는 @Setter를 지원하기 때문에 변경 기능을 제공하지 않기 위한 필드의 안전성을 보장받기 힘들고, JPA 에서의 양방향 연관 관계시 @ToString 의 순환 참조 문제가 발생할 수 있습니다.

이를 위한 차선책이 있습니다.

@Builder 어노테이션을 사용하는 것입니다.

그럼 인스턴스를 생성할 때 좀 더 명시적이게 되겠죠 .

public class User {
private String name;
private String nickName;

@Builder
public User(String name, String nickName) {
this.name = name;
this.nickName = nickName;
}

// 인스턴스 생성 코드
User user = User.builder().name("진혁").nickName("Hyuk").build();
그런데 왜 @Builder 를 생성자 위에 붙일까요??

필드에 추가적인 어노테이션 있으면 생성자로 전달이 안되는 경우가 있다고 합니다.

또한 클래스 위에 어노테이션이 있을 경우 모든 필드에 대한 매개변수가 허용됩니다.

만약 JPA를 사용하면서 id 값이 auto_increament 나 createAt 같은 값이 AuditingEntityListener 가 설정되어있다면 필요가 없겠죠. 그렇기 때문에 생성자를 필요 조건에 따라 지정하고, 생성자 위에 @Builder를 붙이는게 좋습니다.

추가적으로 @Builder에 대한 내용을 더 보니

@Builder
@Builder ... and Bob's your uncle: No-hassle fancy-pants APIs for object creation! @Builder was introduced as experimental feature in lombok v0.12.0. @Builder gained @Singular support and was promoted to the main lombok package since lombok v1.16.0. @Builder with @Singular adds a clear method since ...

projectlombok.org

AllArgsConstructor 관련 글이 존재하였는데요.

Finally, applying @Builder to a class is as if you added @AllArgsConstructor(access = AccessLevel.PACKAGE) to the class and applied the @Builder annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself.

@Builder 사용시에 @AllArgsConstructor(access = AccessLevel.PACKAGE) 를 암묵적으로 사용해도 된다는 내용입니다.

하지만 @AllArgsConstructor 보다는 필요한 필드에 대한 생성자를 직접 작성하여 사용하는 것이 바람직하지 않을까 싶습니다.

profile
후회없는 오늘이, 후회없는 내일

0개의 댓글