1. DAO
DAO객체는 Data Access Object의 약자로 Database의 data에 access하는 트랜잭션 객체입니다.
웹서버는 DB와 연결하기 위해서 매번 커넥션 객체를 생성하는데, 이것을 해결하기 위해 connection Pool을 사용합니다. Connection Pool 이란 connection 객체를 미리 만들어 놓고 그것을 가져다 쓰고, 다쓰고 난 후에는 반환해 놓는 것입니다. 하지만 유저 한명이 접속해서 한번에 하나의 Connection만 일으키는 것이 아니라 많은 Connection을 만들기 때문에, Connection Pool은 오버헤드를 효율적으로 하기 위해 DB에 접속하는 객체를 하나 만들고, 모든 페이지에서 그 객체를 호출해 사용합니다. 이렇게 커넥션을 하나만 가져오고 그 커넥션을 가져온 객체가 모든 DB와의 연결을 하는것이 바로 DAO객체입니다.
즉,
- 데이터베이스 관련 작업 수행
- 데이터베이스에 CRUD 작업 수행
라고 할 수 있습니다.
- 예시 코드
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class CustomerDAO {
private static final String driver = "com.mysql.cj.jdbc.Driver";
private static final String url = "jdbc:mysql://localhost/order_mgmt";
private static final String user = "root";
private static final String pwd = "root1234!";
private Connection con;
private Statement stmt;
public List<Customer> findAll() {
List<Customer> list = new ArrayList<Customer>();
try {
connDB();
String query = "select * from customer";
System.out.println(query);
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String id = rs.getString("customer_id");
String name = rs.getString("name");
String email = rs.getString("email");
LocalDateTime last_login_at = rs.getTimestamp("last_login_at");
LocalDateTime created_at = rs.getTimestamp("created_at");
int black = rs.getInt("black");
Customer customer = new Customer();
customer.setId(id);
customer.setName(name);
customer.setEmail(email);
customer.setLastLoginAt(last_login_at);
customer.setCreatedAt(created_at);
customer.setBlack(black);
list.add(customer);
}
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
private void connDB() {
...
}
}
2. repository
repository는 DDD(Domain-Driven Design)에서 처음 등장한 개념입니다.
repository는 데이터를 저장하고 불러오는 로직을 담당하는 객체입니다. 도메인 레이어는 repository를 통해서 데이터베이스에 저장된 데이터와 별개로 단순하게 추상화된 객체를 반환 받을 수 있습니다. 때문에 repository를 사용하는 측에서는 데이터베이스 연결 상태나 SQL 구문 등에 대한 걱정 없이 아이템을 추가, 수정, 삭제하는 작업을 할 수 있습니다.
DDD에서 데이터베이스는 레포지토리를 통해서만 업데이트 합니다. 어그리게이트 루트(Aggregate Root) 별로 한 개의 레포지토리를 가지며, 레포지토리의 각 동작은 단위 작업 기준으로 구성합니다. 이 때 단위 작업은 하나의 트랜잭션(Transaction)을 기준으로 생각할 수 있습니다. 엔티티, 밸류 오브젝트의 변경 사항은 도메인 레이어에서 수행되며, 레포지토리를 포함하는 데이터 레이어에서는 해당 변경 사항을 적용하는 것에 집중합니다.
3. 차이점
일반적인 웹 어플리케이션 아키텍쳐는 다음과 같습니다.
Presentation 계층은 View,
Application 계층은 service,
domain 계층은 model,
infrastructure 계층은 Persistent 계층이라고도 부르고
db, 외부 라이브러리 등의 인프라를 의미합니다.
- 아키텍쳐 구조에서 DAO
만약 DAO를 사용하고자 할 때, service에서 new를 하여 생성했다고 가정해본다면, service 로직을 담당하는 객체와 db와 관련된 api가 강한 결합을 가지며, infrastructure와 관련된 로직이 service 로직에 생성됩니다.
이런 상황을 방지하기위해 사용하는 것이 DTO(Data Transaction Object)입니다. 데이터를 service로 전송하기 위해 TO를 사용하는 것을 통해 레이어 사이의 결합을 약하게 할 수 있습니다.
- 아키텍쳐 구조에서 Repository
repositoy는 웹 어플리케이션 아키텍쳐에서 어디에 속한다고 할수 있을까요?
단순하게 생각하면 db와 같은 영구저장소를 사용하기위한 것이기 때문에 infrastructure 계층이라고 생각할 수 있습니다. 하지만, Repository는 영구저장소라기 보다는 객체의 상태를 관리하는 저장소라고 하는게 더 정확합니다.
즉, Repository의 구현이 파일시스템으로 만들어졌는지, HashMap으로 구현됐는지는 상관없고, 객체(entity)에 대한 CRUD를 수행할 수 있으면 됩니다.
repository는 객체를 위한 컬렉션일 뿐이고, repository의 내부 구현과는 관계없이 method의 기능을 사용하면 되는 것입니다. 이러한 이유로 Repository의 인터페이스를 도메인 로직으로 구분합니다. 따라서 서비스로직에서 Repository의 인터페이스를 사용할 수 있게 됩니다.
이런 방식으로 사용해도 레이어 사이의 관계가 유지되는 이유는 Repository를 사용하는 클라이언트는 Repository가 어떻게 구현되어 있는지 모르고, 인터페이스를 통하여 그 기능을 사용하기 때문입니다. 하지만, 실제로 바인딩 되는 콘크리트 객체는 infrastructure 레이어에 속해 있는 것입니다.
즉, 우리가 일반적으로 사용하는 관점에서 Repository의 Interface는 도메인 레이어, Repository의 구현체는 infrastructure 레이어에 속합니다. 이를 통해 도메인 레이어와 infrastructure 레이어의 의존성이 뒤집힙니다.
- 결론
DAO는 이름에서도 드러나듯이 자신이 영속성 객체라는것을 숨기지 않고, 자신이 infrastructure 레이어에 있다는 걸 숨기지 않습니다. 또한 계층(모듈)의 의존성을 봤을 때 도메인이 infrastructure에 의존합니다. 따라서 DAO를 이용해 바로 entity를 컨트롤 하는것은 계층을 무너트리고 잘못된 사용이기 때문에 항상 DTO를 사용하여 데이터를 주고받아야 합니다.
그에 반해, Repository는 자신이 영속성 객체임을 숨깁니다. 자신이 infrastructure 레이어에 있다는 것을 숨기고, interface를 통해 의존성이 역전되어 있기 때문에, entity를 그대로 가져와 영속성 로직을 수행하는 것을 가능하게 합니다.
마지막으로 Repository는 도메인 설정 단계에서 하나의 개념 단위로 묶인 aggregate를 도출하는 과정에서 자동으로 식별됩니다. 이것은 Repository 식별 과정이 DDD에 영향을 받는다는 것을 의미합니다.
반면에 DAO는 데이터베이스 테이블 별로 생성되는 것이 일반적이며 infrastructure 레이어에 대한 출입문 역할을 수행합니다. 따라서 DAO 식별 과정은 DDD 보다는 데이터베이스 테이블의 단위에 영향을 받는 경향이 강합니다.
즉, infrastructure 레이어에 대한 출입문 역할을 하는 객체가 추가될 때는 DAO 이고,
도메인 레이어가 DDD로 구성되고 도메인 레이어 내에 객체 컬렉션에 대한 인터페이스가 필요한 경우에는 REPOSITORY입니다.
reference
https://genesis8.tistory.com/214
https://tech.buzzvil.com/handbook/repository/
https://bperhaps.tistory.com/entry/Repository%EC%99%80-Dao%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90
http://aeternum.egloos.com/1160846
'JAVA' 카테고리의 다른 글
디자인 패턴 - 상태 패턴 (0) | 2021.11.18 |
---|---|
SpringBoot Controller 매개변수 애너테이션의 종류 (0) | 2021.10.05 |
Proxy 객체 (0) | 2021.09.07 |
proxy 패턴 (0) | 2021.09.07 |
디자인 패턴 (0) | 2021.08.06 |