데이터를 다룰 때 사용하는 용어라 Entity, DTO, VO를 많이 사용하는데, 각각의 차이에 대해 알고 있으면 좋을 것 같다.
📌 Entity란?
엔티티는 데이터베이스에서 사용하는 용어로 식별이 가능한 객체라는 의미를 가지고 있다. 관계형 데이터베이스의 테이블에서는 기본키를 통하여 식별 가능하도록 객체를 구별하고 있다.
또한 데이터베이스의 테이블과 매칭되는 클래스를 Entity 클래스 라고도 부른다.
아래처럼 스프링 프레임워크는 어노테이션을 통하여 데이터베이스 테이블과 매칭하도록 설정할 수 있는데, 이때 데이터베이스와 매칭되는 역할을 수행한다고 해서 이 클래스를 Entity클래스라고 부른다.
@Entity
public class Phone {
@Id
private Long id = 1;
private String name = "삼송";
private int price = 990000;
public Phone() {
}
}
📌 DTO란?
DTO(Data Transfer Object)는 이름뜻에서 유추할 수 있듯이, 데이터 전송을 담당하는 객체이다. 그렇기 때문에 DTO는 데이터만 가지고 있고 별도의 비즈니스 로직(특정 동작을 수행하는 메서드)를 가지고 있지 않아야 한다.
데이터를 집어넣거나 참조할 수 있어야 하기 때문에 오직 getter, setter 메서드만 가지고 있다.
주로 레이어드 아키텍처와 같이 계층이 나누어져 있는 경우에, 하나의 계층에서 다른 계층으로 데이터를 전송하는 경우에 사용된다.
또한 사용자 입력을 통해서 받은 요청 데이터를 비즈니스 로직을 처리하는 클래스에 넘겨주거나, 출력을 담당하는 객체에 결과값을 전달하는 경우에 응답 데이터로 사용된다.
public class PhoneDto {
private String name;
private int price;
// Getter와 Setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
추가적으로 전달중인 DTO객체의 불변성을 보장하기 위해서 아래와 같이 setter대신 생성자를 통해 생하고 필드를 불변으로 만들어서 사용하기도 한다.
public class PhoneDto {
private final String name;
private final int price;
public Phone(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
📌 VO란?
VO(Value Object)는 말 그대로 값을 표현하는 객체이다. DTO와는 다르게 데이터 전달의 목적이 아니므로 실제 비즈니스 로직을 수행하는 서비스(도메인 영역)에서 값을 표현할 때 사용하고, 별도의 메서드가 존재할 수 있다.
VO의 가장 큰 특징은 불변 객체라는 것이다. 값을 가지고 있지만 해당값은 절대 변할 수 없고, 상태를 변경하는 메서드도 가질 수 없다.
또한 새로운 값이 필요한 경우에 VO객체를 새로 생성해서 할당해야 한다.
마지막으로 값 자체를 비교하기 위하여 hashCode()와 equals() 메서드를 오버라이딩해서 값의 동등성을 비교할 수 있다.
아래의 예시를 보면, Person이라는 객체는 Name이라는 VO객체를 가지고 있다.
public class Person {
private Name name; // VO객체를 필드로 가진다.
public Person(Name name) {
this.name = name;
}
}
// VO객체
public class Name {
private final String name; // final을 통한 불변
public Name(final String name) {
this.name = name;
}
// 별도의 로직을 가질 수 있다.
public String getFirstName() {
return String.valueOf(name.charAt(0));
}
// 같은 이름인지 아닌지에 대해 동등성 검사를 할 수 있다.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Name name1 = (Name) o;
return name.equals(name1.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
'Spring' 카테고리의 다른 글
DDD 설계 vs SQL 중심 설계 (1) | 2023.11.09 |
---|---|
[Spring] HTTP method (0) | 2023.11.06 |
[Spring] 스프링 빈과 의존성 주입 해보기 (0) | 2023.11.03 |
[Spring] Controller 구현하기 (0) | 2023.11.02 |
[Spring] Controller, Service, Repository 3계층의 역할 (0) | 2023.10.31 |