레이어드 아키텍처(Layered Architecture)는 소프트웨어 애플리케이션을 여러 계층(layer)으로 분리하여 각 계층이 명확한 책임을 가지도록 설계하는 방식으로, 이를 통해 코드의 모듈화와 유지보수성을 높일 수 있으며 각 계층 간의 의존성을 줄여 변화에 유연하게 대응할 수 있다.
├── controller // Presentation Layer
│ ├── UserController.java
│ └── OrderController.java
│
├── service // Business Layer
│ ├── UserService.java
│ └── OrderService.java
│
├── repository // Persistence Layer
│ ├── UserRepository.java
│ ├── OrderRepository.java
│ ├── UserRepositoryCustom.java
│ └── UserRepositoryImpl.java
│
├── entity // Domain Layer
│ ├── User.java
│ ├── Order.java
│ ├── Address.java
│ ├── UserRole.java
│ └── OrderStatus.java
│
├── dto // Data Transfer Objects
│ ├── UserDTO.java
│ ├── OrderDTO.java
│ └── AddressDTO.java
│
├── exception // Exception Handling
│ ├── CustomException.java
│ └── GlobalExceptionHandler.java
│
└── config // Configuration Classes
├── WebConfig.java
└── DatabaseConfig.java
내가 기존에 Layered Architecture라고 생각하며 만들었던 패키지 구조 예시이다.
각 Layer별로 구분되어있는 그저 무난한 구조이다.
여기에 피드백을 받았던 내용들을 추가해 수정해본다면
├── controller // Presentation Layer
│ ├── UserController.java
│ └── OrderController.java
│
├── application // Business Layer
│ ├── UserService.java
│ ├── OrderService.java
│ └── dto // Data Transfer Objects
│ ├── UserDTO.java
│ ├── OrderDTO.java
│ └── AddressDTO.java
│
├── repository // Persistence Layer
│ ├── UserRepository.java
│ ├── OrderRepository.java
│ ├── UserRepositoryCustom.java
│ └── UserRepositoryImpl.java
│
├── domain // Domain Layer
│ ├── User.java
│ ├── Order.java
│ ├── Address.java
│ └── enum
│ ├── UserRole.java
│ └── OrderStatus.java
│
├── exception // Exception Handling
│ ├── CustomException.java
│ └── GlobalExceptionHandler.java
│
└── config // Configuration Classes
├── WebConfig.java
└── DatabaseConfig.java
이런 식으로 조금 더 세부적으로 구분할 곳은 구분하고, 관련된 코드는 한 패키지에 모아 찾기 쉽고, 관리가 용이하도록 한다.
Infrastructure
애플리케이션 설계에서 infrastructure는 보통 데이터베이스, 파일 시스템, 네트워크 등과 같은 외부 시스템과의 상호작용을 담당하는 계층을 말한다.
이 계층은 DIP 관점에서 저수준 모듈에 해당하기 때문에 DIP 원칙에 따라, 고수준 모듈(비즈니스 로직)이 저수준 모듈에 직접 의존하지 않도록 설계해야 한다.