JPA에 대해 어느정도 공부한 분들의 글을 보면, Entity에 Setter를 넣지 말라고 하는 내용이 많다.
습관성으로 @Getter, @Setter를 붙여두던 나에겐 대체 왜 쓰지 말라는건지 이유가 궁금해졌다.
다음 코드를 살펴보자.
user.setEmail("hwangdo@exam.com");
이 짧은 한줄짜리 코드는 무엇을 위해 작성되었을까?
"사용자의 이메일 정보를 설정" 은 맞는말이긴 하다. 하지만 새로 생긴 User의 이메일을 설정해 주는 것인지, 기존 User의 이메일을 업데이트 해주는 것인지 이 코드만으로는 이해 할 수 없다.
이렇게 의도가 불분명해지는 메서드는 프로젝트 규모가 커질수록 의도치 않은 실수가 발생할 확률이 높아진다. 이는 객체의 일관성이 보장되지 않는다고 볼 수 있다.
그렇다고 그냥 단순히 Setter를 빼버리면, 엔티티의 수정이 아예 불가능해진다. 이렇게 아예 Immutable하게 만드는 것은 일관성 부분에서 큰 이점이 있겠지만, 코드를 작성하는 개발자 입장에선 너무나도 불편하다.
따라서 다음과 같은 방법을 도입 할 수 있다.
먼저, 처음 만드는 객체일 경우엔 생성자를 통해 값을 넣어주면 된다.
@Builder
public Question(String title, String context, String writer, String password) {
this.title = title;
this.context = context;
this.writer = writer;
this.password = password;
}
Lombok 라이브러리를 사용하면, 이렇게 위에 @Builer annotation을 붙여 빌더 패턴으로 사용 할 수 있다.
빌더 패턴이란?
만약, 객체의 필드가 많아진다면 개발자는 생성자 파라미터의 순서를 외워서 작성하기 힘들어진다. IDE에서 힌트를 주기도 하지만, 수십개의 필드가 있다면 실수의 확률도 올라간다.
Question question = Question.builder()
.title("제목")
.context("내용내용")
.writer("작성자")
.password("pw")
.build();
따라서 빌더 패턴을 도입하면, 이렇게 마치 메서드의 형태처럼 값을 넣어줄 수 있다. StringBuilder를 간략하게라도 써본 사람은 이해가 잘 될것이다.
Setter의 문제는, 의도를 파악하기 힘들다는 것이였다. 따라서, 메서드 이름만으로 의도를 파악할수 있도록 구성한다.
public void updateUserEmail(String email){
this.email = email;
}
위와 같이, 사용하는 사람 입장에서 정확한 의도를 파악할수 있도록 메서드 이름을 정의하는것이 좋다.
Setter를 쓰는것은 지양해야 하는것이지, 금기사항이라고 볼수는 없을 것 같다.
관리만 잘 한다면, Setter를 써도 괜찮을 수 있다.
그러나 내가 더 나은 코드를 위해, Entity에 Setter를 도입하지 않는 방법에 대한 고민한 내용이 있다.
[SpringBoot] @ModelAttribute 사용시 바인딩이 안되는 문제
트러블 슈팅중 나온 방법이지만, DTO를 도입함으로서 문제를 해결했다.