웹 공부를하면서 자주 접하는 단어인 DAO, DTO, VO, Entity가 들을 때마다 헷갈려서 개념을 잡아 놓으려 정리하려 한다.
이름이 귀엽지 않은가
DAO는 Data Access Object로 말 그대로 DB의 데이터에 접근하는 객체이다.
DAO의 주요역할은 아래와 같다.
Java Spring기준으로 DAO는 여러 모양새를 가지고 있을 수 있다.
MyBatis는 DB Connection정보를 root-context.xml이라는 파일에 저장하고
JPA는 application.yml(properties)에 설정하여 사용한다.
DTO는 Data Transfer Object로 데이터를 전달하는 객체이다.
DTO는 Controller, View 등 레이어 사이에서 데이터를 전달하는 역할을 한다.
데이터를 전달하는게 역할을 가지는 객체이므로 서비스로직을 가지지 않는다.
데이터 전달 용도로 사용하는 객체이므로 당연히 서비스로직이 필요없다.
순수한 데이터객체로써 getter와 setter만 가진다.
public class DtoEx {
private String name;
private int age;
DtoEx(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
@Data //Setter, Getter, toString
@Builder //객체를 build 방식으로 생성할 수 있다.
@AllArgsConstructor //모든 필드 값을 매개변수로 받는 생성자
@NoArgsConstructor //매개변수가 없는 생성자
public class DtoHasSetter {
private String name;
private int age;
}
VO는 Value Object로 값 그 자체의 객체이다.
그냥 쉽게 Setter가 없는 DTO라고 보면 될 것 같다.(Getter만 존재 할 수 있다.)
즉 VO는 한 번 생성하면 변경이 불가하다(read-Only)
그렇기에 새로운 값을 사용하려면 새로운 VO를 생성해야한다.
또한 VO는 모든 필드값이 같으면 두 객체는 같다는 정의를 가진다.
이를 위해 equals()와 hashCode()의 오버라이딩이 필요하다.
@Getter
public class VoEx {
private final String name;
private final float height;
public VoEx(String name, float height) {
this.name = name;
this.height = height;
}
@Override
public int hashCode() {
return Objects.hash(name, height);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if(!(obj instanceof VoEx)) return false;
VoEx o = (VoEx)obj;
return Objects.equals(name, o.name) && height == o.height;
}
}
public static void main(String[] args) {
VoEx original = new VoEx("Max",182.2f);
VoEx same = new VoEx("Max", 182.2f);
boolean equals = original.equals(same);
System.out.println(equals);
}
// 출력 : true
// equals오버라이딩 안할 시 false가 출력된다)
Entity는 실제 DataBase의 테이블과 1:1 매핑되는 클래스이다.
고로 Entity는 DB 테이블의 존재하는 칼럼만을 필드로 가져야 한다.
테이블에 존재하지 않는 속성을 가져서도 안된다.
또한 Entity 기준으로 테이블이 형성되므로 Entity의 값이 바뀌면 DB에 반영된다.
Entity는 데이터를 전달하는 용도로 사용하면 안된다.
즉, DTO와 분리하여 사용하여야 한다.
추가로 Entity는 비즈니스 로직을 포함할 수도, setter() 메소드를 포함할 수도 있습니다.
@RequiredArgsConstructor
public class Order {
private final int id;
private final String customerId;
private LocalDateTime orderDate;
private int totalPrice;
private Oder_Status status;
//상태변경 비지니스 로직 가능
public void setStatus(Oder_Status status) {
this.status = status;
}
//id 기준으로 동일성 판단
@Override
public boolean equals(Object o) {
if (!(o instanceof Order order)) return false;
return id == order.id;
}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
}
공부하면서 자주 접하는 DAO, DTO, VO, Entity 개념을 그동안 다소 모호하게 알고 있었는데, 이번 글을 통해 가볍게나마 각 개념을 정리할 수 있었다.
단순히 개념을 읽고 이해하는 데 그치지 않고, 간단한 예제를 직접 만들어보며 코딩해 본 경험이 개념을 더 잘 체득하는 데 큰 도움이 되었다.