오늘은 열심히 작업한 Member 도메인을 어떤 흐름으로 로직이 구성되는지, 내가 작업한 내용들은 어떤것들인지 하루종일 정리를 했다.(정리가 제일 어렵다..) 분명 분석과 설계를 하고 개발을 했음에도, 내가 작업한 내용을 정리하는 것이 어려운 것 같다. 그래도 어렵지만 재밌다. 내가 한 것들을 정리하면서, 생각도 정리되고, 앞으로 개발할 도메인들에 대해서도 가이드가 되는 듯하다.
Member 도메인이면서 프로젝트의 스켈레톤(템플릿) 정리
다른 사람들에게 프로젝트를 소개 및 리뷰를 해야하는 만큼, 첫 도메인 작업 내용을 작성할 때, 불필요한 질문을 줄이기 위해 Member 도메인에 대한 내용 외에도 프로젝트에 대한 구조 및 구성에 대한 설명을 해야한다.(라고 생각한다.) 그래서 기본적인 로직의 흐름, 디렉토리 패키지 구조 및 각 패키지의 역할에 대한 설명을 정리한다.
Request 가 들어오면, Controller 에서 해당 요청을 처리하기 위해 input port 인 Domain-ApplicationService 의 ApplicationService 가 호출된다. 그리고 ApplicationService 에서는 Domain-Core의 DomainService 를 호출한다. 모든 의존성은 도메인을 향하는 구조이다. 이를 보고 의존성이 도메인으로 향하는 것을 보고, 도메인주도개발(DDD) 혹은 클린아키텍처(Ports And Adapters)를 생각했다면천재다.(같이 대화를 나눠보고싶다!!) 그런데 여기서Domain을 왠 Application 과 Core 로 나뉘는걸까? 생각이 들 수 있다.(나느 처음 이에 대한 공부를 할 때 그랬다.. 아님말고..)
왜 Domain 패키지를 Core 와 Application 으로 나누었을까?
Domain-Core 에서는 비즈니스로직을 담당하고, Domain-Application 은 Domain-Core 를 활용한 요리(?)를 담당하고자 했다.
과거 나는 Service 혹은 Helper 에서 비즈니스 로직을 처리를 해왔다. 하지만 이는 불편했다. 점점 비즈니스 로직이 복잡해지고, 요구사항이 늘어남에따라 기존의 비즈니스 로직에 영향을 주고, 응용이 아닌 남용이 되기도 했다.
그리고 나는 이번 프로젝트에서는 해당 문제를 겪고 싶지 않았다. 그런데 마침 클린아키텍처와 DDD를 공부하면서 이 문제를 해결할 수 있는 방법을 찾았고, 그 해결책은 Domain을 식별하고 다른 계층과 분리하며, 분리한 Domain 에서도 상위와 하위 계층으로 나누는 것이다.
Domain-Core 에서는 Domain 및 Entity, Value Object 에 대한 비즈니스 로직을 모델링하고, Domain-Application 에서는 해당 Domain-Core 에 구현된 비즈니스로직을 가진 Domain, Entity, Value Object 를 다양하게 활용하는 것이다. 현재 Member 를 개발하면서 다른 도메인(Product, Order)에 대한 개발이 진행되지 않아 Repository 가 MemberRepository만 사용되었지만, 다른 도메인이 개발된 후, 다른 도메인의 데이터가 필요할경우, Domain-Application 에서 다른 도메인의 Repository를 사용하여 Member 에서 원하는 데이터를 조합할 수도 있을 것이다.
그래서 내 프로젝트 패키지 구조는 다음과 같다.
domain 디렉토리에 앞으로 개발할 도메인들이 추가될 것이다.(현재 member 가 추가되었다.) 그리고 각 도메인 패키지는 4개의 하위 패키지를 갖게된다.
Controller, Data Access, domain, messaging
Controller
MVC 패턴에서 Presentation 계층으로도 불리는 Controller 는 외부 요청을 받아들이며, input port 로 내부 도메인(Domain-Application)을 호출한다. 기본적으로 REST API로 API를 개발을 목표로한다.
Data Access
영속성 을 담당하는 패키지로 DB와 관련된 JPA Repository 가 존재한다. 이 패키지는 일반적인 계층형 아키텍처(MVC) 와 차별화 되는 부분이다. 기존의 계층형 구조라면 Model 패키지로 관리가 될 것이다.(그리고 종속성의 종착지겠지..) 하지만 클린아키텍처에서는 영속성 부분은 output port 로써 관리한다. 따라서 DataAccess 의 이름과 이를 관리하기 위한 entity, adapter, mapper, repository 가 존재한다.
entity, adapter, mapper, repository 각각의 패키지의 역할에 대하 이야기를 해본다면, 이 패키지 구조는 클린아키텍처를 사용하는 대가라고 말할 수 있다. 도메인 계층이 영속성계층과 같은 외부 계층과 철저히 분리되어야 하는 클린아키텍처에서는 애플리케이션의 엔터티에 대한 모델을 각 계층에서 관리해야하기 때문이다.
즉, 도메인 계층에서 사용한 엔터티 클래스를 영속성 계층에서 함께 사용할 수 없으며, 두 계층에서 각각 엔터티 클래스를 만들어야 한다.
그리고 이는 도메인 계층과 영속성 계층이 데이터를 주고 받을 때, 두 엔터티를 서로 변환해야한다 는 것을 의미한다. 따라서 mapper 가 필요하다. 그럼 이제 이런생각이 들 것이다. ?? adapter 는 뭐지?(안들었음 말고...)
adapter 는 의존성 역전을 위한, repository 구현 클래스이다. 이 adapter 가 없었다면 기존의 MVC 패턴처럼 의존성의 최종 종착지는 영속성 계층이 되었을 것이다.
그런데 왜 패키지 이름이 Adapter 라고 의문이 들 수 있다. 이유는 단순하다. port and adapter 패턴에서 output port의 adapter 역할을 담당하는것이라고 생각해서 adapter 라고 하였다.
Domain
도메인계층은 핵심으로써, 모든 의존성의 종착지이다. 도메인은 왕이다. 비즈니스 관점에서 바라보면 그렇다. DDD을 공부해보면(물론 나는 가벼운 책으로 입문해서 자세하고 싶게는 알지못한다..)
도메인로직이 다른 관심사와 섞여 있다면 그와 같은 대응을 달성하기가 수월하지 않다. 따라서 도메인 주도 설계의 전제조건은 도메인 구현을 격리하는 것이다.
도메인 주도 설계의 핵심은 도메인 구현을 격리하는 것이다. 왜? 도메인은 왕이니깐! 도메인이 곧 비즈니스 이다!!(라고 생각한다..) 그리하여 Domain 계층에서는 핵심부분 Core 와 도메인 계층에 들어올 수 있는 Application 으로 나누어 개발한다.
Core 와 Apllication 에 대한 설명은 앞서 이야기 했으니, 생략하겠다.
Messaging
메시징 계층은 프로젝트 아키텍처 중 하나인 이벤트 기반 아키턱처를 위한 패키지이다. 이번 프로젝트의 목표는 EDA 기반의 모놀리식 아키텍처 -> EDA 기반의 마이크로서비스 아키텍처로 고도화 하는 것이다. 그래서 나는 Messaging 패키지를 생성했다.
나는 이벤트 버스로 Kafka를 사용하고, 직렬화 도구로 Avro 를 선택했다. Avro 클래스의 경우, 플러그인을 통해 빌드 시 .avsc 파일들을 통해 자동 생성한다.
주제 밖의 말이지만, 개발을 하면서 가장 많은 시간을 소요했고, 가장 어렵게 느껴지는 부분이다. 카프카 자체는 어렵다는 생각이 들지 않는데(왜일까?) 카프카와 프로젝트를 연결하기 위한 과정이 너무 어렵다. 사용한 경험이 있는 플러그인을 사용하고자 하는데 과거 내가 사용해본 것은 maven 기반의 플러그인이라그런지, 해당 플러그인과 동일한 플러그인을 찾고, 원하는 대로 커스텀하여 사용하는것이 어려운 것 같다.. 그래도 재밌다. 그리고 이를 통해 외부 라이브러리 및 플러그인을 좀 더 잘 사용할 수 있을 것 같다는 생각이 든다.
그래서 프로젝트의 기본 스켈레톤(템플릿)은 Controller, dataaccess, domain, messaging 으로 구성될 것이다. 그리고 패키지는 이에 맞게 구현될 것이다.(너무 재밌겠다!!! )
이번 Member 를 개발하면서 정말 많은 경험을 한 것 같다. 무엇보다 공부한 내용을 직접 응용해서 해보는 것이 힘들었지만 너무 재밌었다. 공부했던 내용을 이전보다 깊이있게 공부한 것같아 기분이 좋다.(사실 내가 모르고있던 부분을 많이 알게된 것이 많다.) 하지만 실무에서는 이러한 내용을 적용하기가 어려울 것이라는 것을 안다. 그래서 누군가는 이런건 이상이고, 현실에서는 할 수 없는 일이라고 한다.(이렇게 귀에 딱지가 생기도록 들었다..전 사ㅅ 한테서..) 하지만 나는 이런 내용을 고민하면서, 코드를 짜며 클래스간의 의존관계는 어떻게 설계해야하고, 패키지 는 어떻게 구성해야하며, 기능 수정 및 추가 시에는 어느 레벨에서 다뤄야하는지에 대한 고민을 하는 것이 결코 나쁜 것이 아니라고 생각한다. 비록 지금은 혼자 공부하면서 해보는 간단한 프로젝트이지만, 가까운 미래에는 이를 다른 사람들과 함께 비즈니스로 해보고싶다.
어서 빨리 다음 도메인 설계를 시작해야겠다.
'회고 > TIL' 카테고리의 다른 글
6월 마지막 주 주말, 클린아키텍처 공부 (0) | 2023.06.25 |
---|---|
PR 작성, 피드백, 개선 (0) | 2023.06.22 |
Member 도메인 완료, 느낀점 (0) | 2023.06.20 |
해결되지 않는 에러.. 원인이 무엇일까? (0) | 2023.06.16 |
오늘도 여전한 에러 해결을 위한 노력과 무시하고 개발하는 나, 이벤트기반 마이크로서비스 구축 (0) | 2023.06.15 |