ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [클린 아키텍처 06] 영속성 어댑터 구현하기
    프로그래밍/기타 2024. 9. 1. 18:50
    반응형

    << 클린 아키텍처 06 >>

    영속성 어댑터 구현하기

    의존성 역전

    영속성 계층 대신 애플리케이션 서비스에 영속성 기능을 제공하는 영속성 어댑터에 대해 말해보자

     

    application.service.Service-> application.port.out.Port <- adapter.out.persistence.Adapter 

     

    애플리케이션 서비스에서는 영속성 기능을 사용하기 위해 포트 인터페이스를 호출한다.

    이 포트는 실제로 영속성 작업을 수행하고 DB와 통신할 책임을 가진 영속성 어댑터 클래스에 의해 구현된다.

     

    영속성 어댑터는 '주도되는' 어댑터다. 

    애플리케이션에 의해 호출될 뿐, 애플리케이션을 호출하지는 않기 때문이다.

     

    포트는 사실상 애플리케이션 서비스와 영속성 코드 사이의 간적접인 계층이다.

    영속성 계층에 대한 코드 의존성을 없애기 위해 간접 계층을 추가하고 있다.

     

    영속성 어댑터의 책임

    영속성 어댑터가 하는 일

    1. 입력을 받는다.

    영속성 어댑터는 포트 인터페이스를 통해 입력을 받는다.

    입력 모델은 인터페이스가 지정한 도메인 엔티티나 특정 DB 연산 적용 개체가 될 것이다.

     

    2. 입력을 데이터베이스 포맷으로 매핑한다.

    데이터베이스를 쿼리하거나 변경하는데 사용할 수 있는 포맷으로 입력 모델을 매핑한다.

    (ex. JPA 엔티티 객체로 변환)

     

    3. 입력을 데이터베이스로 보낸다.

    4. 데이터베이스 출력을 애플리케이션 포맷으로 매핑한다.

    5. 출력을 반환한다.

     

    핵심은 영속성 어댑터의 입력 모델이 영속성 어댑터 내부에 있는 것이 아니라 애플리케이션 코어에 있기 때문에 

    영속성 어댑터 내부를 변경하는 것이 코어에 영향을 미치지 않는 것

     

    포트 인터페이스 나누기

    데이터베이스 연산을 정의하고 있는 포트 인터페이스를 어떻게 나눌까?

    보통 하나의 레포지토리 인터페이스에 넣어둔다!

    그렇게 되면 데이터베이스 연산에 의존하는 각 서비스는 인터페이스에서 단 하나의 메서드만 사용하더라도 하나의 '넓은' 포트 인터페이스에 의존성을 갖게 된다. 

     

    인터페이스 분리 원칙은 이 문제의 답을 제시한다

    클라이언트가 오로지 자신을 필요로 하는 메서드만 알면 되도록 특화된 인터페이스로 구성하자

     

    LoadAccountPort, UpdateAccountStatePort, CreateAccountPort 등등,...

     

    그렇게 되면 각 서비스는 실제로 필요한 메서드에만 의존가능! (좁은 포트 구현 = 플러그-앤드-플레이)

     

    영속성 어댑터 나누기

    하나의 Adapter가 아닌 AccountPersistenceAdapter, UserPersistenceAdapter 등등 

     

    도메인 코드는 영속성 포트에 의해 정의된 명세를 어떤 클래스가 충족시키는지 관심이 없다.

    모든 포트가 구현돼 있기만 하면 된다.

     

    애그리거트당 하나의 영속성 어댑터 접근 방식 또한 추후 여러 개의 바운디드 컨텍스트의 영속성 요구사항을 분리하기 위한 좋은 토대가 된다.

     

     

    스프링 데이터 JPA 예제

    예제코드 참조

     

    데이터베이스 트랜잭션

    트랜잭션은 하나의 특정한 유스케이스에 대해서 일어나는 모든 쓰기 작업에 걸쳐 있어야 한다.

    그중 하나라도 실패할 경우 다같이 롤백될 수 있기 때문이다.

     

    영속성 어댑터는 어떤 데이터베이스 연산이 같은 유스케이스에 포함되는지 알지 못한다

    -> 영속성 어댑터 호출을 관장하는 서비스에 위임하자 

     

    @Transactional
    public class SendMoneyService implements SendMoneyUseCase {
    }

     

    유지보스 가능한 소프트웨어를 만드는 데 어떻게 도움이 될까?

    좁은 포트 인터페이스를 사용하면 포트마다 다른 방식으로 구현할 수 있는 유연함이 생김

    포트 뒤에서 애플리케이션이 모르게 다른 영속성 기술 사용 가능 

    포트의 명세만 지켜진다면 영속성 계층 전체 교체 가능 

    반응형

    댓글

Designed by Tistory.