programming study/B-Spring

[Lombok] 올바른 Lombok 사용법 - @Builder

gu9gu 2023. 1. 11. 01:21

출처 - [Lombok] 올바른 Lombok 사용법 - @Builder (tistory.com)

 

 

 

우리가 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가지인데,

  1. 클래스에@Builder를 붙이기 
  2. 생성자에@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;
    }
}

 

참고

 

만렙 개발자 키우기

개발 경험치를 쌓아가며 성장하는 개발자의 기록 일지입니다.

www.nowwatersblog.com

 

 

자주 사용되는 lombok, 주의 사항 | devk0ng's blog

@Getter, @Setter : 말그대로 getter, setter method를 생성해주는 놈이야! AccessLevel을 명시해줌으로써 접근제한자를 지정 해 줄 수 있어. 123456789public Class Sample { @Getter private String attr1; @Getter(AccessLevel.PRIVATE)

devk0ng.github.io

 

 

 

[Lombok] @Builder와 @NoArgsConstructor 동시 사용시 주의사항

@Builder와 @NoArgsConstructor를 함께 사용하려면, @AllArgsConstructor도 함께 사용하거나 모든 필드를 가지는 생성자를 직접 만들어 줘야 한다. 또한, @Builder를 사용할 때 @NoArgsConstructor뿐만 아니라..

precioustar.tistory.com