src
└── main
└── java
└── com
└── example
├── adapter
│ ├── in
│ │ ├── web
│ │ │ ├── controller
│ │ │ │ ├── OrderController.java
│ │ │ │ └── CustomerController.java
│ │ │ └── dto
│ │ │ ├── OrderRequest.java
│ │ │ ├── OrderResponse.java
│ │ │ ├── CustomerRequest.java
│ │ │ └── CustomerResponse.java
│ │ ├── grpc
│ │ │ └── GrpcServerImpl.java
│ │ ├── kafka
│ │ │ └── KafkaListener.java
│ │ └── event
│ │ └── EventListener.java
│ ├── out
│ │ ├── persistence
│ │ │ ├── entity
│ │ │ │ ├── OrderEntity.java
│ │ │ │ └── CustomerEntity.java
│ │ │ ├── repository
│ │ │ │ ├── OrderRepository.java
│ │ │ │ └── CustomerRepository.java
│ │ ├── OrderRepositoryAdapter.java
│ │ ├── CustomerRepositoryAdapter.java
│ │ ├── grpc
│ │ │ └── GrpcClient.java
│ │ ├── kafka
│ │ │ └── KafkaProducer.java
│ │ └── event
│ │ ├── EventPublisher.java
│ │ └── DomainEvent.java
├── application
│ ├── port
│ │ ├── in
│ │ │ ├── OrderUseCase.java
│ │ │ └── CustomerUseCase.java
│ │ └── out
│ │ ├── OrderRepositoryPort.java
│ │ └── CustomerRepositoryPort.java
│ ├── service
│ │ ├── OrderService.java
│ │ └── CustomerService.java
│ └── command
│ ├── CreateOrderCommand.java
│ ├── UpdateOrderCommand.java
│ ├── CreateCustomerCommand.java
│ └── UpdateCustomerCommand.java
├── domain
│ ├── model
│ │ ├── Order.java
│ │ └── Customer.java
├── config
│ ├── AppConfig.java
│ └── SecurityConfig.java
├── util
│ └── DateUtils.java
├── exception
│ ├── OrderNotFoundException.java
│ └── CustomerNotFoundException.java
└── mapper
├── OrderMapper.java
└── CustomerMapper.java
adapter
패키지:
in
: 애플리케이션으로 들어오는 요청을 처리하는 어댑터.
web
:
controller
: HTTP 요청을 처리하는 REST 컨트롤러.dto
: 요청(Request) 및 응답(Response) DTO 클래스.grpc
: 외부에서 들어오는 gRPC 요청을 처리하는 서버 구현.kafka
: 메시지 큐에서 들어오는 Kafka 메시지를 처리하는 리스너.event
: 애플리케이션 내 이벤트를 처리하는 리스너.out
: 외부 시스템과 상호작용을 처리하는 어댑터.
persistence
:
entity
: 데이터베이스와 상호작용할 엔티티 클래스.repository
: JPA 리포지토리를 정의하여 데이터베이스 작업을 수행.grpc
: 외부 gRPC 서비스와의 통신을 처리하는 클라이언트.kafka
: 외부 시스템으로 메시지를 발행하는 Kafka 프로듀서.event
: 이벤트 발행 로직 및 도메인 이벤트 정의.application
패키지:
port
: 애플리케이션 계층의 입력 및 출력 포트를 정의.
in
: 유즈케이스 인터페이스를 정의하여 비즈니스 로직의 진입점을 제공합니다.out
: 외부 시스템과의 상호작용을 위한 인터페이스를 정의.service
: 비즈니스 로직을 구현하는 서비스 클래스가 포함되어 있습니다. 이 클래스는 도메인 객체를 사용하여 비즈니스 규칙을 수행합니다.command
: useCase에 보낼 데이터를 포함하는 command 클래스들을 정의한다. 컨트롤러에서 useCase를 호출할때 command객체를 보낸다. 서비스에서는 이 command객체의 값을 꺼내서 도메인을 생성해서 도메인으로 비즈니스 로직 처리를 한다. (참고로 port로는 작업완료한 domain 객체를 보낸다. command는 단순히 데이터를 useCase로 전달하는 객체일 뿐이다. 그게 모든 역할이다.)
application
레이어 내의 command
패키지에 위치합니다. 이는 유스케이스와 함께 사용되는 데이터 구조로, 애플리케이션 로직의 일부로 볼 수 있습니다.domain
패키지:
model
: 비즈니스 로직의 핵심을 이루는 도메인 객체(엔티티와 값 객체)를 포함.application
계층에서 비즈니스 로직을 처리합니다. 도메인 서비스는 주로 도메인 모델 내에서 직접 처리할 수 없는 복잡한 비즈니스 규칙이 있을 때 사용될 수 있습니다【83†source】【84†source】.config
: 애플리케이션 설정 관련 클래스를 포함.util
: 재사용 가능한 유틸리티 클래스를 포함.exception
: 커스텀 예외 클래스를 포함하여 애플리케이션 전반에서 사용할 수 있는 예외를 정의.mapper
: DTO와 도메인 객체 간의 변환을 담당하는 클래스.이러한 구조는 헥사고날 아키텍처의 원칙에 따라 명확한 책임을 가지며, 시스템의 유연성과 유지보수성을 높이는 데 기여합니다. 각 계층은 독립적으로 발전할 수 있도록 설계되었습니다.
헥사고날 아키텍처에서 제시한 패키지 구조는 일반적으로 명확한 책임 분리를 통해 애플리케이션의 유지보수성과 확장성을 높이는 데 중점을 둡니다. 제시하신 트리 구조는 헥사고날 아키텍처의 모범 사례와 잘 맞아떨어집니다. 아래는 헥사고날 아키텍처의 기본 원칙과 제시한 구조에 대한 검토입니다.
adapter > in
에 잘 반영되어 있습니다.adapter > out
에 이 개념이 잘 반영되어 있습니다【110†source】【112†source】.domain
패키지 내에서 비즈니스 객체를 정의하여 이 원칙을 따르고 있습니다【111†source】【112†source】.application
패키지가 이 역할을 수행합니다.OrderRepositoryAdapter
와 같은 클래스가 이 역할을 수행합니다【109†source】【112†source】.