패키지 구조에 대한 고민
프로젝트를 시작할 때마다 습관처럼 controller, service, repository 폴더를 만들었다.
처음 배울때 계층 기반 패키지 구조로 배웠고, 딱히 의심 없이 써왔다.
“이 구조가 나한테 맞는 건가? 더 나은 방식이 있지 않을까?”
그래서 계층 기반 구조를 다시 들여다보고, 도메인 기반 구조와 비교해봤다.
어떤 상황에서 어떤 구조를 선택해야 하는지 고민한 기록을 남긴다.
계층 기반 패키지 구조 (Layer-based)
기술적인 역할, 즉 계층(Layer) 을 기준으로 패키지를 나누는 방식이다.
com.example.project
├── controller
│ ├── UserController.java
│ └── OrderController.java
├── service
│ ├── UserService.java
│ └── OrderService.java
└── repository
├── UserRepository.java
└── OrderRepository.java장점
- 구조가 단순하고 직관적이다.
- 어느 계층에 파일이 있는지 예측하기 쉽다.
- 소규모 프로젝트에서는 오히려 이 구조가 더 깔끔하게 느껴진다.
단점
- 프로젝트가 커질수록 한 폴더 안에 파일이 수십 개 쌓인다.
User관련 코드가controller,service,repository에 뿔뿔이 흩어진다.User기능을 파악하려면 4개 폴더를 모두 열어야 한다.- 기능 단위로 묶여 있지 않아서 특정 기능을 통째로 삭제하거나 분리하기 어렵다.
도메인 기반 패키지 구조 (Domain-based)
비즈니스 기능(도메인) 을 기준으로 패키지를 나누는 방식이다.
com.example.project
├── user
│ ├── UserController.java
│ ├── UserService.java
│ ├── UserRepository.java
│ └── User.java
├── order
│ ├── OrderController.java
│ ├── OrderService.java
│ ├── OrderRepository.java
│ └── Order.java
└── common
├── exception
│ └── GlobalExceptionHandler.java
└── config
└── SecurityConfig.java장점
user폴더 하나만 열면 유저 관련 코드가 모두 모여 있다.- 기능 추가, 수정, 삭제 시 해당 도메인 패키지만 건드리면 된다.
단점
- 처음 구조를 잡을 때 도메인 경계를 잘못 나누면 나중에 더 복잡해진다.
- 경계가 불분명한 경우, 어디에 둬야 할지 고민이 생긴다.
그래서 내가 선택한 구조는?
요즘 도메인 기반 구조가 대세라고 한다.
그럼에도 불구하고, 나는 계층 기반 구조를 선택하기로 했다. 이유는 두 가지다.
첫 번째는 내가 진행하는 웹 개발 프로젝트의 특성상 구조 자체가 복잡하지 않다는 점이다. 도메인이 명확하게 분리될 만큼 규모가 크지 않은 상황에서 굳이 도메인 기반 구조를 도입하는 건 오히려 과한 설계라는 생각이 들었다.
첫 번째는 웹 개발의 특성상 이미 계층 기반으로도 도메인이 충분히 구분된다는 점이다. 웹 애플리케이션은 메뉴(기능) 단위로 설계되고, UserController, OrderController 처럼 네이밍 자체가 자연스럽게 도메인을 구분해준다. 패키지 구조까지 도메인 기반으로 가져가는 건 이미 나뉘어진 것을 한 번 더 나누는 느낌이었다. 굳이 도메인으로 나누지 않아도 충분히 깔끔하다고 판단했다.
두 번째는 도메인 기반 구조는 도메인 경계가 불분명한 기능이 생겼을 때 고민이 깊어진다.
마지막 수정