토비의 스프링 UserDao
DAO Data Access Object
•
실제로 DB의 데이터에 접근하는 객체
DTO Data Transfer Object
•
계층 간 데이터 교환을 위한 객체
•
로직 없이 getter setter 메소드만 가진 순수한 데이터 객체 클래스
•
DB → Service → Controller로 보낼 때 →에서 사용함
VO Value Object
•
변경 불가능, read-only
•
DTO는 인스턴스(가변 객체)의 개념이라면, VO는 리터럴 값(불변)의 개념
[Java] 인스턴스(가변 객체) vs 불변 객체
Mutable Object == 가변 객체
•
Java에서 Class의 인스턴스가 생성된 이후에 내부 상태가 변경 가능한 객체
•
멀티 스레드 환경에서 사용하려면 별도의 동기화 처리가 필요
Immutable Object == 불변 객체
•
Java에서 Class의 인스턴스가 생성된 이후 내부 상태를 변경할 수 없는 객체
•
멀티 스레드 환경에서도 안전하게 사용될 수 있다는 신뢰성을 보장
•
read-only 메소드만 제공, 객체의 필드는 모두 final을 사용해서 처음 할당된 이후 상태가 바뀌지 않도록 설정해야 함
◦
필드가 모두 primitive type(==원시 타입)인 경우
◦
필드에 reference type이 있는 경우 → 레퍼런스 타입 객체도 불변으로 만들어야 함
◦
reference type 컬렉션이 있는 경우 → 방어적 복사를 해야 함
그러면 DTO는 불변 객체인 것이 좋지 않을까?
내가 지금까지 개발한 DTO의 대표적인 예시
@Getter
public class AnswerReq {
private Long questionId;
private String content;
}
Java
복사
@Getter
@NoArgsConstructor
public class AnswerRes {
private Long answerId;
private AnswerType type;
private AccountRes account;
private String content;
private Integer heartCount;
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
private Boolean isHearted;
public AnswerRes(Answer answer, List<Long> heartList, Integer heartCount) {
this.answerId = answer.getId();
this.type = answer.getType();
this.content = answer.getContent();
this.account = createdAccountRes(answer.getAccount());
this.heartCount = heartCount;
this.createdAt = answer.getCreatedAt();
this.modifiedAt = answer.getModifiedAt();
this.isHearted = Boolean.FALSE;
if (heartList.contains(answer.getId())) {
this.isHearted = Boolean.TRUE;
}
}
public AnswerRes(Answer answer) {
this.answerId = answer.getId();
this.type = answer.getType();
this.content = answer.getContent();
}
public AnswerRes(Answer answer, Integer heartCount) {
this.answerId = answer.getId();
this.type = answer.getType();
this.content = answer.getContent();
this.account = createdAccountRes(answer.getAccount());
this.heartCount = heartCount;
this.createdAt = answer.getCreatedAt();
this.modifiedAt = answer.getModifiedAt();
}
private AccountRes createdAccountRes(Account account) {
return new AccountRes(account);
}
}
Java
복사
•
final만 붙이지 않았을 뿐 불변 객체로 쓰는 것이 더 이득이 큼
불변 객체일 때의 장점
•
멀티 스레드 환경에서 동기화 고려할 필요 없음
•
캐싱에 유리함
•
프로퍼티 값 변경될 일 없음
•
값 변경 안되는 객체를 방어적으로 복사하는 것보다 애초에 불변 객체인 게 낫다
결론 ⇒ DTO, VO의 가변/불변은 이론상의 개념이고, 둘 다 가능하면 불변 객체로 생성하는 것이 낫다