[DDD] DDD에서의 리포지터리 구현

DaeHoon·2022년 12월 12일
0

  • 기존 서버 api에서는 Repository Layer에서 직접 리포지토리를 구현을 하고 있는 상태입니다. 즉, 리포지토리의 기술에 의존하게 되어 구현 기술이 변경되면 서비스 코드도 변경해야 됩니다.

  • 서비스 코드 입장에서 봤을 때 중요한 건 서비스에 대한 비즈니스 로직이지 리포지토리가 어떤 방식(querydsl, Jpa naming 메소드 등)으로 구현 되어있는 지 중요하지 않습니다. 이를 인터페이스를 이용해 구현해보겠습니다. 코드는 Escrow Headroom인 적립금 개편을 예로 들었습니다.

Repository (Domain)

interface MemberPointListRepository{
  fun searchMemberPointList(searchParam: MemberPointSearchServiceDto): Page<MemberPointSearchResult>
  fun findAllByMemberNo(memberNo: Long): List<MemberPointListJpaEntity>
  fun save(memberPointListJpaEntity: MemberPointListJpaEntity): MemberPointListJpaEntity
  fun findByIdOrNull(memberPointListNo: Long): MemberPointListJpaEntity?
}
  • 저수준 모듈을 추상화한 인터페이스입니다. 이 인터페이스는 에그리거트 당 하나 씩 존재합니다.

JpaRepository (Infrastructure)

interface MemberPointListJpaRepository: JpaRepository<MemberPointListJpaEntity, Long> {
  fun findAllByMemberNo(memberNo: Long): List<MemberPointListJpaEntity>
}
  • 그리고 기존 Repository Layer에서 직접 사용되었던 JpaRepository를 Infrastructure Layer으로 옮겨줍니다.

RepositoryImpl (Infrastructure)


@Component
class MemberPointListRepositoryImpl(
  private val jpaQueryFactory: JPAQueryFactory,
  private val memberPointListJpaRepository: MemberPointListJpaRepository
): MemberPointListRepository  {
  override fun searchMemberPointList(searchParam: MemberPointSearchServiceDto): Page<MemberPointSearchResult> {

    val query = jpaQueryFactory
      .select(MemberPointSearchResult.toQ())
      .from(memberPointListJpaEntity)
      
    searchParam.savingSubtractionDivisionCode?.let {
      query.where(memberPointListJpaEntity.savingSubtractionDivisionCode.eq(searchParam.savingSubtractionDivisionCode))
    }

    searchParam.pointTypeCode?.let {
      query.where(memberPointListJpaEntity.pointTypeCode.eq(searchParam.pointTypeCode))
    }

    searchParam.pointOccurAgentTypeCode?.let {
      query.where(memberPointListJpaEntity.pointOccurAgentTypeCode.eq(searchParam.pointOccurAgentTypeCode))
    }

    return PageImpl(query.fetch(), PageRequest.of(searchParam.pageNo, searchParam.pageSize), query.fetchCount())
  }

  override fun findAllByMemberNo(memberNo: Long)  = memberPointListJpaRepository.findAllByMemberNo(memberNo)
  override fun save(memberPointListJpaEntity: MemberPointListJpaEntity) = memberPointListJpaRepository.save(memberPointListJpaEntity)
  override fun findByIdOrNull(memberPointListNo: Long) = memberPointListJpaRepository.findByIdOrNull(memberPointListNo)
}
  • Domain의 Repository를 Infrastructure Layer에서 구현했습니다.
  • JpaRepository는 생성자 주입 방식으로 의존성을 주입시켜줍니다.

결과

  • 추상화한 인터페이스는 고수준 모듈로 인터페이스를 구현한 코드들은 인프라스트럭처 계층에서 설계하게 끔 역할을 나누어 인프라스트럭처에 대한 의존을 낮췄습니다.
  • 또한 querydsl을 사용하기 위해 만들었던 RepositoryCumtom, RepositoryCumtomImpl 객체를 만들 필요가 없어 관리 포인트도 줄어들게 되었습니다.
profile
평범한 백엔드 개발자

0개의 댓글