헥사고날 아키텍처 – 주문 기능의 흐름

주문(Order) 기능의 흐름

“사용자(Web)가 책을 주문(place order)한다.” 라는 하나의 유스케이스가 어떻게 각 계층을 통과하는지 따라가 보겠습니다.


1. 인바운드(Inbound) 흐름: 외부 요청이 비즈니스 로직으로 들어오는 과정

외부 요청자(사용자)  웹 어댑터(Controller)  인바운드 포트(UseCase)  서비스(UseCase 구현체)

  1. PlaceOrderController.java (인바운드 어댑터)
    • 위치: adapter/in/web/
    • 역할: 사용자의 HTTP POST /orders 요청을 받습니다. JSON 요청 본문(PlaceOrderRequest)을 파싱합니다.
    • 코드의 핵심:
  2. PlaceOrderUseCase.java (인바운드 포트)
    • 위치: application/port/in/
    • 역할: “주문하기” 기능의 명세서(스펙)입니다. “주문하기”라는 행위가 존재함을 선언합니다.
    • 코드의 핵심:

  3. PlaceOrderService.java (서비스, 유스케이스 구현체)
    • 위치: application/service/
    • 역할: PlaceOrderUseCase 인터페이스를 실제로 구현합니다. 주문 생성과 관련된 실제 비즈니스 로직을 수행합니다.
    • 코드의 핵심:

2. 아웃바운드(Outbound) 흐름: 비즈니스 로직이 외부 기술을 사용하는 과정

서비스(UseCase 구현체)  아웃바운드 포트(Port)  영속성 어댑터(Persistence Adapter)  외부(DB)

  1. PlaceOrderService.java (서비스, 유스케이스 구현체)
    • 위에서 본 PlaceOrderService는 주문을 생성한 후, 이를 저장하기 위해 아웃바운드 포트 SaveOrderPort를 호출합니다.
    • PlaceOrderService SaveOrderPort가 어떻게 구현되었는지(JPA인지, MyBatis인지) 전혀 알지 못합니다. 그저 “저장”이라는 기능이 존재하고 호출할 수 있다는 것만 압니다.
  2. SaveOrderPort.java (아웃바운드 포트)
    • 위치: application/port/out/
    • 역할: 데이터베이스에 “주문을 저장하는” 기능의 명세서입니다. 애플리케이션이 외부(영속성 계층)에 무엇을 요구하는지 정의합니다.
    • 코드의 핵심:
  3. OrderPersistenceAdapter.java (영속성 어댑터, 아웃바운드 포트 구현체)
    • 위치: adapter/out/persistence/
    • 역할: SaveOrderPort 인터페이스를 실제로 구현합니다. JPA, OrderJpaEntity, OrderJpaRepository 와 같은 실제 DB 기술을 사용하여 데이터를 저장합니다.
    • 코드의 핵심:

요약: 소스 이름으로 보는 관계

단계 파일명 (역할) 계층 설명
1 PlaceOrderController.java Inbound Adapter HTTP 요청을 받음
2 PlaceOrderUseCase.java (인터페이스) Inbound Port 컨트롤러가 호출할 기능(placeOrder)을 정의
3 PlaceOrderService.java Service PlaceOrderUseCase를 구현. 비즈니스 로직 수행
4 SaveOrderPort.java (인터페이스) Outbound Port 서비스가 DB에 요청할 기능(save)을 정의
5 OrderPersistenceAdapter.java Outbound Adapter SaveOrderPort를 구현. 실제 JPA 코드로 DB에 저장

이처럼 각 파일의 이름과 위치는 그 파일의 역할과 책임을 명확하게 나타내도록 짓는 것이 헥사고날 아키텍처를 유지하는 데 매우 중요합니다.