JPA 엔티티 작성 - Setter 금지

Aiden Shin·2020년 3월 10일
13

엔티티를 작성할 때 제가 생각하는 몇가지 원칙이 있습니다.
그중 엔티티(객체)의 Setter 사용 금지 원칙(?) 에 대해 알아보겠습니다.

Setter 사용 금지 및 생성자 접근 제어

엔티티를 작성할 때 습관적으로 모든 필드에 Setter를 생성하는 경우가 있습니다.
하지만 Setter를 무분별하게 남용하다 보면 여기저기서 객체(엔티티)의 값을 변경할 수 있으므로 객체의 일관성을 보장할 수 없습니다.

그리고 setter는 그 의도를 알기 힘들다고 생각합니다.

예를 들어 아래의 코드의 경우 멤버 객체를 set매소드를 통해 변경하는데 무엇을 하는건지 한번에 알 수 없습니다.(예제의 경우 간단한 변경이지만 복잡해질 경우 객체의 값을 변경하는 행위가 무엇을 위해 변경하는지 한 눈에 알기 힘들 수 있습니다.)

Member member = new Member();
member.setName("신이삼");
member.setTel("01050503453");
...
member.set...

아래의 코드 처럼 객체에서 매소드를 제공하여 변경하면 변경 의도를 한번에 알 수 있고, 객체 자신의 값을 자신이 변경하는 것이 객체 지향 관점에도 더 맞는다고 생각합니다.

// 멤버의 기본정보를 수정한다는 것을 한눈에 알 수 있다
member.changeBasicInfo("신이삼","01050502323");
//Member 엔티티 내부에 매서드 생성
public void changeBasicInfo(String name, String tel) {
    this.name = name;
    this.tel = tel;
}

객체의 일관성을 유지하기 위해 객체 생성 시점에 값들을 넣어줌으로써 Setter 사용을 줄일 수 있습니다.

// 객체의 생성자 설정 (필드가 많을경우 롬복의 @Builder 사용하면 좋다)
@Builder
public Member(String username, String password, String name, String tel, Address address) {
        this.username = username;
        this.password = password;
        this.name = name;
        this.tel = tel;
        this.address = address;
    }
// 객체 생성 시 값 세팅(빌더패턴 사용)
Member member = Member.Builder()
      .username("name")
      .password("1234")
      .name("name);
      .tel("01012345677")
      .address(address)
      .build();

아래와 같이 기본 생성자 접근자를 protected로 변경하면 new Member() 사용을 막을 수 있어 객체의 일관성을 더 유지할 수 있습니다.
(protected로 설정하는 이유는 JPA 기본 스펙 상 기본 생성자가 필요한데 protected로 제어하는 것 까지 허용되기 때문입니다.)

  // Member 엔티티
@Entity
@Getter
@Table(name = "member")
public class Member{

    // 기본 생성자 protected로 접근 제어
    protected Member(){};
    
    ...
}

롬복을 사용한다면 @NoArgsconstructor 어노테이션 설정을 통해 간단하게 설정할 수 있습니다.

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Table(name = "member")
public class Member {

}

무분별한 Setter 사용금지는 엔티티 뿐 아니라 객체 생성 및 변경 시 모두 해당하는 부분입니다. 객체의 일관성을 유지할 수 있어야 프로그램의 유지 보수성을 끌어 올릴 수 있기 때문에 일급 컬렉션 사용 등 많은 개발자들이 객체의 일관성을 유지하기 위해 노력을 기울이고 있다고 생각합니다.

profile
예전 블로그: https://shinilhyun.github.io/

0개의 댓글