우리가 Spring에서 자주 볼 수 있는 Lombok들에 대해 알아보겠습니다
아래와 같은 코드가 있다고 할 때 이를 어떻게 리펙토링 할 수 있을까요?
@Getter
@Setter // 문제 1. 객체가 무분별하게 변경될 가능성 있음
@NoArgsConstructor // 문제 2. 기본 생성자의 접근 제어자가 불명확함
@Builder
@AllArgsConstructor // 문제3. 객체 내부의 인스턴스멤버들을 모두 가지고 있는 생성자를 생성 (매우 위험)
@Entity
public class Member
해결 1. @Setter를 사용하지 않기
Setter는 그 의도가 분명하지 않고 객체를 언제든지 변경할 수 있는 상태가 되어서 객체의 안전성이 보장받기 힘듭니다. 특히 엔티티에서는 @Setter를 사용 시 해당 업데이트 문이 어디서 누구에 의해 발생했는지 추적하기가 힘들어진다.
때문에 값 변경이 필요한 경우 의미 있는 메서드를 생성하여 이를 사용하는 것이 좋습니다.
해결 2.@NoArgsConstructor(access = AccessLevel.PROTECTED)로 변경
기본 생성자(NoArgsConstructor)의 접근 제어를 PROCTECTED 로 설정하면 아무런 값도 갖지 않는 의미 없는 객체의 생성을 막게 됩니다. 즉 무분별한 객체 생성에 대해 한번 더 체크할 수 있습니다.
//@NoArgsConstructor(access = AccessLevel.PROTECTED)
Member member = new Member(); //컴파일 에러 발생
이때, '의미있는 객체' 생성을 위해서@Builder을 사용할 수 있습니다.
@Builder를 사용하는 방법은 총 2가지인데,
- 클래스에@Builder를 붙이기
- 생성자에@Builder를 붙이기
해결 3. @AllArgsConstructor 는 쓰지 않기
만약 해결 2의 방법1을 사용, 클래스 레벨에서@Builder와 @NoArgsConstructor를 함께 쓰면 오류가 발생합니다.
이를 해결하기 위해서는 모든 필드를 가지는 생성자를 만들어주어야 하는데
이때 @AllArgsConstructor를 사용하는 것은 추천하지 않습니다. 이는 @AllArgsConstructor 가 너무 위험하기 때문입니다, @AllArgsConstructor는 클래스에 존재하는 모든 필드에 대한 생성자를 자동으로 생성하는데, 인스턴스 멤버의 선언 순서에 영향을 받기 때문에 두 변수의 순서를 바꾸면 생성자의 입력 값 순서도 바뀌게 되어 검출되지 않는 치명적인 오류를 발생시킬 수 있습니다.
리펙토링 결과
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Member {
@Id
@Column(name = "id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
private String picture;
@Enumerated(EnumType.STRING)
private Role role;
public Member update(String name, String picture) {
this.name = name;
this.picture = picture;
return this;
}
// 생성자에 @Builder 적용
@Builder
public Member(String name, String email, String picture, Role role) {
this.name = name;
this.email = email;
this.picture = picture;
this.role = role;
}
}
참고
'spring' 카테고리의 다른 글
Spring MVC 단위 테스트 (0) | 2023.10.24 |
---|---|
메소드 인자에서 @NotNull 과 @NonNull (0) | 2021.12.24 |
JPA (2) 엔티티 생명주기, 영속성 컨텍스트 (0) | 2021.09.18 |
JPA (1) JPA , ORM 개념 (0) | 2021.09.18 |
서블릿 (0) | 2021.09.18 |