'매핑하지 않기' 전략
웹 계층, 애플리케이션 계층, 영속성 계층 모두 Account 클래스에 접근하여 같은 모델을 사용한다.
웹 계층과 영속성 계층은 모델에 대해 특별한 요구사항이 있을 수 있다. 도메인과 애플리케이션 계층은 특수한 요구사항에 관심이 없음에도 불구하고 Account 도메인 모델 클래스는 이런 모든 요구사항을 다뤄야 한다. 이는 단일 책임 원칙을 위반한다.
기술적인 요구사항이 아니더라도 각 계층이 특정 커스텀 필드를 두도록 요구할 수 있다.
모든 계층이 정확히 같은 구조의 같은 정보를 필요로 한다면 이 전략은 완벽한 선택지다.
그러나 애플리케이션 계층이나 도메인 계층에서 웹과 영속성 문제를 다루게 되면 곧바로 다른 전략을 취해야 한다. 어떤 매핑 전략을 선택했더라도 나중에 언제든 바꿀 수 있다.
'양방향' 매핑 전략
각 계층이 전용 모델을 가진 매핑 전략
웹 계층에서는 인커밍 포트에서 필요한 도메인 모델로, 인커밍포트에 의해 반환된 도메인 객체를 다시 웹 모델로 매핑한다.
영속성 계층에서는 아웃고잉 포트가 사용하는 도메인 모델과 영속성 모델 간의 매핑을 담당한다.(두 계층 모두 양방향으로 매핑)
장점
- 각 계층이 전용 모델을 갖고 있기 때문에 전용 모델을 변경하더라도 다른 계층에 영향이 없다.
- 매핑하지 않기 전략 다음으로 간단하며 매핑 책임이 명확하다.
단점
- 많은 보일러플레이트 코드가 생긴다. 매핑 프레임워크가 내부 동작 방식을 숨길 경우 매핑 로직을 디버깅하는 것이 어렵다.
- 도메인 모델이 계층을 넘어서 통신하는 데 사용되고 있다. 포트는 도메인 객체를 입력 파라미터와 반환값으로 사용한다. 바깥쪽 계층의 요구에 따른 변경에 취약해진다.
'완전' 매핑 전략
각 연산마다 별도의 입출력 모델을 사용한다.
SendMoneyUseCase 포트의 입력 모델로 SendMoneyCommand를 사용한다.
웹 계층은 입력을 애플리케이션 계층의 커맨드 객체로 매핑할 책임을 갖고있다. 각 유스케이스는 전용 필드와 유효성 검증 로직을 가진 전용 커맨드를 가진다. 그러고 나서 애플리케이션 계층은 커맨드 객체를 유스케이스에 따라 도메인 모델을 변경하기 위해 필요한 무엇인가로 매핑할 책임을 가진다.
더 많은 코드가 필요하지만 여러 유스케이스의 요구사항을 함께 다뤄야 하는 매핑에 비해 구현하고 유지보수하기 쉽다.
이 전략은 웹 계층과 애플리케이션 계층 사이에서 상태 변경 유스케이스의 경계를 명확하게 할 때 좋다. 애플리케이션 계층과 영속성 계층 사이에서는 매핑 오버 헤드 때문에 사용하지 않는 것이 좋다. 어떤 경우에는 연산의 입력 모델에 대해서만 이 매핑을 사용하고, 도메인 객체를 그대로 출력 모델로 사용하는 것도 좋다.
'단방향' 매핑 전략
모든 계층의 모델들이 같은 인터페이스를 구현한다. 이 인터페이스는 관련 있는 특성에 대한 getter 메서드를 제공해서 도메인 모델의 상태를 캡슐화한다.
도메인 자체는 풍부한 행동을 구현할 수 있고, 애플리케이션 계층 내의 서비스에서 이러한 행동에 접근할 수 있다. 도메인 객체가 인커밍/아웃고잉 포트가 기대하는 대로 상태 인터페이스를 구현하고 있기 때문에 도메인 객체를 바깥 계층으로 전달하고 싶으면 매핑 없이 할 수 있다.
바깥 계층에서는 상태 인터페이스를 이용할지, 전용 모델로 매핑할지 결정할 수 있다.
바깥 계층에서 애플리케이션 계층으로 전달하는 객체들도 이 상태 인터페이스를 구현하고 있다. 애플리케이션 계층에서는 이 객체를 실제 도메인 모델로 매핑해서 도메인 모델의 행동에 접근할 수 있게 된다.
만약 한 계층이 다른 계층으로부터 객체를 받으면 해당 계층에서 이용할 수 있도록 다른 무언가로 매핑한다. 그러므로 각 계층은 한 방향으로만 매핑한다. 하지만 매핑이 계층을 넘나들며 퍼져 있기 때문에 다른 전략에 비해 개념적으로 어렵다.
이 전략은 계층 간의 모델이 비슷할 때 가장 효과적인다. 읽기 전용 연산의 경우 상태 인터페이스가 필요한 모든 정보를 제공하기 때문에 웹 계층에서 전용 모델로 매핑할 필요가 없다.
언제 어떤 매핑 전략을 사용할 것인가?
그때그때 다르다.
언제 어떤 전략을 사용할지 결정하려면 팀 내에서 합의할 수 있는 가이드라인을 정해둬야 한다.
가이드라인은 어떤 상황에서 어떤 매핑 전략을 가장 먼저 택해야 하는지, 왜 해당 전략을 최우선으로 택해야 하는지 설명할 수 있어야 한다.
예를 들어, 변경 유스케이스를 작업하고 있다면
웹 계층과 애플리케이션 계층 사이에서는 유스케이스 간의 결합을 제거하기 위해 완전 매핑 전략을 첫 번째 선택지로 택해야 한다.
애플리케이션 계층과 영속성 계층 사이에서는 매핑 오버헤드를 줄이고 빠르게 코드를 짜기 위해 매핑하지 않기 전략을 첫 번째 선택지로 택해야 한다. 하지만 애플리케이션 계층에서 영속성 문제를 다뤄야 하게 되면 양방향 매핑 전략으로 바꿔야 한다.
쿼리 작업을 한다면
웹 계층과 애플리케이션 계층 사이, 애플리케이션 계층과 영속성 계층 사이에서는 매핑 오버헤드를 줄이고 빠르게 코드를 짜기 위해 매핑하지 않기 전략을 첫 번째 선택지로 택해야 한다. 하지만 애플리케이션 계층에서 영속성 문제나 웹 문제를 다뤄야 하게 되면 양방향 매핑 전략으로 바꿔야 한다.
유지보수 가능한 소프트웨어를 만드는 데 어떻게 도움이 될까?
인커밍/아웃고잉 포트는 서로 다른 계층이 어떻게 통신해야 하는 지를 정의한다. 여기에는 계층 사이에 매핑을 수행할지 여부와 어떤 매핑 전략을 선택할지가 포함된다.
각 유스케이스에 대해 좁은 포트를 사용하면 유스케이스마다 다른 매핑 전략을 사용할 수 있다.
매핑 가이드라인이 있으면 더 유지보수하기 쉬운 코드로 관리할 수 있다.
'📙 > Study' 카테고리의 다른 글
[만들면서 배우는 클린 아키텍처] 10. 아키텍처 경계 강제하기 (1) | 2024.10.18 |
---|---|
[만들면서 배우는 클린 아키텍처] 09. 애플리케이션 조립하기 (1) | 2024.10.17 |
[만들면서 배우는 클린 아키텍처] 07. 아키텍처 요소 테스트하기 (0) | 2024.10.15 |
[만들면서 배우는 클린 아키텍처] 06. 영속성 어댑터 구현하기 (0) | 2024.10.14 |
[만들면서 배우는 클린 아키텍처] 05. 웹 어댑터 구현하기 (0) | 2024.10.12 |