본문 바로가기
Develop/Design

[Clean Architecture] 경계 간 모델 매핑 전략

by 코딩의성지 2022. 4. 25.

이전 포스팅에서 헥사고날 아키텍처에 대해 포스팅을 좀 했었다.

https://devkingdom.tistory.com/341

 

[Clean Architecture] 계층형 아키텍처의 문제점을 해결하는 육각형 아키텍처(헥사고날 아키텍처)

얼마전에 계층형 아키텍처의 문제점에 다뤘었다. https://devkingdom.tistory.com/340 [Clean Architecture] 계층형 아키텍처의 문제점 최근에 "만들면서 배우는 클린 아키텍처"라는 책을 정독했다. 요즘 웹 아

devkingdom.tistory.com

 

 

오늘은 User 도메인에서 비밀번호 변경 로직을 처리하는 상황가정하고
각 계층의 모델을 어떻게 매핑할 지에 대해 포스팅 해보도록 하겠다.

 

매핑하지 않기 전략

 

매핑하지 않기 전략은 말그대로 매피없이 모든 계층의 입출력을 도메인 모델로 사용한다. 이설계는 아주 단순하게 작업이 가능하지만 비효율적인 작업을 해야하는 경우가 있다.

 

예를들면 웹계층에서 모델을 json 객체로 직렬화 하기위해 특정한 어노테이션을 특정필드에서 사용해줘야한다거나, ORM 프레임워크 사용시 데이터베이스 매핑을 위한 어노테이션을 사용해줘야하는 등 도메인 모델 자체에 여러 책임을 부여하게 된다. 이렇게 되면 결국 단일 책임원칙을 위반하는 경우가 생긴다.

 

하지만 이러한 설계기법이 무조건 안좋다는 뜻은 아니다. 단순한 CRUD만 수행하는 유스케이스에서는 이러한 설계는 오히려 완벽한 기능을 수행하는 설계가 될 수도 있다.

 

양방향 매핑 전략

 

양방향 매핑전략에서는 각계층이 전용으로 사용할 모델이 있다.

웹계층에서는 웹모델을, 도메인 계층에서는 도메인 모델을, 영속성 계층에서는 영속성 모델을 사용한다.

웹계층의 인커밍 포트에서 웹모델을 도메인 모델로 매핑을 하고 인커밍 포트에 의해 반환된 도메인 객체를 다시 웹모델로 매핑한다. 영속성 계층에서도 아웃고잉 포트가 사용하는 도메인 모델과 영속성 모델간의 매핑이 발생한다.

 

이러한 방식은 각 계층의 모델이 변경되더라도 다른 계층에 영향을 주지 않기에 각 계층의 모델에 책임을 명확하게 할 수 있다. 즉 단일 책임원칙을 철저하게 지킬 수 있다는 이야기이다.

 

하지만 이렇게 각 계층에 모델을 두면 보일러플레이트 코드가 만들어지게 되어 코드양이 늘어나게 된다. 또한 거대한 프로그램에서는 디버깅을 할때도 큰 비용이 들게 된다.

 

그리고 이 전약의 치명적인 단점은 결국 각 계층을 통신할때 도메인 모델이 사용된다는 것이다.

인커밍 포트에서는 도메인객체가 입력 파라미터로 쓰이고, 아웃고잉 포트에서는 도메인 객체가 반환값으로 사용되는데 이러한 구조는 바깥 계층의 요구에 따른 변경이 발생할 수 있다.

 

완전 매핑 전략

 

이 매핑전략에서는 각 연산의 과정마다 별도의 입출력 모델이 존재한다.  

웹계층에서는 어플리케이션 계층의 리퀘스트 객체로 매핑을 할 책임이 있고,

매핑된 리퀘스트 객체는 각 유스케이스에서 사용될 전용필드와 유효성 검증로직이 포함되어 있다.

그리고 어플리케이션 계층에서는 리퀘스트 객체를 유스케이스에 따라 도메인 모델로 매핑할 책임이 주어진다.

초기에 이렇게 설계를 해두면 코드가 굉장히 많아진다. 하지만 이렇게 해두면 유지보수 측면에서 매우 탁월한 선택이 될 수 있다.

 

웹-어플리케이션 계층 간에선 탁월한 선택일 될 수 있지만 어플리케이션-영속성 계층 간에서는 최악의 수가 될 수도 있다. 웹-어플리케이션 계층  매핑보다 어플리케이션-영속성 계층간 매핑은 오버헤드가 매우 심해 사용하지 않는 것을 추천한다.

 

단방향 매핑 전략

 

단방향 매핑전략이란 것도 존재한다.

동일한 상태를 구현하는 인터페이스를 하나 구현해서 각 계층은 다른계층으로 온 객체를 단방향으로 매핑하여 사용한다.

이 전략에서 상태 인터페이스는 attribute 에 대해 getter 메서드를 제공해 도메인 모델의 상태를 캡슐화해준다. 

도메인 모델에서 어떤 행동이 구현되더라도 애플리케이션 계층내의 서비스에서 이 행동에 자유롭게 접근할 수 있다. 그리고 도메인 객체를 바깥의 계층으로 전달하려고 할 때도 별도의 매핑없이 할 수도 있다.

그 이유는 도메인 객체가 인커밍/아웃고잉 포트가 동일한 상태를 구현하는 인터페이스를 구현하고 있기 때문이다.

 

바깥계층에서 어플리케이션 계층으로 전달하는 객체들도 마찬가지로 이 상태 인터페이스를 구현한다. 어플리케이션 계층에서는 이 객체를 도메인 모델로 매핑하여 도메인 모델의 행동에 접근한다.

 

이러한 매핑 방식은 어떤 상태로부터 도매인 객체를 재구성할 책임이 있따는 DDD 의 팩토리 개념과 어울린다. 

이 전략은 철저하게 매핑 책임을 명확하게 준다. 각 계층은 한 방향으로만 매핑을 한다. 개념적으로는 어렵지만 철저하게 책임을 줄 수 있다는 부분에서 매력적인 방법이 된다.

 

Ref.
톰 홈버그, 『만들면서 배우는 클린 아키텍처』, 위키북스(2021), p97~104

 

반응형

댓글