엔티티에 setter가 있다고해서 무조건 나쁘다는 뜻은 아니다.
엔티티 설계에 관한 다수의 의견을 종합했을 때 setter를 쓰지 않는 것을 권장하고 있다.
엔티티에 setter가 있다면
양방향 바인딩의 경우 setter가 있다면 훨씬 더 간단하게 구현할 수 있고
엔티티 필드의 값을 직접 변경할 수 있기 때문에
Dirty checking을 곧바로 사용할 수 있다는 장점(?)이 있다.
하지만 setter를 사용해 값을 어디선가 직접 변경할 수 있다면
그만큼 일관성이 깨질 수 있다는 위험이 있다.
일관성이 깨진다면 객체의 상태 추적을 하기 어려워지고 파급 효과를 잡기 어려워진다.
아래는 setter 사용을 지양해야하는 이유이다.
1. 불명확한 사용 의도
user.setName("짱구");
user.setAge(20);
여기서 set 메서드는 새로운 값을 set하는지, 기존의 값을 update하는지 알 수 없다.
사용 의도가 명확하지 않다.
2. 일관성 유지
public setter인 경우 외부에서 객체 내부 상태를 변경할 수 있기 때문에 일관성이 깨질 수 있다.
그러려면 각 setter마다 유효성 검사 코드가 추가되어야 한다.
그렇다면 setter 없이 엔티티의 값을 어떻게 담을까?
1. 별도의 업데이트 메서드를 추가하는 방법
private String name;
private int age;
public void updateAge(int age) {
this.age = age;
}
setter 메서드를 제거하고 getter만 남은 상태이다.
이렇게 updateAge 메서드를 추가하면
앞서 말한 불명확한 사용 의도에 따른 문제점은
update 메서드를 사용함으로써 의도를 파악할 수 있고
일관성 유지 관련해선 age 필드는 값을 변경해도 되기 때문에 update 메서드가 존재하는 것이다.
여기서는 하나만 업데이트했지만
변경할 값들을 여러개 담아 다수의 필드를 업데이트할 수도 있다.
2. Builder 사용(생성자 사용)
@Builder
public User(String name, int age) {
this.name = name;
this.age = age;
}
롬복 어노테이션을 사용했다.
@Builder 어노테이션은 클래스 단위보다 생성자 위에 사용을 권장한다.
만약 클래스 위에 @Builder와 @AllArgsConstructor을 같이 사용하게되면
객체 생성 시 의도하지 않은 값을 설정할 수 있기 때문이다.
return User.builder()
.name(userDto.getAge())
.age(userDto.getAge())
.nickname(userDto.getNickname())
.gender(userDto.getGender())
.hobby(userDto.getHobby())
.build();
그리고 Builder가 주는 장점은
저 값들을 생성자 파라미터에 가득 담아서 보내는 것보다
어떤 값에 무엇이 들어가는지 알 수 있어 가독성이 좋다는 장점이 있다.
이렇게 Builder를 사용하면 객체의 생성 시점에 의도한 값을 대입해줄 수 있어
setter를 사용하지 않아도 된다.
그렇다면 어떤 방법이 최선인가?
엔티티 설계에 관해선 명확한 규정이 없다.
엔티티의 책임: 데이터베이스에 대응되는 Java 클래스
프로젝트 협의나 개인 재량에 따라 선택해야 한다.
1. (가장 넓은)엔티티에 비즈니스 로직을 허용한다.
- 엔티티가 뚱뚱해지며 그만큼 책임이 명확해지지 않을 수 있다.
- 책임이 분산된 만큼 서비스 레이어가 간단해진다.
2. 일부 편의 메서드(update , setter)만 허용한다.
- 변경이 가능한 일부 필드만 열어두어 외부 변경 위험을 최소화할 수 있다.
- 여전히 엔티티의 책임을 넘어선다.
3. (가장 보수적)생성자와 필드만 허용한다.
- 엔티티 변환을 위한 로직으로 이해관계에 있는 클래스들이 뚱뚱해진다.
- 책임이 명확해진다.
도움을 받은 곳
jpa create 및 update 시 dto에서 entity 변환방식 - 인프런 | 질문 & 답변
안녕하세요 정말 유익한 강의 잘듣고 있고요 항상 친절한 답변에 감사함을 느낍니다.1.create시 createDto로 서비스로 넘어 온다면 아래에 방법중 어떤게 유지보수와 같은 측면에서 가장 나은 선택
www.inflearn.com
'Spring > Spring' 카테고리의 다른 글
Spring Initializr 개편 이후의 Java 8, 11, Spring Boot 2.7.x 프로젝트 생성 방법 (0) | 2023.11.30 |
---|---|
[Spring Security] X-Frame-Options와 정적 파일 로드 문제 (0) | 2023.07.18 |
[JPA] JSON 직렬화 순환 참조 문제 (0) | 2023.06.27 |
[Spring Security] 스프링 시큐리티 인증 아키텍처 (0) | 2023.06.07 |
[Spring Security] 사장된 WebSecurityConfigurerAdapter (0) | 2023.06.06 |