헥사고날 아키텍처 회고 (1)

2024. 2. 12. 20:41프로젝트/[EATceed] 몸무게 증량 어플

728x90

 

EATceed 프로젝트에서 헥사고날 아키텍처를 사용해보며, 고민해본 점을 서술해보려고 합니다.

먼저, 헥사고날 아키텍처를 도입한 이유입니다.

 

헥사고날 아키텍처를 도입한 이유

 

계층형 아키텍처는 데이터베이스 주도 설계를 유도

 

계층형 아키텍처는 엔티티를 비즈니스 모델처럼 사용해 도메인 로직뿐만아니라, 즉시 로딩/ 지연 로딩 트랜잭션 등등 영속성 관련 작업을 한 번에 처리하여 관심사의 분리가 제대로 되지 않았습니다.
따라서, 이번 프로젝트의 핵심 도메인은 "식사"관련 도메인들은 엔티티에 비즈니스 로직을 넣지 않고, 영속성과 도메인을 명확히 분리하여, 도메인 주도 설계를 하고자 하였습니다.

이렇게 함으로써 스키마에 변경이 생겼을 때 이것이 도메인 로직에 영향을 받지 않아 프로젝트를 진행하며 스키마 변경이 비교적 수월하였습니다.

 

 

유스케이스를 잘 드러내기 위해서

 

기존에 계층형 아키텍처를 사용했을 때, 넓은 범위의 Service 클래스를 사용하여, Service 클래스 내의 코드가 점점 많아졌습니다.

이는 기능을 추가하거나 기능에 변경사항을 반영하는 것이 어려워졌고, 테스트 코드를 작성하는 데도 불편하였습니다.

따라서, 이번 프로젝트에서는 유스케이스를 하나의 작업 단위만 수행하게끔 만들어 기능을 추가할 때 변경할 때, 유스케이스를 새롭게 만들거나 기존 유스케이스를 수정하면 되게끔 만들었습니다.

 

 

헥사고날 아키텍처를 적용하며 가졌던 고민

 

어떤 매핑 전략을 사용하지? 

 

헥사고날 아키텍처를 사용하며, 어떤 매핑 전략을 사용할 지 선택하는 게 어려웠습니다.

 

해당 아키텍처에 대한 경험이 부족하기 때문에 책에서 나온 가이드라인을 따라가며 매핑 전략을 사용했습니다.

책에 나온 가이드라인은 다음과 같습니다.

 

변경 유스케이스를 작업한다면, 웹 계층과 유스케이스 계층 사이에는 유스케이스간의 결합을 제거하기 위해 "완전 매핑" 전략을 처음으로 고려하라

 

 

해당 방식의 장점은 유스케이스별 유효성 검증 규칙이 명확해지고, 유스케이스에 필요한 필드만 넘길 수 있습니다.

(유스케이스의 재사용성이 증가합니다.)

 

변경 유스케이스를 작업한다면, 유스케이스 계층과 영속성 계층 사이에는 "매핑 하지 않기" 전략을 처음으로 고려해라

 

 

 

"매핑 하지 않기" 전략을 사용하면, 빠르게 코드를 작성할 수 있는 장점이 있습니다. 하지만 해당 전략을 사용하면, 영속성 엔티티가 유스케이스에 넘어와서 영속성 레이어와 도메인 레이어가 엄격하게 구분이 안 된다는 단점이 있습니다.

 

만약, 엄격하게 분리해야할 경우 "양방향 매핑 전략"을 사용해야합니다.

 

 

재활용 가능한 유스케이스를 만들자

 

프로젝트를 설계하면서, 가장 고민을 많이 하였던 부분이고 재미있었던 부분이었습니다.

말로 설명하기가 어려워 EATceed 프로젝트의 한 API를 예시를 들어보며 설명해보겠습니다.

 

간단하게 EATceed 프로젝트에 대해서 설명하자면, 해당 서비스의 목표는 "건강하게 증량하자"입니다.

따라서, "건강"하기 위해 증량하기 위해 신체 정보를 바탕으로 유지 칼로리와 목표 칼로리를 구하고, 오늘 먹은 음식을 바탕으로 앞으로 섭취해야하는 영양소를 구해야합니다. 

 

 

이에, 다음과 같은 유스케이스를 만들었습니다.

 

  • 몸무게를 유지하기 위해 섭취해야하는 영양소를 구하는 유스케이스
    • GetMaintainMealUsecase
  • 몸무게를 증량하기 위해 섭취해야하는 영양소를 구하는 유스케이스
    • GetTargetMealUsecase
  • 오늘 먹은 모든 음식의 영양소의 합을 구하는 유스케이스 
    • GetCurrentMealQuery

 

그리고, GetMaintainMealUsecase와 GetTargetMealUsecase에서는 Member 도메인을 사용해 유지 칼로리 및 영양소와 목표 칼로리 및 영양소를 구합니다.

 

 

유스케이스를 만들 때, 해당 유스케이스가 하나의 기능만 하면 되게끔 설계하였습니다. 

2개 이상의 기능을 하면 SRP 원칙에 지키지 못 해 변경의 이유가 하나 더 늘어나기 때문입니다.

 

 

EATCeed에서는

 

EATCeed에서는 단순 CRUD만을 수행하는 유스케이스의 경우에는 빠른 개발을 위하여 도메인 모델과 엔티티 모델을 분리하지 않고, 엔티티 모델에 비즈니스 로직을 구현하여 "매핑하지 않기" 전략을 사용하였습니다. 

 

또한, 복잡한 비즈니스 로직이 포함되어있는 유스케이스일 경우에는 도메인 계층을 영속성 모델으로부터 보호하기 위해서 "양방향 매핑 전략"을 사용하였습니다.

 

728x90