서론
Spring MVC를 사용할 때는 DAO를 데이터베이스를 연결하는 객체로 생각하고 여기에 SQL문을 다 넣었었다. JPA를 배우고 난 뒤에 JpaRepository를 구현하면서 DAO는 자연스럽게 Repository로 생각하고 넘겼었다.
그러다 이 둘의 차이를 묻는 질문 글을 발견했고 그 답변의 내용이 상당히 어려웠다. 조금이나마 이해한 것을 번역하면서 글로 정리하지 않으면 다 잊어버릴까 봐 이렇게 글로 나마 정리한다.
내가 이해한 것을 토대로 작성하기 때문에 틀린 내용이 많을 수도 있다.
이 글은 답변 글 번역에 단순히 내 생각을 덧붙인 글로 나는 명확한 차이를 모르겠다.
#1
- DAO는 data persistence의 추상화다.
- Repository는 a collection of objects의 추상화다.
- DAO는 데이터베이스와 관련이 많으며 Table 중심이다.
- Repository는 도메인과 관련이 많으며 Arggregate Roots만을 다룬다.
Repository는 여러 DAO를 사용해 구현될 수 있지만, 그 반대의 경우는 불가능하다.
또한 Repository는 보통 한정된 인터페이스다. 단순히 Get(id), Find(Specification), Add(Entity)와 같은 객체들의 collection이다.
Update 같은 메소드는 DAO에 적합하며 Repository와는 맞지 않는다. Repository를 사용할 때는, 보통 분리된 UnitOfWork(비즈니스 로직 수준의 트랜잭션)에 의해 엔티티들의 변화가 관리된다.
실제로 흔히들 Repository라고 부르지만 DAO와 가까운 것들이 많다. 그래서 아마 둘의 차이가 명확하지 않은 것이다.
#2
둘 다 비슷하지만 DAO가 Repository보다 좀 더 유연한 패턴이다. 만약 둘 다 쓰고 싶으면, DAO에서 Repository를 사용한다.(?)
Repository:
객체들의 특정 타입의 저장소다. 특정 타입의 객체들을 찾을 수 있고 저장할 수 있다. 보통 객체들의 한가지 타입만 다룬다. 예를 들어 아래의 경우와 같이 쓰인다.
// AppleRepositor
List<Apple> findAll(Creteria criteria);
Apple save(Apple apple);
그리고 DDD 용어라는 것을 기억해라. 데이터베이스 용어가 아니다. 고로 데이터베이스에 저장되는 것과는 아무 상관이 없다.
Repository는 대부분 같은 테이블에 모든 데이터를 저장한다. 반면 패턴은 요구되지 않는다. 그러나 단일 타입의 데이터만 처리하기 때문에 하나의 기본 테이블에 논리적으로 연결된다.
DAO:
데이터를 저장한다. 같은 데이터 타입인지 아닌지는 상관하지 않으며, 따라서 관련된 데이터를 저장하는 DAO를 별 제약 없이 쉽게 생성할 수 있다.
예를 들어 UserDao 메소드는 아래의 경우도 가능하다.
// UserDao
Collection<Permission> findPermissionsForUser(String userId)
User findUser(String userId)
Collection<User> findUsersForPermission(Permission permission)
User와 관련된 모든 것들은 하나의 DAO안에 있을 수 있다. Repository는 불가능하다.
#3
DAO와 Repository는 모두 DAL(Data Aceess Layer)의 구현체다. DAL은 뭐냐?
DB와 연결된 객체지향 어플리케이션들은 반드시 DB 관련 정보들을 처리해야 한다. 그러기 위해서는 그 코드들을 깔끔하게 모듈화 해야하는데, Layerd Architecture에서 이 모듈이 바로 DAL이다.
그럼 이 DAL을 어떻게 모듈화 하냐? 어떻게 코드로 구현하냐?
스프링에서는 Hibernate를 사용해 구현하고 있고 그것이 바로 DAO패턴이다.
DAO패턴은 DAL을 생성하나는 한 방법이고 보통 도메인 엔티티마다 자신의 DAO를 가지고 있다.
예를 들어 User는 UserDao, Appointment는 AppointmentDao.
그럼 Repository는 어떨까? DAO와 비슷하게, Repository 또한 DAL를 구현하는 방법 중 하나이다. 이 패턴의 중요한 점은 사용자의 관점에서의 collection처럼, 보고 행동해야 한다는 것이다. 여기서 collection은 자바 객체 collection이 아니다. 이건 더하고 빼고 포함하는 것과 같은 연산들이다.
예를 들어 하이버네이트의 경우 Repository의 패턴은 DAO로 실체화되어있다. 이것은 DAL이며 DAO 패턴임과 동시에 Repository다.
Repository 패턴이 반드시 DAO 상위에 구축되는 것은 아니다. 위에 언급했던 연산들을 지원하는 인터페이스로 설계된 DAO는 Repository 패턴의 객체다. 만약, DAO가 이미 위의 연산들의 작업을 지원한다면 그 위에 추가 레이어(Repository)가 필요한 이유가 있을까?
예를 들어 PetType Table(name: 고양이, type: 포유류) Pet Table(name: 냐옹이, breed: 페르시안 고양이)과 같은 모델이 있다고 가정해보자.
PetType | |
name | 고양이 |
type | 포유류 |
Pet | |
name | 야옹이 |
breed | 페르시안 고양이 |
그럼 우리가 해왔던 것 처럼 PetTypeDao, PetDao가 있을 것이다. 만약 PetType에 없는 종류의 Pet을 DB에 추가하고 싶을 경우(예를 들면, 푸들), 우리는 Dao 상위에 Repository interface에 메서드를 생성해 두 개의 DAO를 묶을 수 있다. 이러한 구조는 DAO들 간의 결합도를 낮춰 유지보수에 용이하다.
결론
내가 영어가 부족해서 그런지는 몰라도 말하는게 조금씩 다른 것 같기도 하다. 그나마 제일 이해가 잘 됐던 건 #3 답변 글이었다. 내가 내린 결론은 DAO와 Repository의 차이는 크지 않다. DAL을 구현하는 방식의 차이다.
Repository는 DDD 용어이기 때문에 도메인 중심으로 설계되어 Domain의 Aggregate당 하나씩 보통 생성된다. 그래서 자연스럽게 Aggregate Root와 관계된 Objects들의 연산(Collection)으로 구성되어 있으며 그 타입은 Aggregate Root 하나인 것이다.
아직 DDD에 이해가 부족하기 때문에 좀 더 공부하면 명확해질 것 같다.
DAO의 경우에는 Table로 생각하는 Model(일반적인 MVC에서 Model)에 하나씩 생성하면 된다.
즉, Repository와 DAO는 하는 역할은 거의 같지만 DAL 구현하는 방식에서 조금 차이 나는 것이다.
위와 같은 이유 때문에 DAO가 좀 더 유연하고 일반적이라 하는 것 같다.
'Backend > Java' 카테고리의 다른 글
@RequestBody 모델에 기본생성자, setter/getter가 필요한가? (4) | 2021.01.21 |
---|---|
parse, valueOf 차이와 문제점 (0) | 2021.01.21 |
[Spring Boot] 유효성 검사 (0) | 2020.12.16 |
[JSP] 쿼리문 실행 오류 (0) | 2020.07.09 |
[JSP] 한글 인코딩 (0) | 2020.05.28 |