소개
만들면서 배우는 클린 아키텍처 책을 읽고 정리하며 소감을 적는 포스트입니다.
경계 간 매핑하기
늘상 겪는 문제인 각 계층의 모델을 매핑하는 것에 대해서는 거의 다뤄지지 않는다.
여러분도 매퍼 구현을 피하기 위해 두 계층에서 같은 모델을 사용하는 것에 대해 논의 해 본적이 있을 것이다.
매핑에 찬성하는 개발자
:
두 계층 간에 매핑을 하지 않으면 양 계층에서 같은 모델을 사용해야 하는데 이렇게 하면 두 계층이 강하게 결합됩니다.
매핑에 반대하는 개발자
:
하지만 두 계층 간에 매핑을 하게 되면 보일러플레이트 코드를 너무 많이 만들게 돼요. 많은 유스케이스들이 오직 CRUD만 수행하고 계층에 걸쳐 같은 모델을 사용하기 때문에 계층 사이의 매핑은 과합니다.
모두 틀린 말이 아니며 결정에 도움이 되는 매핑 전략에 대해 알아본다.
“매핑하지 않기” 전략
포트 인터페이스가 도메인 모델을 입출력 모델로 사용하면 두 계층 간의 매핑을 할 필요가 없다.
위 예제는 송금하기
유스케이스와 관련된 요소들이다.
웹 계층과 애플리케이션 계층 모두 Account 클래스에 접근해야 한다. 반대쪽의 영속성 계층과 애플리케이션 계층도 같은 관계이다. 모든 계층이 같은 모델을 사용하니 계층 간 매핑을 전혀 할 필요가 없다.
하지만 만약 JSON으로 직렬화하기 위해 어너테이션을 모든 클래스의 특정 필드에 붙여야 할 수도 있다. 또한 ORM을 사용한다면 데이터베이스 매핑을 위해 특정 어너테이션이 필요 할 수 도 있다.
이는 단일 책임 원칙
을 위반한다.
하지만 어너테이션으로 인해 코드가 지저분 해지지만 딱히 문제 없이 잘 돌아갈 것이다.
간단한 CRUD의 경우 매핑하지 않기 전략이 더 맞을 수도 있다.
“양방향” 매핑 전략
각 어댑터가 전용 모델을 가지고 있어서 해당 모델을 도메인 모델로, 도메인 모델을 해당 모델로 매핑할 책임을 가지고 있다.
두 계층 모두 양방향으로 매핑하기 때문에 양방향
매핑이라고 부른다.
각 계층의 전용 모델을 변경하더라도 다른 계층에는 영향이 없다.
이 매핑 전략은 웨이나 영속성 관심사로 오염되지 않은 깨끗한 도메인 모델로 이어진다.
하지만, 너무 많은 보일러플레이트 코드가 생긴다. 또한 도메인 모델이 계층 경계를 넘어서 통신하는 데 사용되고 있다.
인커밍 포트와 아웃고잉 포트의 도메인 객체를 입력 파라미터와 반환값으로 사용되고 있다.
어떤 매핑 전략도 철칙처럼 여겨져서는 안된다. 그 대신 각 유스케이스 마다 적절한 전략을 택해야 한다.
“완전” 매핑 전략
각 연산이 전용 모델을 필요로 하기 때문에 웹 어댑터와 애플리케이션 계층 각각이 자신의 전용 모델을 각 연산을 실행하는 데 필요한 모델로 매핑한다.
이 매핑 전략에서는 각 연산마다
별도의 입출력 모델을 사용한다. 계층 경계를 넘어 통신 할 때는 도메인 모델을 사용하지 않고 Command
, Request
와 같은 특화된 모델을 사용한다.
한 계층을 여러 개의 커맨드로 매핑하는 데는 하나의 웹 모델과 도메인 모델 간의 매핑보다 더 많은 코드가 생기지만 유지보수하기는 쉽다.
하지만 이 매핑 전략을 전역 패턴으로는 추천하지 않는다. 이 전략은 경계를 명확하게 할 때 가장 빛을 발한다.
“단방향” 매핀 전략
동일한 ‘상태’ 인터페이스를 구현하는 도메인 모델과 어댑터 모델을 이용하면 각 계층은 다른 계층으로부터 온객체를 단반향으로 매핑하기만 하면 된다.
이 전략에서는 모든 모델들이 같은 인터페이스를 구현한다. 도메인 모델 자체는 풍부한 행동을 구현할 수 있고, 애플리케이션 계층 내의 서비스에서 이러한 행동에 접근 할 수 있다.
이 매핑은 팩터리(factory)라는 DDD 개념과 잘 어울린다. DDD 용어인 팩터리는 어떤 특정한 상태로부터 도메인 객체를 재구성할 책임을 가지고 있다.
이 전략은 계층 간의 모델이 비슷할 때 가장 효과적이다.