[Clean Architecture] 빠져 있는 장
카테고리: Clean Architecture
이번 장에서는 클린 아키텍처는 잠시 한쪽으로 제쳐놓고, 설계나 코드 조직화와 관련된 몇 가지 접근법을 알아봅니다.
(온라인 서점을 구축하고 있으며, 고객이 주문 상태를 조회할 수 있어야 한다는 유스케이스를 구현해야 한다고 해봅니다.)
계층 기반 패키지
Spring Boot로 프로젝트를 해봤다면, 자주 접하게 되는 계층 기반 패키지 입니다.
계층형 아키텍처는 구조가 단순하여 처음 시작하기에 적합합니다. 하지만 소프트웨어가 커지고 복잡해지면 큰 그릇 세개만으로 다 담기에는 부족하다는 것을 깨닫고 더 잘게 모듈화 해야할지 고민할 것입니다. (패키지 안에 Order, User 등등 많은 도메인 관련 클래스들이 생김)
또한, 해당 아키텍처는 업무 도메인에 대해 아무것도 말해주지 않는다는 문제도 있습니다.
기능 기반 패키지
계층 기반 패키지를 간단히 리팩터링한 형태로 서로 연관된 기능, 도메인 개념 또는 Aggregate Root에 기반하여 수직의 얇은 조각으로 코드를 나누는 방식입니다.
여기서 Aggregate Root란, 하나 이상의 객체로 구성된 집합의 진입점을 말합니다. 예를들어서 주문
을 한다고 하면 주문
이라는 Aggregate Root가 생성되고 그 안에는 OrderController - OrderService - OrderRepository 등등으로 구성되어 있을것입니다.
이렇게 나누게 되면, 주문에 관련된 수정사항이 생기면, Order 패키지만 수정하면 된다는 장점이 있습니다.
포트와 어댑터
포트와 어댑터는 내부(도메인)
와 외부(인프라)
로 구성되어있는 구조입니다. 엉클 밥에 따르면, 포트와 어뎁터
, 육각형 아키텍처
, 경계
등의 방식으로 접근하는 이유는 업무/도메인에 초점을 둔 코드가 프레임워크나 데이터베이스 같은 기술적이 세부 구현과 독립적이며 분리된 아키텍처를 만들기 위해서 입니다. 그림으로 표현하면 다음과 같습니다.
내부
영역은 도메인 개념을 모두 포함하는 반면, 외부
영역은 외부 세계 (UI, DB, 서드파티 라이브러리)와의 상호작용을 포함합니다. 이를 패키지 형태로 나타내면 다음과 같습니다.
여기서 내부 패키지는 com.mycompany.myapp.domain
이며, 외부 패키지는 com.mycompany.myapp.data
입니다. 이렇게 나누면, 도메인은 외부에 의존하지 않게 됩니다.
(domain에 OrderRepository가 아닌 Orders로 이름지은 것은 DDD에서 내부에 존재하는 모든 것의 이름은 반드시 유비쿼터스 도메인 언어 관점에서 기술하라고 조언하기 때문입니다.)
컴포넌트 기반 패키지
MVC 패턴을 적용할 때, 보통 Controller 는 Serivce에 의존하고, Service는 Repository에 의존하도록 설정합니다. Controller에서 Repository를 직접 의존하지는 않습니다. 개념적으로는 이렇지만, 이것을 강제로 막을 방법은 없습니다. 컴포넌트 기반 패키지에서는 이런 의존성을 강제하도록 설정할 수 있습니다. 바로 컴파일타임의 접근 제한자
를 통해 가능합니다.
위 처럼 분리하고, OrderComponent만 public 으로 열어주고 나머지는 default로 접근제한자를 걸면, Controller 에서는 OrderComponent에만 접근가능합니다. 이렇게 접근 제한자를 통해 강제성을 제어할 수 있습니다. 또한, 추후 MSA 같은 아키텍처로 변환할 때도 더욱 쉽게 조립하여 구축해 나갈 수 있다는 장점도 있습니다.
결론
이러한 계층구조는 이상에 가깝습니다. 실제로 프로젝트를 하다보면 100% 다 지킬 수 있지는 않습니다. 그렇기에 가능하다면 선택사항을 열어두되, 실용주의적으로 선택하고 행해야 합니다. 그리고 팀의 규묘, 기술 수준, 해결책의 복잡성을 일정과 예산이라는 제약과 동시에 고려해야 합니다. 또한 선택된 아키텍처 스타일을 강제하는데에는 업무 규칙등과 같은 강제성이 없는 방법이 아닌, 컴파일러의 도움을 받아 강제성을 가질 수 있도록 해야 합니다.
댓글 남기기