[목차]
1. 글의 목적
2. DAO(Data Access Object)
3. DTO(Data Transfer Object)
4. VO(Value Object)
5. Entity
6. Conclustion
| 글의 목적
- 이전에 쇼핑몰 클론 프로젝트를 하면서, 이번에 프로그래머스에서 강의를 듣고 과제를 하면서 여러번 접했던 용어입니다. DTO에 대해서만 어렴풋이 알았고 사용했기에 DAO를 들었을 때는 "어라? 비슷한건가?"라는 반응을, VO를 봤을 때는 "이건.. DTO랑 뭐가 다르지?"이런 궁금증을 가졌습니다. 그래서, 이번 기회에 그 개념과 차이를 정리하고자 작성했습니다!
| DAO
In computer software, a data access object (DAO) is a pattern that provides an abstract interface to some type of database or other persistence mechanism. By mapping application calls to the persistence layer, the DAO provides some specific data operations without exposing details of the database.(Wikipedia)
- DAO는 Data Access Object의 약자로, Database에 접근하는 역할을 하는 객체입니다.
- 프로젝트의 서비스 모델에 해당하는 부분과 데이터베이스를 연결하는 역할을 하며 데이터의 CRUD 작업을 시행하는 클래스입니다. 즉, DAO는 데이터에 대한 CRUD 기능을 전담한 오브젝트를 의미하는 것이죠.
- 이를 사용하는 사람은 자신에게 필요하거나 사용하려는 인터페이스를 DAO에게 넘겨주고 DAO는 이 인터페이스를 구현한 구현체를 사용자가 편리하게 사용할 수 있도록 반환해줍니다.
- 그렇다면, DAO를 사용하는 이유가 무엇일까?
- 효율적인 커넥션 관리와 보안성때문이다.
- DAO는 비즈니스 로직을 분리하여 도메인 로직으로부터 DB와 관련한 메커니즘을 숨기기 위해 사용합니다.
[DAO의 예제]
import java.sql.*;
public class DaoEx {
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/dao_db";
private static final String USER = "root";
private static final String PASSWORD = "********";
private Connection con;
private Statement stmt;
private ResultSet res;
public DaoEx() throws ClassNotFoundException {
Class.forName(DRIVER);
}
public void select() {
String sql = "SELECT * FROM vouchers";
try {
con = DriverManager.getConnection(URL, USER, PASSWORD);
stmt = con.createStatement();
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(res.getString("id") + " ");
System.out.println(res.getString("value") + " ");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public void close(Connection con, Statement stmt, ResultSet res) throws SQLException {
if (res != null)
res.close();
if (stmt != null)
stmt.close();
if (con != null)
con.close();
}
}
| DTO
In the field of programming a data transfer object (DTO) is an object that carries data between processes. The motivation for its use is that communication between processes is usually done resorting to remote interfaces (e.g., web services), where each call is an expensive operation.(Wikipedia)
- DTO는 Data Transfer Object의 약자로, 데이터를 전달하기 위한 객체입니다.
- 여러 레이어(Layer)간 데이터를 주고 받을 때 사용할 수 있는데 주로 View와 Controller 사이에서 활용된다.
- DTO는 getter / setter 메소드를 포함한다. 하지만, 이외의 다른 비즈니스 로직은 포함하지 않는다.
- DTO는 어떻게 구현하느냐에 따라 가변 객체로 활용할 수도 있고 불변 객체로 활용할 수도 있다.
[가변 객체로써의 DTO]
public class DtoEx {
private String name;
private int 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;
}
}
[불변 객체로써의 DTO]
public class DtoEx {
private final String name;
private final int age;
public DtoEx(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
- 가변 객체로써 DTO를 만들 때는 setter() 메소드를 이용하여 구현할 수 있습니다. 반대로, 불변 객체로써 DTO를 만들 때는 생성자를 이용해서 구현하며 getter() 메소드만 구현합니다. 이렇게 구현함으로써 데이터를 전달하는 과정에서 데이터의 불변성을 보장합니다.
| VO
Terminology
A value object is not a DTO. The two terms have been conflated by Sun/Java community in the past.(Wikipedia)
- VO는 Value Object의 약자로 비슷한 개념이지만 값 자체를 표현하는 객체입니다. 위의 정의에서도 나와있듯이 DTO를 말하는 용어가 아닙니다.
- VO는 getter() 메소드를 포함해서, 이외의 비즈니스 로직도 포함할 수 있습니다. 하지만, setter() 메소드는 가지지 않습니다.(오로지, 읽기 기능만 가능합니다!)
[VO 예제]
public class VoEx { static class Money{ private final int value; Money(int value) { this.value = value; } public int getValue() { return value; } public String printMoney(){ return this.value + "원"; } } }
- VO는 객체의 주소가 다르더라도, 값이 같을 경우 동일한 것으로 판단합니다. 그러므로, hashCode()메소드와 equals()메소드를 오버라이딩해줘야 합니다.
[VO 객체가 동일한지 확인하는 예제]
class VoExTest { @Test void isSame() { Money money1 = new Money(1000); Money money2 = new Money(1000); Assertions.assertEquals(money1, money2); } }
[hashCode(), equals() 메소드 오버라이딩]
@Override
public int hashCode() {
return Objects.hash(value);
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null || getClass() != obj.getClass())
return false;
Money money = (Money) obj;
if(value == money.value)
return true;
else
return false;
}
- (추가) DTO와 VO를 혼용해서 사용하는 경우가 많습니다. 저 또한 궁금해서 알아본 결과,
⌜Core J2EE Patterns: Best Practices and Design Strategies⌟ 책의 초판에서는 데이터 전송용 객체를 VO로 정의하였지만, 2판에서는 DTO로 정의해서 작성을 했기 때문에 혼동하는 경우가 발생했다고 합니다!
| Entity
- Entity는 실제 DB 테이블과 매핑이 되는 클래스입니다. 그렇기에 이 Entity를 기준으로 테이블이 형성되고, 칼럼이 변경되곤 합니다.
-> 그러므로, Entity를 데이터를 전달하는 클래스로 사용하면 안됩니다!
(Entity는 앞서 말씀드린대로, DB 테이블과 매핑되는 클래스이므로!) - Entity는 비즈니스 로직을 포함할 수도, setter() 메소드를 포함할 수도 있습니다.
[Entity 예제]
public class EntityEx {
private final Long id;
private final String name;
private final int value;
public EntityEx(Long id, String name, int value) {
this.id = id;
this.name = name;
this.value = value;
}
}
| Conclusion
- DTO / DAO / VO / Entity의 개념에 대해서 확실히 이해할 수 있었습니다. 그리고 공부하면서 DAO가 DTO, Entity와는 별개로 구분되어야하는 부분이라는 것을 알게되었습니다.(단순히.. 이름만 비슷한..)
- 이번에도 그렇고, 전 포스팅이었던 데드락을 공부할 때도 유투브의 테코톡에서 많은 공부를 했습니다. 우테코에서 공부를 하고 계시는 분들의 발표였는데 이해하기도 쉽고 영상도 짧아 자주 보면 좋을 것 같습니다!
- 정리표
DTO | VO | Entity | |
정의 | Layer간의 데이터 전송용 객체 | 값을 표현하는 객체 | DB 테이블에 대해 매핑하는 객체 |
상태 변경 여부 | 가변 혹은 불변 | 불변 | 가변 혹은 불변 |
로직 여부 | getter() / setter()메소드에 대한 로직만 포함한다. | setter() 메소드 이외의 메소드를 가진다. | 로직을 포함할 수 있다. |
(참고)
'Develop > JAVA' 카테고리의 다른 글
Java 디자인 패턴 다섯번째 이야기 - 전략 패턴(Strategy Pattern) (0) | 2021.08.16 |
---|---|
Java 디자인 패턴 네번째 이야기 - 팩토리 메소드 패턴(Factory Method Pattern) (0) | 2021.08.16 |
Java 디자인 패턴 세번째 이야기 - 빌더 패턴(Builder Pattern) (0) | 2021.08.13 |
Java 디자인 패턴 두번째 이야기 - 프록시 패턴(Proxy Pattern) (0) | 2021.08.10 |
Java 디자인 패턴 첫번째 이야기 - 싱글톤 패턴(Singleton Pattern) (0) | 2021.08.07 |