[CS] 객체 지향의 핵심: DI, DIP, IOC

최지나·2023년 10월 21일
2

CS

목록 보기
7/55

의존성 주입, 의존관계역전원칙, 제어의 역전

DI = Dependency Injection
DIP = Dependency Inversion Principle
IOC = Inversion Of Control

1. DI (의존성 주입)

메인 모듈이 직접 다른 하위 모듈에 대한 의존성을 주기보다는, 중간에 의존성 주입자(dependency injector)가 이 부분을 가로채, 메인 모듈이 '간접적'으로 의존성을 주입하는 방식

  • 의존성 주입을 통해 모듈을 쉽게 교체 가능한 구조로 만들 수 있음
  • Java에서는 주로 생성자, 메서드 혹은 field를 통해 의존 객체를 주입
  • 의존 객체는 주로 인터페이스를 통해 정의. 이를 통해 다른 구체적인 구현을 주입할 수 있음

"의존한다"의 의미

  • A가 B에 의존한다 = B가 변하면 A에 영향을 미친다 = A -> B

1-1 DI가 적용되지 않은 사례

  • class Factory

    • class Product
    • class Toy
  • 상위 클래스인 Factory 클래스가 직접 Product와 Toy에 의존

  • 변경과 확장이 어려우며, 새로운 제품이나 장난감 추가가 어려움

class Product {
    public void manufacture() {
        System.out.println("제품을 생산합니다.");
    }
}

class Toy {
    public void assemble() {
        System.out.println("장난감을 조립합니다.");
    }
}

class Factory {
    private final Product product;
    private final Toy toy;

    public Factory(Product product, Toy toy) {
        this.product = product;
        this.toy = toy;
    }

    public void produce() {
        product.manufacture();
        toy.assemble();
    }
}

1-2 DI가 적용된 사례

  • 위의 Factory class 예시에 DI를 적용 ( = DIP 원칙을 적용)

  • 인터페이스인 Manufacturable 을 도입하여 의존성 주입을 적용

  • Factory 클래스는 Manufacturable 인터페이스에 의존, 제품 및 장난감 클래스는 Manufacturable 인터페이스를 구현

  • 이로써 의존 관계가 역전, 새로운 제품이나 장난감을 쉽게 추가하거나 교체 가능, 의존적인 화살표가 역전됨 (DI를 하게 되면 의존관계역전원칙이 적용된다)

interface Manufacturable {
    void manufacture();
}

class Product implements Manufacturable {
    @Override
    public void manufacture() {
        System.out.println("제품을 생산합니다.");
    }
}

class Toy implements Manufacturable {
    @Override
    public void manufacture() {
        System.out.println("장난감을 조립합니다.");
    }
}

class Factory {
    private final List<Manufacturable> products;

    public Factory(List<Manufacturable> products) {
        this.products = products;
    }

    public void produce() {
        products.forEach(Manufacturable::manufacture);
    }
}

의존성 주입의 장점

  • 모듈을 쉽게 교체할 수 있음
  • 단위 테스트와 마이그레이션이 쉬워짐 (마이그레이션 = 다른 운영 환경으로 이동하는 것)
  • 애플리케이션 의존성 방향이 좀 더 일관되어 코드 추론이 쉬워짐

의존성 주입의 단점

  • 결국에는 모듈이 더 생기기 때문에 복잡성 증가
  • 의존성 주입 자체가 컴파일 시가 아닌 런타임 때 일어나기 때문에 컴파일 시 종속성 주입에 대한 에러를 잡기 어려울 수 있음

2. DIP (의존관계역전원칙)

  • SOLID 원칙 중 하나로 객체 지향 설계 원칙의 한 부분
  • 의존성 주입 시에는 의존관계역전원칙이 적용됨
  • 상위 모듈은 하위 모듈에 의존해서는 안되며 둘 다 추상화에 의존해야 한다.
  • 추상화는 세부사항에 의존해서는 안된다.
  • 인터페이스나 추상 클래스를 사용하여 구체적인 구현에 대한 의존성을 낮추고, 코드의 유연성과 재사용성을 향상시킴

3. IOC (제어의 역전)

  • 제어의 흐름을 외부 엔티티에게 위임
  • 주로 프레임워크나 컨테이너가 객체의 생명 주기를 관리하고 필요한 객체를 제공함으로써 제어의 역전을 구현
  • 보통 의존성 주입과 결합되어 사용되며, 객체 간의 결합을 낮추고 유지보수성을 향상시킴


REF

profile
의견 나누는 것을 좋아합니다 ლ(・ヮ・ლ)

0개의 댓글