Phase 4레슨 18

Hexagonal Architecture (Ports & Adapters)

Port, Adapter, Driving/Driven — 애플리케이션을 육각형으로

💡ELI5·

육각형과 포트

     [HTTP]          [gRPC]        [CLI]
       \              |              /
        \             |             /
    ┌───[Driving Port: PlaceOrder]───┐
    │              Domain             │
    │  ┌─────────────────────────┐    │
    │  │    Order, User, ...     │    │
    │  └─────────────────────────┘    │
    └──[Driven Port: OrderRepo]───────┘
        /              |              \
       /              |               \
   [MySQL]        [Postgres]      [In-Memory]
💡 비유육각형 = 애플리케이션 코어. 각 변 = Port (연결 포트). 포트에 꽂는 플러그 = Adapter. 같은 포트에 다른 플러그를 꽂으면 다른 DB/프레임워크로 교체. 코어는 플러그가 뭔지 모른다.
🔬Deep Dive·

Driving vs Driven

구분방향예시교체 예
Driving Port외부 → 내부 (입력)PlaceOrderUseCase 인터페이스REST → gRPC → CLI
Driven Port내부 → 외부 (출력)OrderRepository 인터페이스MySQL → MongoDB → In-Memory
Driving AdapterDriving Port를 호출REST Controller, gRPC Handler프레임워크 교체
Driven AdapterDriven Port를 구현MySQLOrderRepositoryDB 교체
🔬Deep Dive·

실제 구조 예시

// Port (내부에 정의)
interface PlaceOrderPort {
  execute(cmd: PlaceOrderCommand): Promise<Order>;
}
interface OrderRepositoryPort {
  save(order: Order): Promise<void>;
}

// Domain (내부, 외부 모름)
class OrderApplication implements PlaceOrderPort {
  constructor(private repo: OrderRepositoryPort) {}
  async execute(cmd: PlaceOrderCommand) {
    const order = Order.create(cmd.items);
    await this.repo.save(order);
    return order;
  }
}

// Driving Adapter (외부 — REST)
class OrderRestController {
  constructor(private app: PlaceOrderPort) {}
  @Post('/orders')
  async create(@Body() body) {
    return this.app.execute(new PlaceOrderCommand(body.items));
  }
}

// Driven Adapter (외부 — MySQL)
class MySQLOrderAdapter implements OrderRepositoryPort {
  async save(order: Order) { /* SQL */ }
}
⚖️Trade-off·

Hexagonal vs Clean

구분HexagonalClean
핵심 모델Port & Adapter (경계)Layer (양파)
강조점외부와의 연결 포트의존성 방향
실용성인터페이스 기반 명확계층 분리 명확
실제혼용해서 사용 (같은 원칙)혼용해서 사용

❓ 체크포인트 질문

  1. 1.Port와 Adapter의 차이는?
  2. 2.Driving Port와 Driven Port의 차이는?
  3. 3.Hexagonal과 Clean Architecture의 공통점과 차이점은?
  4. 4.Hexagonal에서 REST API를 gRPC로 교체할 때 무엇이 바뀌는가?
  5. 5.Hexagonal Architecture가 테스트에 유리한 이유는?