왜 생성자 애너테이션들을 지양해야 할까?
@AllArgsConstructor, @NoArgsConstructor 애너테이션을 지양해야 하는걸까?
이유를 알기 전 각각의 애너테이션이 무엇인지에 대해 먼저 알아보고자 한다.
@AllArgsConstructor, @NoArgsConstructor 애너테이션이란?
@NoArgsConstructor : 파라미터가 없는 디폴트 생성자를 생성
@AllArgsConstructor : 모든 필드 값을 파라미터로 받는 생성자를 생성
class Member{
private String name;
private Integer age;
private String email;
public Member(){} // 기본 생성자
public Member(String name){
this.name = name;
}
public Member(String name, Integer age){
this.name = name;
this.age = age;
}
public Member(String name, Integer age, String email){
this.name = name;
this.age = age;
this.email = email;
}
}
위의 코드는 기본 생성자와 그 외의 생성자들을 작성한 것인데, 이는 애너테이션을 사용할 경우 아래와 같이 간단하게 나타낼 수 있다.
@NoArgsConstructor
@AllArgsConstructor
class Member{
private String name;
private Integer age;
private String email;
}
왜 이렇게 간단해지는 애너테이션 사용을 지양해야 할까?
@NoArgsConstructor를 지양해야 하는 이유
1. 불필요한 빈 객체 생성 가능성
매개변수가 없는 기본 생성자를 생성하는 애너테이션으로, 외부에서 불필요하게 객체를 생성 할 수 있게 되어,
객체의 의도와 목적에 맞지 않는 상태로 객체가 생성될 수 있음
2. 불변성 위반 가능성
불변의 객체를 설계할 때에는 초기화 이후 상태 변경이 불가능해야 하는데, 기본 생성자로 인해 생성 후에도 외부에서 필드를 수정할 수 있는 가능성이 존재할 수 있음
따라서 @NoArgsConstructor(access=accessLevel.PROTECTED)로 설정하여,
객체 내부에서 생성자를 하나로 만들어 활용하며 @Builder를 활용하는 것이 좋다.
최대한 지양해야 할 애너테이션은 @AllArgsConstructor이다.
@AllArgsConstructor를 지양해야 하는 이유
1. 불필요한 외부 의존성 증가
모든 필드를 인자로 받는 생성자를 생성하기 때문에 모든 필드에 대한 의존성이 증가하여 불필요한 의존성이 발생할 수 있는데,
이는 프로젝트가 커지고 여러 모듈이나 프로젝트 간 코드 공유에 문제를 야기할 수 있음
또한, 접근할 필요가 없는 필드값에 대해서도 접근할 수 있게 되어 접근 가능성을 최대화 할 수 있음
2. 캡슐화 원칙 위반
객체지향 프로그래밍에서는 캡슐화의 원칙을 지키며, 필요한 경우 getter/setter를 사용하는 것이 일반적인데 @AllArgsConstructor을 사용할 경우 모든 필드를 매개변수로 받는 생성자를 생성하여, 객체 내부 상태를 외부에서 직접 조작할 수 있는 가능성을 높임
3. 필드 순서에 따른 에러 발생
모든 필드를 인자로 받는 생성자를 생성하기 때문에 변수들의 순서에 영향을 받아 에러가 발생할 수 있음
@AllArgsConstructor
class Member{
private String name;
private String email;
}
Member member = new Member("hong@gmail.com", "홍길동");
* 이름이 이메일이 되고 이메일이 이름이 되는 현상이 발생할 수 있음
위와 같은 문제가 발생할 수 있기 때문에 @Builder를 사용하는 것이 좋다.
@AllArgsConstructor 대신 Builder를 사용하면 어떻게 될지 예시를 하나 보고자 한다.
@AllArgsConstructor
class Member{
private String name;
private String email;
}
Member member = new Member("hong@gmail.com", "홍길동");
위에서 해당 코드의 문제를 보았는데 이 코드를 Builder를 사용하면 어떻게 될까?
@AllArgsConstructor
class Member{
private String name;
private String email;
@Builder
private Order(String name, String email){
this.name = name;
this.email = email;
}
}
Member member = Member.builder()
.email("hong@gmail.com")
.name("홍길동")
.build();
위와 같이 파라미터를 순서가 아닌 이름으로 값을 지정하기 때문에 생성이나 리팩토링 시 유연하게 대응이 가능해진다.
오늘 얻은것은?
@AllArgsConstuctor은 최대한 지양하고, Builder를 이용하자!
'공부 자료 > Spring' 카테고리의 다른 글
[JPA] N:1, 1:N, 1:1, M:N 연관관계 매핑 (단방향/양방향 연관관계) (1) | 2023.11.27 |
---|---|
[Spring + JPA] JPA Entity 매핑 (feat. Entity 만들기) (2) | 2023.11.23 |
[Spring] @CreatedDate&@LastModifiedDate vs @CreationTimeStamp&@UpdateTimeStamp, 둘은 뭐가 다를까? (1) | 2023.11.21 |
[Spring JPA] 페이징 Pageable, Page, Slice / 페이지 나누기 (2) | 2023.11.21 |
[Spring] Getter/Setter를 지양하자? (1) | 2023.11.21 |