인프런 커뮤니티 질문&답변

code-tree님의 프로필 이미지

작성한 질문수

오브젝트 - 기초편

5-4-예제. 애플리케이션 객체 추가하기

DAO 관련 질문드립니다

해결된 질문

24.08.17 11:34 작성

·

111

1

안녕하세요 좋은 강의 감사합니다!

 

ReservationService에서 xxDAO를 인터페이스로 선언한 부분에서 질문드립니다.

 

아래와 같이 여러 persistence 클래스를 같이 사용하는 경우 결합도를 낮추려면 xxxDAO 구현체 내부에 jpaRepository, querydslRepository, jdbcRepository를 주입받는 것이 좋을까요?(이렇게 하면 xxxDAO를 인터페이스로 선언할 필요가 있나 고민도 됩니다)

public class xxxService {
    JpaRepository jpaRepository;
    QueryDslRepository queryDslRepository;
    JdbcRepository jdbcRepository;
}

 

답변 1

1

조영호님의 프로필 이미지
조영호
지식공유자

2024. 08. 17. 15:45

code-tree님 안녕하세요. 🙂

강의 재미있게 들어주시고 좋은 질문 남겨 주셔서 감사드립니다.

질문에 대한 답변을 두 가지로 나눠서 설명 드리도록 하겠습니다.

1) 다양한 영속성 메커니즘을 구현한 DAO 혼용

먼저 하나의 데이터베이스에 대해 영속성 메커니즘 별로 DAO(또는 Repository)를 나누는 것은 그렇게 좋은 방법은 아닙니다.

JPA는 영속성 컨텍스를 이용해서 엔티티들을 관리하기 때문에 예제에서 사용한 JdbcClient와 같이 영속성 컨텍스트를 인지하지 못하는 기술을 혼용할 경우 예상하지 못한 결과가 나올 수 있습니다.

또한 유지보수 측면에서도 혼란스러울 수 있는데 JPQL, QueryDSL, 네이티브 쿼리를 직접 사용하는 기술 모두 동일한 기능을 구현할 수 있기 때문에 어떤 DAO를 사용해야 하는지 기준을 정하기가 애매할 수 있습니다.

따라서 하나의 엔티티를 관리하는 경우라면 하나의 인터페이스 안에 구현 메커니즘에 독립적인 오퍼레이션을 정의하고 구현 클래스에서 오퍼레이션 레벨에서 서로 다른 영속성 메커니즘을 사용하는 것은 가능합니다.

하지만 너무 많은 영속성 메커니즘을 혼용하는 것은 좋지 않기 때문에 JPA를 사용하신다면 가급적이면 EntityManagerr와 QueryDSL 두 가지 종류만 혼용해서 사용하는 것으로 한정할 수는 없는지 고민해 보시는 것이 좋습니다.

시스템이 커지고 오퍼레이션이 커지면 비즈니스 로직을 구현하기 위한 Command와 조회를 위한 Query를 분리하는 CQRS에 대한 고민이 생길 수 있는데 이 경우에는 Command와 Query를 위한 DAO를 분리해서 구현할 수는 있습니다.

이 경우에는 Command를 위한 DAO는 JPA를, Query를 위한 DAO는 QueryDSL이나 네이티브 쿼리를 사용해서 구현할 수는 있겠지만 두 DAO에 대해 기술에 중립적인 인터페이스를 정의해서 Service를 영속성 메커니즘으로부터 분리시키는 것은 여전히 좋은 설계 방법입니다.

정리하면 영속성 메커니즘에 따라 DAO를 나누지 말고 DAO를 사용하는 클라이언트의 목적에 따라 DAO를 분리한 후에 적합한 영속성 메커니즘을 선택하는 것이 좋고 가급적이면 사용하시는 영속성 메커니즘의 수를 제한하고 기준을 명확하게 정의하시는 것이 좋습니다.

2) DAO에 인터페이스를 사용하는 이유

DAO에 인터페이스를 사용하는 이유는 다양한 DAO 구현체를 제공하기 위해서가 아니라 의존성을 끊기 위해서입니다.

(물론 테스트를 고려한다면 목과 스텁이라는 관점에서 여러 개의 DAO 구현체를 제공하기 위해 인터페이스를 제공한다고 말할 수 있습니다.)

의존성을 끊는 이유에 대해서는 제 블로그에 있는 아티클(의존성 끊기와 단위 테스트-1부, 의존성 끊기와 단위 테스트-2부)을 참고하시면 도움이 될거에요.

강의의 예제 코드를 보시면 Service가 영속성 메커니즘에 대해 의존하지 않도록 DAO를 인터페이스로 정의하고 DAO 구현 클래스들은 별도의 패키지 안에 구현했다는 것을 알 수 있습니다.

image.png

이렇게 인터페이스를 이용해서 Service 레이어를 영속성 메커니즘과 분리하면 관심사를 명확하게 분리할 수 있고 Service 레이어를 테스트하거나 재사용하기 용이해집니다.

이 경우 역시 의존성 역전 원칙(Dependency Inversion Principle)을 사용해서 결합도를 낮춘 예라고 할 수 있습니다.

답변이 됐는지 모르겠네요.

즐거운 하루 보내세요. :)

code-tree님의 프로필 이미지
code-tree
질문자

2024. 08. 18. 12:23

상세한 답변 감사합니다!!