/
Inbound Port와 Outbound Port의 정의 및 접근 방향

Inbound Port와 Outbound Port의 정의 및 접근 방향

1. Inbound Port

정의:

  • 애플리케이션의 내부(Core Domain 또는 비즈니스 로직)로 들어오는 요청을 처리하기 위한 인터페이스.

  • 외부 계층(예: Controller, API Gateway 등)이 비즈니스 로직을 호출하기 위해 사용하는 진입점.

접근 방향:

  • 외부에서 내부로의 접근이 허용됩니다.

    • Controller → Inbound Port → Application Logic의 흐름.

  • 내부(Core)는 Inbound Port에 의존하지 않으며, 이 Port를 구현하는 어댑터가 외부 계층에서 이를 호출합니다.

예시:

// Inbound Port 인터페이스 public interface OrderService { OrderResponse processOrder(OrderRequest request); } // 구현체 (Application Layer) @Service public class OrderServiceImpl implements OrderService { @Override public OrderResponse processOrder(OrderRequest request) { // 비즈니스 로직 처리 return new OrderResponse(...); } } // Controller에서 Inbound Port 호출 @RestController @RequestMapping("/orders") public class OrderController { private final OrderService orderService; public OrderController(OrderService orderService) { this.orderService = orderService; } @PostMapping public ResponseEntity<OrderResponse> createOrder(@RequestBody OrderRequest request) { return ResponseEntity.ok(orderService.processOrder(request)); } }

 

  • 접근 방향:

    • 외부(Controller) → 내부(OrderService).


2. Outbound Port

정의:

  • 애플리케이션 내부(Core Domain 또는 비즈니스 로직)에서 외부 시스템(예: 데이터베이스, API, 메시지 브로커 등)과 상호작용하기 위한 인터페이스.

  • 외부 의존성(예: 구현체)을 캡슐화하여, 내부(Core)가 구체적인 외부 시스템에 의존하지 않도록 설계.

접근 방향:

  • 내부에서 외부로의 접근이 허용됩니다.

    • Application Logic → Outbound Port → Adapter → External System의 흐름.

  • 내부(Core)는 Outbound Port에 의존하며, 구현체(Adapter)는 외부 시스템과 상호작용을 처리합니다.

예시:

// Outbound Port 인터페이스 public interface NotificationConfigRepository { NotificationConfig findById(Long id); NotificationConfig save(NotificationConfig config); } // 구현체 (Adapter) @Repository public class JpaNotificationConfigRepository implements NotificationConfigRepository { private final JpaRepository<NotificationConfig, Long> jpaRepository; public JpaNotificationConfigRepository(JpaRepository<NotificationConfig, Long> jpaRepository) { this.jpaRepository = jpaRepository; } @Override public NotificationConfig findById(Long id) { return jpaRepository.findById(id) .orElseThrow(() -> new RuntimeException("Config not found")); } @Override public NotificationConfig save(NotificationConfig config) { return jpaRepository.save(config); } } // 비즈니스 로직에서 Outbound Port 호출 @Service public class NotificationService { private final NotificationConfigRepository configRepository; public NotificationService(NotificationConfigRepository configRepository) { this.configRepository = configRepository; } public void updateNotification(Long id, boolean isActive) { NotificationConfig config = configRepository.findById(id); config.setActive(isActive); configRepository.save(config); } }

 

  • 접근 방향:

    • 내부(NotificationService) → 외부(NotificationConfigRepository).


Inbound Port와 Outbound Port의 접근 규칙

1. 접근 방향의 규칙

  • Inbound Port는 외부에서 내부로 접근하는 데 사용됩니다.

    • 예: ControllerService 호출.

  • Outbound Port는 내부에서 외부로 접근하는 데 사용됩니다.

    • 예: ServiceRepository 호출.

2. 의존성 역전 원칙(DIP)의 적용

  • Inbound Port와 Outbound Port 모두 구현체(Adapter)에 의존하지 않도록 설계되어야 합니다.

    • Inbound Port: 외부 계층은 Port 인터페이스에 의존.

    • Outbound Port: 내부(Core)는 Port 인터페이스에 의존.


Inbound Port와 Outbound Port의 외부 Feature 접근 허용 여부

1. Inbound Port 접근 허용 여부

  • 허용: 외부 계층(Controller 등)이 해당 Feature의 비즈니스 로직을 호출하기 위해 사용.

  • Feature 간 공유는 비추천:

    • Inbound Port는 Feature의 비즈니스 로직에 특화된 인터페이스이므로, 다른 Feature에서 직접 호출하지 않는 것이 원칙.

    • 다른 Feature에서 호출하려면, 해당 Feature에 새로운 Inbound Port를 정의하는 것이 바람직합니다.

2. Outbound Port 접근 허용 여부

  • 허용: Outbound Port는 외부 시스템과의 상호작용을 추상화하므로, 다른 Feature에서도 활용 가능.

  • 공유 Port가 필요한 경우:

    • Outbound Port를 공통 모듈(common 또는 shared)로 분리하여 여러 Feature에서 사용할 수 있도록 설계합니다.


결론

  • Inbound Port: 외부에서 내부로의 접근만 허용하며, 다른 Feature에서의 직접적인 접근은 지양.

  • Outbound Port: 내부에서 외부로의 접근을 위해 사용되며, 여러 Feature에서 재사용하려면 공통 모듈로 분리.

헥사고날 아키텍처의 철학에 따라, 의존성의 방향을 유지하면서 접근 방향을 결정해야 합니다. 필요하면 더 구체적으로 설계를 도와드리겠습니다! 😊