Entity는 실제 데이터 베이스 테이블과 매핑되는 클래스이며,
테이블 내에 존재하는 컬럼만을 필드로 가져야 한다.
Entity 클래스는 상속을 받거나 추상클래스(인터페이스)의 구현체여서는 안된다.
Entity는 데이터베이스의 영속성 목적으로 사용되는 객체이기에 Request나 Response 값을 전달하는 클래스로 사용하는것을 지양해야 한다.
따라서 Setter 메서드 역시 최대한 지양하고 생성자를 통해 초기화할 수 있도록 해야한다.
생성자(Constructor)를 이용해서 초기화하는 경우 불변 객체로 활용할 수 있고, 불변 객체로 만들면 데이터를 전달하는 과정에서 데이터가 변조되지 않음을 보장할 수 있다.
고유한 ID를 통해 Entity를 구별하며 유일한 식별자(Primary Key)를 가지고 있어야 한다.
//Spring Data JPA를 사용할 경우 어노테이션을 이용해서 Entity class 및 Primary Key를 지정할 수 있음
@Entity
public class Airplane {
@Id
private String modelNum;
private int capacity;
private String airline;
private boolean active;
public Airplane(String modelNum, int capacity, String airline, boolean active) {
this.model = model;
this.capacity = capacity;
this.airline = airline;
this.active = active;
}
// 로직을 추가할 수 있다.
public void deactivateAccount() {
this.active = false;
}
// getter 생략...
public class AirplaneDTO {
private String modelNum;
private int capacity;
private String airline;
public AirplaneDTO(String registrationNumber, String model, int capacity, String airline) {
this.model = model;
this.capacity = capacity;
this.airline = airline;
}
//getter & setter 생략...
Entity와 DTO의 구조를 보면 상당히 유사하다는 것을 볼 수 있다. 차이점은 크게
- "setter를 가지고 있는가"
- "비즈니스 로직을 가지고 있을 수 있는가"
라고 볼 수 있다,
그렇다면 어떤 이유로 Entity와 DTO를 구분해서 사용하는 것일까?
public class Airplane {
private String model;
private int capacity;
private String airLine;
public Airplane(String model, int capacity, String airLine) {
this.model = model;
this.capacity = capacity;
this.airLine = airLine;
}
public String getModel() {
return model;
}
public int getCapacity() {
return capacity;
}
public String getAirLine() {
return airLine;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Airplane airplane = (Airplane) o;
return capacity == airplane.capacity &&
Objects.equals(model, airplane.model) &&
Objects.equals(airLine, airplane.airLine);
}
@Override
public int hashCode() {
return Objects.hash(model, capacity, airLine);
}
}
이전까지 혹은 지금도 DTO와 VO를 구분없이 혼용하여 사용하는 경우가 많다고 한다.
원인은 ⌜Core J2EE Patterns: Best Practices and Design Strategies⌟ 라는 책이라고 하는데...
간단하게 DTO와 VO의 차이를 정리해보면
- DTO는 데이터를 Layer to Layer로 전달하는 객체일 뿐 그 이상의 큰 의미는 없다.
따라서 불변성이 강제되지 않고, 필요할 경우 데이터를 가공해 전달할 수 있다.- 하지만 VO는 값 그 자체를 의미하기 때문에 불필요한 상태변경(setter 등)을 구현하지 않고 불변성을 보장힌다.
따라서 데이터베이스에서 받은 값을 VO를 통해 전달할 경우, 이 데이터를 신뢰할 수 있으며, 비즈니스 로직을 가질 수 있다.
Enity와 VO의 가장 큰 차이는
- Entity의 경우 속성이 같아도 ID가 다르면 다른 Entity이다.
VO의 경우 속성이 같다면 그것은 같은 객체이다.- Entity는 데이터베이스와의 상호작용을 위해 가변적 속성을 가질 수도 있고
속성이 변경되더라도 이는 같은 Entity이다.
VO는 불변성을 보장해야하며, 불변성이 깨져 속성이 변경되면 이는 다른 객체로 취급된다.
매우 유사하게 보이고 햇갈릴 수 있는 개념 3가지를 정리해 보았다.
Entity의 경우 익숙히 알고 있던 개념이었지만
DTO 와 VO는 생소했던 개념이라 공부하는 재미가 있었다.
또한 공부하면서 MVC패턴에 대한 이해가 부족하다는 느낌이 들어서
MVC패턴에 대해 더 공부해야겠다.