Phase 4레슨 17

Clean Architecture

Dependency Rule, Entity, Use Case, Interface Adapter — 의존성이 안쪽으로만

💡ELI5·

양파와 Clean Architecture

┌─────────────────────────────────┐
│ Frameworks & Drivers (DB, Web)  │  외부 — 변경 가능, 의존함
│  ┌───────────────────────────┐  │
│  │ Interface Adapters        │  │
│  │  ┌─────────────────────┐  │  │
│  │  │ Use Cases           │  │  │
│  │  │  ┌───────────────┐  │  │  │
│  │  │  │   Entities    │  │  │  │  내부 — 핵심, 독립
│  │  │  └───────────────┘  │  │  │
│  │  └─────────────────────┘  │  │
│  └───────────────────────────┘  │
└─────────────────────────────────┘

Dependency Rule: → 안쪽으로만 의존
💡 비유양파의 속심 = Entity (가장 중요, 변하지 않음). 껍질 = DB, Web Framework (교체 가능). 속심은 껍질이 뭔지 모르지만, 껍질은 속심을 감싼다. 의존성은 껍질 → 속심 방향으로만.
🔬Deep Dive·

4계층 구조

계층역할예시
Entity핵심 비즈니스 규칙, 도메인 객체User, Order (순수 객체, 프레임워크 없음)
Use Case애플리케이션 비즈니스 로직, 사용자 시나리오CreateOrderUseCase, LoginUseCase
Interface Adapter외부와 내부의 변환 (Controller, Presenter, Gateway)OrderController, OrderDTO, Repository 구현체
Framework/DriverDB, Web Framework, 외부 서비스Express, MySQL, Redis
🔬Deep Dive·

Dependency Inversion — 핵심 메커니즘

// 내부 (Use Case) — 인터페이스를 정의 (외부를 모름)
interface OrderRepository {
  save(order: Order): Promise<void>;
  findById(id: string): Promise<Order | null>;
}

class PlaceOrderUseCase {
  // 인터페이스에 의존 — 실제 구현체는 외부에서 주입
  constructor(private orderRepo: OrderRepository) {}

  async execute(items: CartItem[]): Promise<Order> {
    const order = Order.create(items);
    await this.orderRepo.save(order); // 인터페이스 호출
    return order;
  }
}

// 외부 (Infrastructure) — 내부 인터페이스를 구현
class MySQLOrderRepository implements OrderRepository {
  async save(order: Order) {
    await db.query('INSERT INTO orders ...', order);
  }
  async findById(id: string) {
    return db.query('SELECT * FROM orders WHERE id = ?', id);
  }
}

// 조립 (Composition Root)
const repo = new MySQLOrderRepository(db);
const useCase = new PlaceOrderUseCase(repo); // 외부 → 내부로 주입
Use Case는 MySQL이나 PostgreSQL을 모른다. OrderRepository 인터페이스만 알 뿐. DB를 In-Memory로 바꾸려면 MySQLOrderRepository → InMemoryOrderRepository로 교체하면 된다. Use Case 코드는 변경 없음.
⚖️Trade-off·

Clean Architecture의 장단점

장점단점
도메인이 프레임워크/DB에 독립추상화 계층 많음 (코드량 증가)
테스트 용이 (Mock 주입)단순 CRUD에 과도한 구조
외부 교체 용이 (DB, Framework)학습 곡선 가파름
비즈니스 규칙이 명확히 분리간접 호출로 디버깅 추적 어려움

❓ 체크포인트 질문

  1. 1.Clean Architecture의 Dependency Rule이란?
  2. 2.Clean Architecture에서 DB를 교체하기 쉬운 이유는?
  3. 3.Entity와 Use Case의 차이는?
  4. 4.Clean Architecture의 단점은?
  5. 5.Clean Architecture에서 인터페이스가 왜 외부가 아닌 내부에 정의되는가?