헥사고날 아키텍처 – application 다른 폴더

port service는 헥사고날 아키텍처에서 application 계층의 가장 핵심적이고 필수적인 구성 요소이지만, 애플리케이션의 복잡성과 설계 결정에 따라 다른 폴더를 추가하여 구조를 더 명확하게 만들 수 있습니다.

application 패키지 내에 추가될 수 있는 다른 폴더들

1. dto 또는 command / query

애플리케이션 계층에서 사용되는 데이터 전송 객체를 별도로 관리하기 위한 폴더입니다. 이는 어댑터 계층의 DTO와는 역할이 다릅니다.

  • command: CUD(Create, Update, Delete) 유스케이스에 대한 입력 데이터를 캡슐화하는 객체입니다. “무엇을 하라”는 명령의 내용을 담습니다.
    • 예시: PlaceOrderCommand.java, UpdateUserAddressCommand.java
  • query: R(Read) 유스케이스에 대한 입력 데이터를 캡슐화하는 객체입니다. “무엇을 조회해달라”는 요청의 내용을 담습니다.
    • 예시: GetOrderQuery.java, SearchUsersQuery.java

폴더 구조 예시:

왜 이 폴더를 사용할까?

  • 의도의 명확화: PlaceOrderUseCase.placeOrder(PlaceOrderCommand command) 처럼 메서드 시그니처만 봐도 “이 유스케이스는 ‘주문하기’ 명령을 처리하는구나”라는 의도가 명확해집니다.
  • 입력 데이터 유효성 검사: Command/Query 객체 내에서 생성자를 통해 입력값에 대한 기본적인 유효성 검사를 수행할 수 있습니다.
  • 서비스 메서드 시그니처 단순화: 여러 개의 파라미터를 하나의 객체로 묶어 전달하므로, 메서드 시그니처가 깔끔해집니다.

참고: 일부 설계에서는 이 Command/Query 객체들을 port/in 패키지 내에 두기도 합니다. 인바운드 포트와 관련된 데이터 구조로 보기 때문입니다. 어느 쪽이든 팀의 컨벤션에 따라 일관성 있게 정하면 됩니다.

2. exception

애플리케이션의 비즈니스 로직과 관련된 **커스텀 예외(Custom Exception)**를 정의하는 폴더입니다.

  • 예시: OrderNotFoundException.java, ProductStockNotEnoughException.java

폴더 구조 예시:

왜 이 폴더를 사용할까?

  • 명시적인 예외 처리: try-catch 블록에서 catch (OrderNotFoundException e) 와 같이 특정 비즈니스 예외 상황을 명시적으로 처리할 수 있게 해줍니다.
  • 오류 상황 전달: 컨트롤러(어댑터)에서 이 커스텀 예외를 잡아 사용자에게 더 친절한 오류 메시지(예: “주문 정보를 찾을 수 없습니다.”)와 적절한 HTTP 상태 코드(예: 404 Not Found)를 반환하는 데 사용됩니다.

3. common 또는 util

애플리케이션 계층 내에서 공통적으로 사용되지만, 특정 도메인에 속하지 않는 유틸리티성 클래스나 인터페이스를 모아두는 폴더입니다.

  • 예시: PagingUtil.java (페이징 처리 관련 헬퍼), EventPublisher.java (도메인 이벤트를 발행하는 인터페이스)

폴더 구조 예시:

왜 이 폴더를 사용할까?

  • 여러 서비스에서 중복해서 사용되는 로직을 분리하여 재사용성을 높입니다.
  • port service에 두기 애매한 성격의 파일들을 체계적으로 관리할 수 있습니다.

종합적인 application 폴더 구조 예시

위의 요소들을 모두 포함한 종합적인 application 패키지 구조는 다음과 같을 수 있습니다.

결론

port service application 계층의 필수 골격인 것은 맞습니다.

하지만 애플리케이션이 복잡해짐에 따라 command/query, exception, common 과 같은 추가적인 폴더를 구성하여 관심사를 더 세분화하고 코드의 의도를 명확하게 만들 수 있습니다.

이러한 구조는 정답이 있는 것이 아니라, 프로젝트의 규모와 팀의 합의에 따라 유연하게 결정됩니다. 중요한 것은 **”왜 이 폴더를 여기에 두는가?”**에 대한 명확한 기준과 일관성을 유지하는 것입니다.