
오늘은 Lombok에서 생성자 생성에 대한 기능을 제공해주는 어노테이션인
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor에 대해 알아 보려고 한다.
우리가 좋아하는 치킨을 예제로, Lombok 없이 작성했을 때와 비교하면서 알아보도록 하겠다.
@NoArgsConstructor
먼저 @NoArgsConstructor는 파라미터가 없는 기본 생성자를 만드는데 사용하는 어노테이션이다.
예제를 통해 알아보자
@Getter
@NoArgsConstructor //Lombok 사용
public class Chicken {
private String name;
private int price;
}
여기선 이 Lombok 덕분에 기본 생성자가 자동으로 생성된다. 즉, new Chicken(); 처럼 매개변수 없이 객체를 생성할 수 있게 되는 것이다.
Lombok 없이 작성할 경우
@Getter
public class Chicken {
private String name;
private int price;
public Chicken() { // 기본 생성자를 수동으로 생성함
}
}
이렇게 Lombok을 사용하지 않으면 직접 기본 생성자를 작성해 줘야 한다.
※주의사항※
이 어노테이션을 클래스에 붙이면, 기본 생성자가 public으로 생성되기 때문에, 굳이 외부에 생성을 열어둘 필요가 없으면 막는것이 좋다.
@NoArgsConstructor(access = AccessLevel.PROTECTED) 이런식으로 접근 권한을 최소화하는 것을 권장한다.
@RequiredArgsConstructor
이 @RequiredArgsConstructor는 final이나 @NonNull인 필드값만 파라미터로 받는 생성자를 만들어준다.
예제를 통해 알아보자
@Getter
@RequiredArgsConstructor //Lombok 사용
public class Chicken {
private final String name;
private final int price;
}
이렇게 하면 name과 price를 매개변수로 받는 생성자가 자동으로 생성된다.
Chicken chicken = new Chicken("뿌링클", 23000);
하지만 만약 private String brand; 같은 final이 없는 필드는 생성자의 매개변수에 포함이 되지 않는다.
Lombok 없이 작성할 경우
@Getter
public class Chicken {
private final String name;
private final int price;
public Chicken(String name, int price) { // 필드를 받는 생성자를 직접 생성함
this.name = name;
this.price = price;
}
}
이렇게 Lombok 없이 사용하면 필수 필드만 받는 생성자를 직접 작성해야 한다.
@AllArgsConstructor
이 @AllArgsConstructor는 클래스의 모든 필드 값을 파라미터로 받는 생성자를 자동으로 생성한다.
예제를 통해 알아보자
@Getter
@AllArgsConstructor //Lombok 사용
public class Chicken {
private String name;
private int price;
private String brand;
}
이렇게 하면 모든 필드를 초기화하는 생성자가 자동으로 생성된다.
Chicken chicken = new Chicken("뿌링클", 23000, "bhc");
이렇게 name, price, brand 까지 한번에 초기화 가능하다.
Lombok 없이 작성할 경우
@Getter
public class Chicken {
private String name;
private int price;
private String brand;
public Chicken(String name, int price, String brand) { // 모든 필드를 받는 생성자를 직접 생성함
this.name = name;
this.price = price;
this.brand = brand;
}
}
이렇게 Lombok을 사용하지 않으면 직접 모든 필드를 받는 생성자를 만들어야 한다.
※@AllArgsConstructor 사용을 지양하자❓※
문제점
알아본 바로 @AllArgsConstructor 어노테이션은 모든 필드를 받는 생성자를 만들어준다.
그러나 이 경우에 생성자 사용의 문제점인 같은 타입에 매개변수 (name, brand) 를 서로 바꿔 입력했을 때 발생하는 문제다.
@Getter
@AllArgsConstructor
public class Chicken {
private String name;
private int price;
private String brand;
}
위 코드에서 생성된 생성자는 다음과 같다.
public Chicken(String name, int price, String brand) {
this.name = name;
this.price = price;
this.brand = brand;
}
여기서 필드 순서를 바꾸면?
@Getter
@AllArgsConstructor
public class Chicken {
private String name;
private String brand;
private int price;
}
이렇게 변경하면 기존 코드에서 Chicken chicken = new Chicken("뿌링클", 23000, "bhc"); 같은 부분이 컴파일 오류 없이도 잘못된 값으로 생성될 수 있다.
해결책
해결방법은 상황에 따라 다를 수 있음
1. @Builder 패턴 사용
- 가독성이 좋음
- 필드 순서 변경에도 안전함
- 필요한 필드만 설정 가능함
- 유지보수와 확장성이 뛰어남
2. @RequiredArgsConstructor 사용
- 필드 순서 변경에 안전함
- 불필요한 필드까지 강제 초기화 하는 문제를 해결할 수 있음
마무리
오늘은 생성자 생성시 자주 사용하는 어노테이션들에 대해 알아보았다.
사용하면서 무슨 역할들을 하는지 궁금하고 알고 쓰는 습관을 위해 정리 해봤는데 도움이 많이 된것같다.