6.1. 의존성 역전

코어의 서비스가 영속성 어댑터에 접근하기 위해 포트를 사용한다.

코어의 서비스가 영속성 어댑터에 접근하기 위해 포트를 사용한다.

영속성 어댑터가 애플리케이션 서비스에 영속성 기능을 제공하기 위해 어떻게 의존성 역전 원칙을 적용하는지 보여준다.

애플리케이션 서비스에는 영속성 기능을 사용하기 위해 포트 인터페이스를 호출한다. 이 포트는 실제로 영속성 작업을 수행하고 DB와 통신할 책임을 가진 영속성 어댑터 클래스에 의해 구현된다.

헥사고날 아키텍처에서 영속성 어댑터는 ‘주도되는’ 혹은 ‘아웃고잉’ 어댑터다. 애플리케이션에 의해 호출될 뿐, 애플리케이션을 호출하지는 않기 때문이다.

포트는 사실상 애플리케이션 서비스와 영속성 코드 사이의 간접적인 계층이다. 영속성 문제에 신경 쓰지 않고 도메인 코드를 개발하기 위해(=영속성 계층에 대한 코드 의존성을 없애기 위해) 이런 간접 계층을 추가하고 있다. 이렇게 되면 영속성 코드를 리팩터링하더라도 코어 코드를 변경하지 않을 것이다.

자연스럽게 런타임에도 의존성은 애플리케이션 코어에서 영속성 어댑터로 향한다. 예를 들어, 영속성 계층의 코드 변경 중 버그가 발생하면 애플리케이션 코어의 기능은 망가질 것이다. 하지만 포트가 있으니 코어에 영향을 미치지 않으면서 영속성 코드를 마음껏 수정할 수 있다.

6.2. 영속성 어댑터의 책임

  1. 입력을 받는다.

    영속성 어댑터는 포트 인터페이스를 통해 입력을 받는다. 입력 모델은 인터페이스가 지정한 도메인 엔티티나 특정 DB 연산 전용 객체가 될 것이다.

  2. 입력을 DB 포맷으로 매핑한다.

    영속성 어댑터는 DB를 쿼리하거나 변경하는 데 사용할 수 있는 포맷으로 입력 모델을 매핑한다.

  3. 입력을 DB로 보낸다.

    ORM 대신 DB와 통신하기 위해 어떤 기술을 사용해도 상관없다. 입력 모델을 평범한 SQL 구문에 매핑해서 보내도 되고, 들어오는 데이터를 파일로 직렬화해서 읽어도 된다.

    핵심은 영속성 어댑터의 입력 모델이 영속성 어댑터 내부가 아니라 애플리케이션 코어에 있기 때문에 영속성 어댑터 내부를 변경하는 것이 코어에 영향을 미치지 않는다는 것이다.

  4. DB 출력을 애플리케이션 포맷으로 매핑한다.

    영속성 어댑터가 DB에 쿼리를 날리고 쿼리 결과를 받아온다. 이후 DB 응답을 포트에 정의된 출력 모델(애플리케이션 코어에 위치)로 매핑해서 반환한다.

  5. 출력을 반환한다.

입출력 모델이 영속성 어댑터가 아니라 애플리케이션 코어에 있다는 점을 제외하면 전통적인 영속성 계층의 책임과 크게 다르지 않다.

6.3. 포트 인터페이스 나누기