DI

의존성 주입이란?

  • 객체 자체가 아니라, 외부 (Framework 등)에 의해 객체 의존성이 주입되는 설계 패턴

  • 필요로 하는 오브젝트를 스스로 생성하는 것이 아닌, 외부로부터 주입받는 기법

    • 필요한 자원을 외부에서 넣어주는게 바로 의존성 주입이다

DI 와 IoC (Inversion of Control)

  • Dependency Injection은 IoC 개념이 적용된 결과물 중 하나이다

    • 의존성을 주입한다는 것을 IoC 적인 행위로 바라볼 수 있지만, IoC와 의존성 주입이 같은 것은 아니다

DI와 DIP (Dependency Inversion Principle)

DI는 DIP를 구현하는 기법중 하나일 뿐 서로 같은 개념이 아니다

스프링에서의 의존성 주입이란?

  • 스프링은 DI라는 방식을 이용하여 모듈간 결합도를 낮추어준다

  • 스프링에서의 DI란 Spring IoC Container 가 개발자 대신 정의된 대로 Bean 객체를 생성하고 의존성을 대신 주입 하는 것을 의미한다

    • 여기서 IoC란 제어의 역전이라는 말로 사용자가 직접 객체를 생성하고 관리하던 것을, Spring의 IoC Container가 대신 해준다는 말이다

스프링에서는 어떻게 구현하는가?

  • 개발자가 해야하는 일

    • Bean class 작성

    • 주입을 위한 설정 (xml파일 기술 또는 @(어노테이션) 기술)

왜 의존성 주입을 사용해야 하는가?

  • 의존성 주입을 이용하면 결합도를 낮출 수 있다

  • 느슨한 결합이 가능하도록 유도할 수 있게 되고, 이 과정에서 OCP 원칙을 적용할 수 있게 된다

    • OCP (Open Closed Principle - 개방 폐쇄 원칙)

      • 확장에 대해 열려있고, 수정에 대해서는 닫혀있어야 한다는 원칙

  • 스프링은 IoC 를 기반으로 동작한다

    • IoC를 이용하면 로직 실행과 구현의 분리 가 가능해지며, 구현 간의 전환이 쉬워진다

    • 컨테이너가 Bean의 라이프 사이클을 관리하므로, 개발자의 관리 포인트가 줄어든다는 장점이 있다

    • IoC에서 사용하는 패턴이 바로 DI이다

DI 방식과 장단점

Spring Framework에서는 Dependency Injection을 3가지 방식으로 지원하고 있다

생성자 (constructor) 주입

생성자에 의존성 주입을 받고자 하는 field를 나열하는 방법으로, 권고되는 방법 중 하나이다

  • 장점

    • 인스턴스가 생성되었을 때 의존성이 존재하는 것이 보장되기 때문에, 의존성 존재 여부가 보장되고 의존상을 immutable 하게 정의할 수 있다

    • 필수적으로 사용해야 하는 레퍼런스 없이는 인스턴스를 만들지 못하도록 강제한다

    • Spring 4.3 이상부터는, 생성자가 하나인 경우 @Autowired를 사용하지 않아도 된다

      • 묵시적 생성자 자동 주입

    • Circular Dependency (순환 참조) 의존성을 알아차릴 수 있다

    • 의존성 대상 field를 final 로 불변 객체를 선언할 수 있다

    • Test case 작성 시, 생성자를 통해 의존성 주입이 용이하다

  • 단점

    • 어쩔 수 없는 순환 참조는 생성자 주입으로 해결하기 어렵다

      • 이 때 나머지 주입 방법을 사용하도록 하지만, 순환 참조가 발생하지 않도록 하는 것이 중요하다

수정자 (setter) 주입

setter method에 @Autowired annotation을 선언하여 주입하는 방법

  • 장점

    • 의존성이 선택적으로 필요한 경우에 사용

    • 생성자에 모든 의존성을 기술하면 과도하게 복잡해질 수 있는 것을 선택적으로 나눠서 주입할 수 있다

  • 유의할 점

    • 주입 받은 의존성의 기본값을 정의할 수 없다면, null 값이 존재할 수 있다

  • 단점

    • 의존성 주입 대상 필드에 final로 불변 객체를 선언할 수 없다

field 주입 → Deprecated

member field에 @Autowired annotation을 선언하여 주입하는 방법

  • 장점

    • 코드가 간결해진다

  • 단점

    • 의존 관계가 눈에 보이지 않아 추상적이고, 이로 인해 의존성 관계가 복잡해질 수 있다

    • SRP (Single Responsibility Principle: 단일 책임 원칙)에 반하는 anti-pattern

    • Unit test 시 의존성 주입이 용이하지 않다

    • 의존성 주입 대상 필드에 final을 선언할 수 없다

결론: 생성자 주입과 setter 주입을 적절히 상황에 맞게 사용하자!

Last updated