🎯 0. 들어가기 전
MVC 패턴 & 자바 기반의 콘솔 애플리케이션에서는
관성적으로 model(domain) & controller & view 패키지를 만들고 시작하는 경우가 대부분이었다.
웹 애플리케이션을 구현하면서, 설계 단계에서 관성을 버리고 패키지 구조에 대해서 고민하기로 했다.
그리고 설계하면서 설계 단계에서 패키지 구조에 대한 고민을 겪었다.
늘 하던 것처럼 '계층형'으로 패키지 구조를 만드는 것이 좋을까?
'도메인형' 구조가 있다는데 이 구조를 적용해볼까?
계층형과 도메인형 둘 중 하나를 선택하기 위해, 두 구조의 장단점을 비교해보자.
장바구니 애플리케이션이라고 가정하고, 도메인이 'Member', 'Product', 'Cart'가 있다고 하고 비교해보자.
🎯 1. 계층형 구조
controller
⎿ ProductController
⎿ MemberController
⎿ CartController
service
⎿ ProductService
⎿ MemberService
⎿ CartService
dao
⎿ ProductDao
⎿ MemberDao
⎿ CartDao
domain
⎿ Product
⎿ Member
⎿ Cart
계층형 구조는 애플리케이션에서 사용하는 계층별로 패키지를 구성하는 방식이다.
대부분이 Layered Architecture를 사용하기 때문에
Layered Architecture의 컴포넌트들 및 관련 요소들이 패키지가 되는 경우가 많다.
이와 같은 계층형 패키지 구조를 공부해보고 생각해보면서 느낀 장단점은 다음과 같다.
1-1. 계층형 구조 장단점
- 장점
- 1. 프로젝트 전반적인 이해도가 낮아도, 패키지 구조만 보고 전체적인 구조를 파악할 수 있다.
- 애플리케이션의 API를 보고 흐름을 파악하고 싶다면, Controller 패키지 하나만 보고 파악할 수 있다.
- 애플리케이션의 비즈니스 로직을 보고 싶다면, Service 패키지 하나만 보고 파악할 수 있다.
- 2. 계층별 응집도가 높아진다.
- 계층별 수정이 일어날 때, 하나의 패키지만 보면 된다.
- 1. 프로젝트 전반적인 이해도가 낮아도, 패키지 구조만 보고 전체적인 구조를 파악할 수 있다.
- 단점
- 1. 도메인별 응집도가 낮다. (패키지로 애플리케이션의 기능을 구분짓지 못한다)
- 1-1. 도메인의 흐름을 파악하기 힘들다.
- Product 도메인의 흐름을 보고 싶을 때, 모든 계층 패키지를 봐야한다.
- 하나의 패키지안에 여러 도메인(상품, 장바구니, 사용자)들이 섞여 있다.
- 1-2. 도메인과 관련된 스펙 & 기능이 변경되었을 때, 변경 범위가 크다.
- Product에 대한 변경점이 있을 때, 여러 패키지에서 변경이 일어난다.
- 1-1. 도메인의 흐름을 파악하기 힘들다.
- 2. 유스케이스(사용자의 행위) 표현이 어렵다.
- 규모가 커지면, 유스케이스별로 클래스를 분리할 때가 있다.
- ex : 상품 등록 유스 케이스 -> RegisterProductService
- 하지만, 계층형에서는 계층으로 패키지가 묶이기 때문에 위와 같이 네이밍해서 분리하기 어렵다.
- 3. 규모가 커지면 하나의 패키지 안에 여러 클래스들이 모여서 구분이 어려워진다.
- 1. 도메인별 응집도가 낮다. (패키지로 애플리케이션의 기능을 구분짓지 못한다)
🎯 2. 도메인형 구조
product
⎿ controller
⎿ service
⎿ dao
⎿ dto
member
⎿ controller
⎿ service
⎿ dao
⎿ dto
cart
⎿ controller
⎿ service
⎿ dao
⎿ dto
도메인형 구조는 도메인을 기준으로 패키지를 나눈 구조이다.
이와 같은 도메인형 패키지 구조를 공부해보고 생각해보면서 느낀 장단점은 다음과 같다.
2-1. 도메인형 구조 장단점
- 장점
- 1. 도메인별 응집도가 높아진다.
- 1-1. 도메인의 흐름을 파악하기 쉽다.
- Product 도메인의 흐름을 보고 싶을 때, Product 패키지 하나만 보면 된다.
- 1-2. 도메인과 관련된 스펙 & 기능이 변경되었을 때, 변경 범위가 적다.
- Product에 대한 변경점이 있을 때, Product 패키지만 변경이 일어난다.
- 1-1. 도메인의 흐름을 파악하기 쉽다.
- 2. 유스케이스별로 세분화해서 표현이 가능하다.
- ex : 상품 등록 유스 케이스 -> RegisterProductService
- ex : 상품 검색 유스 케이스 -> SearchProductService
- 도메인별로 패키지가 나뉘기 때문에 product 패키지에서 위와 같은 네이밍으로 분리할 수 있다.
- 1. 도메인별 응집도가 높아진다.
- 단점
- 애플리케이션의 전반적인 흐름을 한눈에 파악하기가 어렵다.
- 흐름을 파악하기 위해 여러 패키지를 왔다갔다 해야할 가능성이 높다.
- 개발자의 관점에 따라 어느 패키지에 둘지 애매한 클래스들이 존재한다.
- Welcome 페이지를 맵핑하는 컨트롤러일 때, 어느 도메인 패키지에 위치할지 개발자에 따라 다를 수 있다.
- 자신이 예상하는 패키지와 다를 때, 해당 클래스를 찾기가 어렵다.
- 애플리케이션의 전반적인 흐름을 한눈에 파악하기가 어렵다.
🎯 3. 결론 - 계층형 VS 도메인형 어느 구조를 선택할까?
위에서 계층형과 도메인형 패키지 구조와 장단점을 살펴봤다.
그렇다면, 어떤 패키지 구조를 선택해야할까?
장단점을 비교해보면서 '무조건적으로 좋은 것, 정답은 없다'라고 느꼈다!
프로젝트 및 애플리케이션 규모 및 상황에 따라 장단점을 비교해서 선택하는 것이 좋을 것 같다고 생각했다.
그렇다면, 어떤 기준으로 선택을 할까?
일단 프로젝트 경험이 많이 없는 지금 내가 정한 기준은 다음과 같다.
(아직 프로젝트 경험이 많이 없어서 추후에 경험해보면서 기준이 바뀔 수도 있을 것 같다!)
* 계층형 구조 선택
- 규모가 작고, 도메인이 적은 경우
- 계층형 패키지 안에 클래스들이 구분이 안될만큼 많아질 경우가 적다.
- 애플리케이션 흐름 및 가독성이 도메인형보다 좋다.
- 유스케이스별로 클래스를 분리하는 경우가 적다.
- 도메인의 변경이 일어나도, 규모가 작고 도메인이 적은만큼 변경 범위가 그렇게 크지 않을 것이다.
* 도메인형 구조 선택
- 규모가 크고, 도메인이 많은 경우
- 규모가 크고 도메인이 많은 만큼 도메인의 응집도가 높은 것이 중요할 것이다.
- 규모가 큰 만큼 유스케이스별로 클래스를 분리하는 경우가 있을 수 있다.
계층형, 도메인형 패키지 구조의 예시에서 사용한 애플리케이션에서는
위의 기준에 따라 '계층형' 구조를 선택했다.
더 자세한 이유로는 '도메인형' 구조가 가진 단점이 너무 크게 느껴졌다.
'도메인형'으로 설계했을 때 가독성이 '계층형' 구조에 비해 너무 안 좋았고,
어느 패키지에 들어가야할지 모르는 클래스가 있었어서 '계층형' 구조를 선택하게 되었다.
이처럼, 기준을 정하고 trade-off를 적당히 파악하면서
매번 애플리케이션 설계 시마다 적절한 패키지 구조를 정하는 것이 좋다고 느끼게 되었다!
Reference
https://ahnheejong.name/articles/package-structure-with-the-principal-of-locality-in-mind/
https://cheese10yun.github.io/spring-guide-directory/
https://jaime-note.tistory.com/411
'아키텍쳐' 카테고리의 다른 글
[MSA] 개인 프로젝트 Monolithic to MSA 전환기 - (2) 멀티 모듈 구성하기 (1) | 2024.02.02 |
---|---|
[MSA] 개인 프로젝트 Monolithic to MSA 전환기 - (1) MSA란? (0) | 2024.02.01 |
Controller와 Service 레이어 간 요청 & 응답 Dto 사용에 관하여 (2) | 2023.06.19 |
[아키텍쳐] Service, Repository가 왜 필요할까? (0) | 2023.04.24 |
[아키텍쳐] Layered Architecture란? (feat. 자동차 경주 미션 예시) (7) | 2023.04.21 |