문제&해결

Builder 패턴 객체 생성시 필드 초기값 무시되는 문제

mint* 2024. 3. 17. 22:46
728x90

문제 상황

Lombok의 @Builder 패턴을 사용하여 Member 클래스의 인스턴스를 생성할때, 특정 필드에 대해 명시적으로 값이 설정되지 않으면 null 값으로 초기화된다.

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
@Table(name = "member")
@Where(clause = "is_deleted=false")
@AttributeOverride(name = "id", column = @Column(name = "member_id"))
public class Member extends BaseEntity {

    @Enumerated(EnumType.STRING)
    @Column(length = 50, nullable = false)
    private MemberRole role;

    @Column(length = 100, nullable = false)
    private String name;

    @Column(length = 255, nullable = false, name = "image_url")
    private String imageUrl;

    @Column(length = 100, nullable = false, name = "oauth_id")
    private String oauthId;

    @Enumerated(EnumType.STRING)
    @Column(length = 50, nullable = false)
    private OAuth2Provider provider;

    @Column(length = 255)
    private String fcmToken;

    @OneToMany(mappedBy = "member", fetch = FetchType.EAGER)
    private Set<Participant> participations = new HashSet<>();

    @Column(nullable = false, name = "image_num")
    private Integer imageNum = new Random().nextInt(12) + 1;

    @Builder // 빌더 패턴
    public Member(MemberRole role, String name, String imageUrl, String oauthId, OAuth2Provider provider,
                  String fcmToken,
                  Set<Participant> participations, Integer imageNum) {
                  String fcmToken, Integer imageNum) {
        this.role = role;
        this.name = name;
        this.imageUrl = imageUrl;
        this.oauthId = oauthId;
        this.provider = provider;
        this.fcmToken = fcmToken;
        this.participations = participations; // null 값으로 설정됨
        this.imageNum = imageNum;
    }
}

 

participants는 new HashSet<>()으로 초기화되어있음에도 불구하고 @Builder를 사용해 객체 생성시 participants 필드가 빌더에 의해 설정되지 않으면 초기화 값 대신 null 값이 할당된다.

 

해결 방법

1. 빌더 패턴 생성자 인자에 participants를 포함시키지 않는다.

@Builder
public Member(MemberRole role, String name, String imageUrl, String oauthId, OAuth2Provider provider,
              String fcmToken, Integer imageNum) {
    this.role = role;
    this.name = name;
    this.imageUrl = imageUrl;
    this.oauthId = oauthId;
    this.provider = provider;
    this.fcmToken = fcmToken;
    this.imageNum = imageNum;
}

빌더 사용시 participants 필드에 대한 값이 명시적으로 설정되지 않았기 때문에,

할당한 초기값 new HashSet<>()이 그대로 적용된다.

 

2. 생성자 내 기본값 설정

@Builder
public Member(MemberRole role, String name, String imageUrl, String oauthId, OAuth2Provider provider,
              String fcmToken, Integer imageNum) {
    this.role = role;
    this.name = name;
    this.imageUrl = imageUrl;
    this.oauthId = oauthId;
    this.provider = provider;
    this.fcmToken = fcmToken;
    this.imageNum = imageNum;
    this.participations = new HashSet<>(); // 기본값 설정
}

 

결론

Lombok의 @Builder 패턴 사용시 특정 필드의 기본값을 보장하려면 해당 필드를 생성자에 포함시키지 않거나, 명시적으로 생성자에 기본값을 설정해야한다.

728x90