• 각 계층의 모델을 매핑
    • 두 계층 간에 매핑을 하지 않으면 양 계층에서 같은 모델을 사용해야 하는데 이렇게 하면 두 계층이 강하게 결합된다.
  • 각 계층의 모델을 매핑하지 않음
    • 두 계층 간에 매핑을 하게 되면 보일러플레이트 코드를 너무 많이 만들게 된다. 많은 유스케이스들이 오직 CRUD만 수행하고 계층에 걸쳐 같은 모델을 사용하기 때문에 계층 사이의 매핑은 과하다.

‘매핑하지 않기’ 전략

  • 웹 계층, 애플리케이션 계층, 영속성 계층 모두 같은 Account 모델을 사용한다.
  • 장점:
    • 매핑할 필요가 전혀 없어서 단순하다.
  • 단점:
    • 웹 계층과 영속 성 계층에 필요한 요구사항에 의해 관련 어노테이션을 붙여야 할 수 있다.(단일 책임 원칙 위반)
    • 기술적인 요구사항이 아니더라도, 각 계층에서만 필요로 하는 필드들을 포함하는 파편화된 도메인 모델로 이어질 수 있다.
  • 간단한 CRUD의 경우는 이 전략을 사용할 수 있다.
    • 모든 계층이 정확히 같은 구조, 같은 정보를 필요로 한다면 좋은 선택지다.
    • 그러나 애플리케이션 계층이나 도메인 계층에서 웹과 영속성 문제를 다루게 되면 곧바로 다른 전략을 취해야 한다.

‘양방향’ 매핑 전략

  • 각 계층이 도메인 모델과 완전히 다른 구조의 전용 모델을 가지고 있다.
  • 장점:
    • 웹이나 영속성 관심사로 오염되지 않는 깨끗한 도메인 모델로 이어진다.
    • ‘매핑하지 않기’ 전략 다음으로 간단한 전략이다.
  • 단점:
    • 너무 많은 보일러플레이트 코드가 생긴다.
    • 도메인 모델이 계층 경계를 넘어서 통신하는 데 사용되고 있다.

‘완전’ 매핑 전략

  • 각 연산마다 별도의 입출력 모델을 사용한다.
    • 계층 경계를 넘어 통신할 때 도메인 모델을 사용하는 대신 SendMoneyUseCase 포트의 입력 모델로 동작하는 SendMoneyCommand처럼 각 작업에 특화된 모델을 사용한다.
    • 웹 계층은 입력을 애플리케이션 계층의 커맨드 객체로 매핑할 책임을 가지고 있다.
    • 애플리케이션 계층은 커맨드 계층을 유스케이스에 따라 도메인 모델을 변경하기 위해 무엇인가로 매핑할 책임을 가진다.
  • 장점:
    • 여러 유스케이스의 요구사항을 함께 다뤄야 하는 매핑에 비해 구현하고 유지보수하기가 쉽다.
  • 이 매핑 전략은 전역 패턴으로 추천하지 않는다.
    • 웹 계층과 애플리케이션 계층 사이에서 상태 변경 유스케이스의 경계를 명확하게 할 때 가장 빛을 발한다.
    • 애플리케이션 계층과 영속성 계층 사이에서는 매핑 오버헤드 때문이다.

‘단방향’매핑 전략

  • 모든 계층의 모델들이 같은 인터페이스를 구현한다.
    • 이 인터페이스는 관련 있는 특성에 대한 getter 메서드를 제공해서 도메인 모델의 상태를 캡슐화 한다.
  • 장점:
    • 도메인 모델 자체는 풍부한 행동을 구현할 수 있고, 애플리케이션 계층 내의 서비스에서 이러한 행동에 접근할 수 있다.
    • 도메인 객체를 바깥 계층으로 전달하고 싶으면 매핑 없이 할 수 있다.
      • 도메인 객체가 인커밍/아웃고잉 포트가 기대하는 대로 상테 인터페이스를 구현하고 있기 때문이다.
      • 바깥 계층에서는 상태 인터페이스를 이용할지, 전용 모델로 매핑할지 결정할 수 있다.
      • 행동을 변경하는 것이 상태 인터페이스에 의해 노출돼 있지 않기 때문에 실수로 도메인 객체의 상태를 변경하는 일은 발생하지 않는다.
  • 단점:
    • 매핑이 계층을 넘나들며 퍼져 있기 때문에 이 전략은 다른 전략에 비해 개념적으로 어렵다.
  • 이 전략은 계층 간의 모델이 비슷할 때 가장 효과적이다.

언제 어떤 매핑 전략을 사용할 것인가?

  • 각 매핑 전략이 저마다 장단점을 갖고 있기 때문에 한 전략을 전체 코드에 대한 어떤 경우에도 변하지 않는 전역 규칙으로 정의 하려는 충동을 이겨내야 한다.
  • 같은 코드에 여러 패턴을 섞으면 어수선하게 느껴질 수 있지만, 고정된 매핑 전략으로 유지하는것보다는 빠르게 코드를 짤 수 있는 간단한 전략으로 시작해서 계층 간 결합을 떼어내는 데 도움이 되는 복잡한 전략으로 갈아타는 것도 괜찮은 방법이다.
  • 언제 어떤 전략을 사용할지 결정하려면 팀 내에서 합의할 수 있는 가이드라인을 정해둬야 한다. 아래는 예시다.
    • 변경 유스케이스를 작업하고 있다면 웹 계층과 애플리케이션 계층 사이에서는 유스케이스 간의 결합을 제거하기 위해 ‘완전 매핑’ 전략을 첫 번째 선택지로 택해야 한다.
    • 변경 유스 케이스를 작업하고 있다면 애플리케이션과 영속성 계층 사이에서는 매핑 오버헤드를 줄이고 빠르게 코드를 자기 위해 ‘매핑하지 않기’ 전략을 첫 번째 선택지로 사용한다. 하지만 애플리케이션 계층에서 영속성 문제를 다뤄야 하게 되면 ‘양방향’ 매핑 전략으로 바꿔서 영속성 문제를 영속성 계층에 가둘 수 있게 한다.
    • 쿼리 작업은 매핑 오버헤드를 줄이고 빠르게 코드를 짜기 위해 ‘매핑하지 않기’ 전략을 사용한다. 하지만 애플리케이션 계층에서 영속성 문제나 웹 문제를 다뤄야하게 되면 ‘양방향’ 매핑 전략으로 바꿔야 한다.