DTO(Data Transfer Object)
계층간 데이터 교환을 위한 객체로 로직을 가지지 않는 순수한 데이터 객체로 필드와 필드 정보 제공을 위한 메소드만 가진다.
클라이언트에게서 폼을 넘겨받는 컨트롤러 계층 사이, 컨트롤러 계층과 애플리케이션 계층 사이 등 Layer를 오갈 때 사용한다.
자바에선 엔티티의 순환참조를 끊는 역할도 한다.
@Getter
public class PostResponse {
private Long id;
private String title;
private String content;
private String nickname;
private String username;
private LocalDate createDate;
private List<CommentResponse> commentResponses;
@Builder
public PostResponse(Post post) {
this.id = post.getId();
this.title = post.getTitle();
this.content = post.getContent();
this.nickname = post.getUser().getNickname();
this.username = post.getUser().getUsername();
this.createDate = post.getCreatedDate();
this.commentResponses = post.getComments().stream().map(CommentResponse::new).collect(Collectors.toList());
}
}
Entity
엔티티는 다른 엔티티와 구별할 수 있는 식별자를 가진 도메인의 실체 개념을 표현하는 객체이다.
식별자는 고유하되 엔티티의 속성 및 상태는 계속 변할 수 있다.
자바에선 실제 DB 테이블과 매핑되는 클래스이고 id로 구분되며, 비즈니스 로직을 포함한다.
엔티티를 기준으로 테이블이 생성되고 스키마가 변경되기에 수정에 민감하게 반응해야한다.
Entity
public class Post extends TimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 50, nullable = false)
private String title;
@Column(columnDefinition = "TEXT", nullable = false)
private String content;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE)
private List<Comment> comments = new ArrayList<>();
@Builder
public Post(String title, String content, User user) {
this.title = title;
this.content = content;
this.user = user;
}
public void edit(PostEdit postEdit) {
this.title = postEdit.getTitle();
this.content = postEdit.getContent();
}
public void addComment(Comment comment) {
this.comments.add(comment);
comment.setPost(this);
}
}
VO(Value Object)
값 자체를 표현하는 객체로 각 속성이 변화하지 않는 개념적 완전성을 모델링한다.
따라서 속성과 송성의 합에 의해 전체 개념이 부여되며, 개별 속성이 별개로 수정되지 않고 전체 객체가 한번에 생성되거나 삭제된다.
엔티티와 달리 식별자가 아닌 속성들의 값의 비교에 의해 동일함이 결정된다.
자바에선 getter와 비즈니스 로직을 포함할 수 있고, 값 비교로 동일성을 판단하기 위해 hashcode와 equals를 오버라이딩을 통해 모든 필드를 비교해야 한다.
Entity vs VO
엔티티와 VO는 도메인 주도설계시에 비즈니스 로직을 가지는 Domain Layer에 속하지만 필드의 상태로 일치를 확인하는지, 식별자로 일치를 확인하는지가 다르다.