본문 바로가기

📝 ErrorNote

[Builder pattern] @Builder 사용 하여 객체의 정보를 수정할 때 값이 수정되지 않고 초기화 되는 문제

Builder 패턴

 

👀 문제 상황 

  • 사용자의 정보를 수정하는 로직을 작성하는 중에 dto로 받아온 사용자의 수정 데이터를 toEntity 라는 메서드로 엔티티 객체로 변환하는 순간 dto로 받아온 데이터들이 모두 사라지는 문제를 겪었다. 
  • Chat GPT 에게 물어봐도 toEntity 메서드는 객체를 새로 생성하는 메서드이기 때문이라고 하는데 나는 이 이야기를 들으면서도 도대체 말을 이해하지 못했다. 당연히 빌더 패턴을 사용해서 dto를 entity로 변경하는 건데 왜 기존의 값이 수정되지 않고 새로 생성이 되는지 이해를 못했다. 
  • 이건 내가 빌더패턴을 정확하게 이해하지 못해서 발생한 대참사이다. 빌더는 객체를 수정하는 것이 아니라 생성자처럼 객체를 생성하는 기능을 수행한다고 한다. 

 

🌟 정확하게 알아야 할 개념

  • 빌더패턴은 객체의 생성을 담당하는 패턴으로, 일반적으로 빌더를 사용하여 객체를 새로 생성한다. 빌더를 사용하여 객체를 생성할 때, 이전 객체의 값을 수정하는 것이 아니라 새로운 객체를 생성하는 것이다. 
  • 이것이 빌더 패턴의 주요 특징 중 하나이며, 이를 이해하는 것이 중요하다. 
  • 빌더 패턴은 객체 생성 시에 여러 속성을 가진 객체를 편리하게 생성하기 위해 사용된다. 따라서 객체의 속성을 일부 변경하거나 해당 속성을 지정하여 새로운 객체를 생성해야한다고 한다. 
  • 따라서 내가 dto로 받아온 값을 User 엔티티의 빌더 패턴으로 엔티티 객체로 변환하려고 하는 행위(?)는 잘못되었다고 할 수 있다. 
  • 하지만 빌더 패턴을 사용해서 객체의 데이터를 수정하는 것이 아예 불가능한 것은 아니라고 한다.

 

✏️ 그렇다면 빌더 패턴으로 어떻게 값을 수정할 수 있는가?

@Getter
@Setter
@Builder(toBuilder = true) // 기존 인스턴스를 기반으로 새로운 객체를 빌드할 수 있게 함
public class UserEntity {
    private String name;
    private String password;
    private String phone;
    private String bio;
    private String website;
    private String gender;
    // 기타 필드 및 메서드
}

 

이처럼 toBuilder 속성을 true 로 설정해줄 경우 toBuilder() 메서드를 사용할 수 있게되는데

 

이 메서드를 사용하면 이미 생성되어있는 객체의 값을 toBuilder() 메서드를 활용하여 특정 필드의 값만을 변경해줄 수 있다고 한다. 

public class UserManager {

    public static void main(String[] args) {
        // UserEntity 객체 생성
        UserEntity user = UserEntity.builder()
                .name("홍길동")
                .password("password123")
                .phone("010-1234-5678")
                .bio("안녕하세요, 저는 홍길동입니다.")
                .website("https://example.com")
                .gender("남성")
                .build();

        // toBuilder() 메서드를 사용하여 UserEntity 객체의 일부 정보 업데이트
        UserEntity updatedUser = user.toBuilder()
                .phone("010-1324-1234") 
                .website("https://example.com") 
                .build();

    }
}

 

😅 결과

toBuilder 메서드를 활용하면 객체의 값을 일부 수정할 수는 있지만 내가 구현하려는 로직에서는 사용하기에 적합하지 않은 것 같다는 생각이 들었다. 

 

어쨌든 빌더패턴이라는 것이 매개변수가 많아 생성자에 정의된 순서대로 데이터를 넣기 어려워 이를 편하게 하기 위한 디자인패턴인 건데 즉, 객체를 생성하는 것이 주된 목적인데 나는 객체의 값을 수정하는 로직을 만들어야 하므로 객체의 값을 부분적으로 수정하기 위해서는 굳이 엔티티 객체로 바꿀 필요는 없을 것 같고, dto에서 값을 꺼내서 entity에 setter 를 사용해서 update를 해주는 방식으로 구현하는 것이 적합한 것 같다.