의존성 주입 (Dependency Injection)

SEUNGJUN·2024년 1월 22일

DI?

소프트웨어 개발에서 객체 간의 의존 관계를 외부에서 설정하고 주입하는 디자인 패턴으로 의존성 주입을 통해서 객체 간의 결합도를 낮추고 코드의 재사용성과 테스트 용이성을 증가시킬수가 있다.

DI의 주요 개념

1. 의존성(Dependency)

  • 객체가 다른 객체에 의존하는 경우, 이를 의존성이 있다고 한다. 예시로 클래스 A가 클래스 B의 메서드나 속성을 하용하는 경우에 A는 B에 의존성이 있다고 할수 있다.

2. 의존성 주입(Dependency Injection)

  • 의존성 주입은 객체가 직접 의존하는 객체를 생성하거나 참조하는것이 아니라, 외부에서 의존 객체를 주입받는 디자인 패턴이다.

DI 왜 써야할까?

1. 의존성 역전(Dependency Inversion)

  • DI는 의존성 역전 원칙을 따른다. 상위 수준 모듈이 하위 수준 모듈에 의존하는 전통적인 의존성과 달리, 인터페이스나 추상 클래스를 통해 의존성을 주입함으로써 역전 시킨다.
// 전통적인 의존성 (ioc)
class Engine {
    // 엔진의 기능들...
}

class Car {
    private Engine engine;

    public Car() {
        this.engine = new Engine();
    }
}
// 의존성 역전을 이용한 DI
interface Engine {
    void start();
    // 엔진의 기능들...
}

class Car {
    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }
}

전통적인 의존성은 상위 수준 모듈이 하위 수준 모듈에 의존하는 구조인데 DI에서는 이런 관계가 역전 되어 있다. 예시로 위와 같이 Car 클래스는 직접적으로 Engine을 생성하는 게 아니라 외부에서 주입을 받아와서 사용하게 되므로, 엔진의 구체적인 구현에 대한 의존성이 낮아지게 되는것이다.

2. 유연성과 테스트 용이성

  • DI를 사용하면 의존성을 외부에서 주입하기 때문에 코드 변경이 쉬워지고, 테스트에서 모의 객체 등을 통한 단위 테스트가 용이해진다.
// 테스트를 위한 Mock 객체
class MockEngine implements Engine {
    void start() {
        // Mock 엔진의 동작 정의...
    }
}

// 테스트 코드
class CarTest {
    @Test
    void testCarStart() {
        Engine mockEngine = new MockEngine();
        Car car = new Car(mockEngine);
        // 테스트 수행...
    }
}

테스트할 때 실제 엔진 대신 MockEngine을 주입해서 Car 클래스의 동작을 테스트 할수가 있다.

3. 코드 재사용성

  • 의존성을 주입받기 때문에 재사용성이 높아진다. 동일한 객체를 여러 컨텍스트에서 쉽게 재사용할 수 있다.
class Bike {
    private Engine engine;

    public Bike(Engine engine) {
        this.engine = engine;
    }
}

Car가 아닌 Bike와 같은 다른 컨텍스트에서도 Engine을 주입받아 재사용이 가능하다.

3. 결합도 감소

  • 객체 간의 결합도가 낮아져서 각 객체가 독립적으로 존재 하고, 변경이 다른 객체에 미치는 영향이 줄어든다.
class Ship {
    private Engine engine;

    public Ship(Engine engine) {
        this.engine = engine;
    }
}

Car 클래스는 어떤 종류의 Engine을 사용할지에 대해 결정을 내부적으로 하지않고, 외부에서 주입을 받기 때문에 객체 간의 변경이 서로에게 미치는 영향이 줄어든다. Ship 클래스가 Engine을 사용해도, Car 클래스에는 영향이 미쳐지지 않는다. 이렇게 되면 객체 간의 독립성이 높아지고, 유연성을 확보하는데 도움이 된다.

profile
RECORD DEVELOPER

0개의 댓글