의존성 주입(Dependency Injection) 이란?

SANG HUN SHON·2023년 1월 27일
0

해당 포스팅은 참고 사이트에서 읽은 내용을 이해하고자 예제를 따라해본것이니, 참고 사이트 내용을 먼저 읽어보시는 것을 권유드립니다.


포스팅 목적

  • 의존성 주입의 개념을 확실히 이해하자.
  • 의존성 주입이 필요한 이유를 이해하자.

의존성 주입 이란?

외부에서 두 객체간의 의존 관계를 결정해주는 디자인 패턴이다.

인터페이스를 사이에 둬서 클래스 레벨에서는 의존 관계가 고정되지 않도록 하고, 런타임시 관계를 동적으로 주입하여 유연성을 확보하고 결합도를 낮출 수 있게 해준다.


의존성 주입이 필요한 이유

피자를 만들어 파는 Store가 있다고 가정해보자.

public class Store {

    private final Pizza pizza;

    public Store() {
        this.pizza = new Pizza();
    }
}

위 예제의 클래스는 아래와 같은 문제점을 가지고 있다.

  • 두 클래스가 강하게 결합되어 있다.
    • Store에 필요한 Pizza를 스스로 생성한다.
    • 만약 Pizza가 아닌 다른 음식을 팔고자 한다면 Store의 생성자에 변경이 필요하다.
  • 객체들 간의 관계가 아닌, 클래스간의 관계가 맺어진다.
    • 올바른 객체지향적 설계라면, 객체들과의 관계가 맺어져야한다.
    • 객체들간의 관계가 맺어진다면, Store가 제품에 대한 구현 클래스(Pizza)를 알지 못하더라도 인터페이스 타입으로 사용할 수 있다.
    • 근본적인 원인은 Store가 어떤 제품을 팔지에 대한 관심사의 분리가 되지 않았다고 볼수있다.
    • Spring에서는 DI를 활용해서 이같은 문제를 해결한다.

의존성 주입을 통한 문제 해결

위와 같은 문제를 해결하기 위해서는 다형성이 필요하다.
여러 제품을 하나로 표현하기위해 Product 인터페이스를 만든다.
그리고 Pizza에서 Product를 구현하도록 하자.

public interface Product {

}

public class Pizza implements Product {
    
}

이제 StorePizza의 강하게 결합되어 있는 부분을 제거해보자.
아래와 같이 Store 외부에서 판매할 상품을 주입하자.
그래야 Store에서 구체 클래스(Pizza)에 의존하지 않게 된다.

public class Store {

    private final Product product;

    public Store(Product product) {
        this.product = product;
    }
}

여기서 Spring이 DI Container를 필요로 하는 이유를 알 수 있는데, Store에서 Product를 주입받기 위해서 애플리케이션 실행 시점에 필요한 객체를 생성해야 하며, 의존성이 있는 두 객체를 연결시켜 주기 위해 한 객체(Product)를 다른 객체(Store)로 주입 시켜 줘야 한다.

public class Example {

    public static void main(String[] args) {
        Product product = new Pizza();

        // Store를 만들기 위해선, 의존 관계인 Product를 외부에서 주입시켜줘야 한다.
        Store store = new Store(product);
    }
}

Spring에서는 아래와 같이 BeanFactory가 동적으로 의존 관계를 연결시켜주는 역할을 한다.

public class BeanFactory {

    public Store store() {
        Product product = new Pizza();

        // 의존성이 있는 Product를 외부에서 주입시켜줘야 한다.
        Store store = new Store(product);

        return store;
    }
}

이러한 개념은 제어의 역전(Inversion of Control, IoC)라고 불리기도 한다. 어떠한 객체를 사용할지에 대한 책임은 프레임워크에게 넘어갔고, 자신은 수동적으로 주입받는 객체를 사용하기 때문이다.


의존성 주입 정리

한 객체가 어떤 객체(구현 클래스)에 의존 할 것인지는 별도의 관심사이다.
Spring은 의존성 주입을 도와주는 DI 컨테이너로써, 강하게 결합 된 클래스를 분리하고, 애플리케이션 실행 시점에 객체 간의 관계를 설정해줌으로써 결합도를 낮추고 유연성을 확보해준다.

단, 한 객체가 의존 객체를 주입받을려면 반드시 DI 컨테이너에 의해 관리되고 있어야 한다.

하지만 의존 관계를 주입할 객체를 계속 생성하고 소멸한다면, 아무리 GC 성능이 좋아졌어도 부담이 된다.
그래서 Spring에서는 Bean들을 기본적으로 Singleton으로 관리한다.


참고 사이트

https://mangkyu.tistory.com/150

profile
개발이 너무 좋아요

0개의 댓글