공부/Spring

[Spring] DI(의존성 주입) 3가지 방법

맴썰 2022. 2. 21. 19:12

DI(의존성 주입, 종속객체 주입)은 IoC(제어의 역행)의 테크닉 중 하나로 하나의 객체가 다른 객체한테 의존성을 주입하는 테크닉으로, 의존성이란 곧 서비스로 사용가능한 객체를 뜻한다. 테스트의 용이성, 코드 재사용성 향상 및 결합도와 의존도 감소의 효과가 있다.

Spring MVC 프로젝트 초기 생성 시 주어지는 HomeController에 단순히 Hello World 문자열을 반환하는 기능을 가진 서비스를 선언하고, HomeController에 3가지 방법으로 주입시켜볼 것이다.

  • DI의 3가지 방법
  1.  생성자 주입

  2.  필드 주입

 3.   수정자 주입

 

스프링 레퍼런스에 따르면 생성자 주입을 가장 추천한다고 한다.

가장 간단해보이는 필드 주입이나 생성자 주입과 별반 다를바 없어 보이는 수정자 주입은 왜 추천하지 않을까?

필드 주입의 단점

  • DI Container와의 결합이 매우 강해진다.
    • 필드 주입을 하면 모든 스프링 설정이 끝나고, 모든 빈을 읽어야지만 테스트가 가능하다. 따라서 외부에서 사용하기 어려워진다. 
  •  의존관계가 명확하게 보이지 않아 단일 책임 원칙을 위배하는지 알아채기 힘들다.
    • 단순히 @AutoWired를 이용해서 선언만 하면 의존성을 주입시켜주므로 단일 책임 원칙을 위배하는지 잘 보이지 않아 문제점 발견에 힘이 든다는 단점이 있다.

수정자 주입의 단점 

  • NullPointer Exception
    • 위의 사진을 보면 HomeController의 인스턴스는 setHelloService 메소드를 실행시키지 않고도 만들 수 있다. 그 말은 초기화 되지 않은 ReturnHelloService의 변수나 메소드에 접근할 수 있다는 말이고, 이는 NullPointer Exception을 야기할 수 있다.

 

생성자 주입의 장점

  1. NullPointer Exception이 발생하지 않는다 
    • 생성자에 null을 주입시키지 않는 이상 HomeController 객체를 만들기 위해서는 ReturnHelloService 객체가 필요하므로 NullPointer Exception이 발생하지 않는다.
  2.  의존 관계가 명확히 보인다.
    • 생성자의 매개변수로 의존성을 주입하는 객체가 모두 보이므로, 많으면 많아질수록 생성자의 코드가 지저분해지고, 단일 책임 원칙을 위배하는지 쉽게 알 수 있고, 리펙토링을 생각할 수 있다.
  3. final 키워드 사용가능
    •  생성자를 사용하면 final 키워드를 사용할 수 있는데, 이는 중간에 객체를 바꿔치지 할 수 없도록 객체의 불변성을 보장해주기 때문에 보다 안정적인 프로그램을 만들 수 있다.
  4. 순환참조를 방지할 수 있다.
    • A 클래스에서 필드주입이나 수정자 주입을 이용해 의존성을 주입시킨 B를 얻고, B 클래스에서도 마찬가지로 의존성을 주입시킨 A를 얻고 각 생성자에서 반대의 함수를 계속 실행시키면 A 실행-> B 실행의 순서가 무한히 반복되지만 실행상의 문제가 없기 때문에 어떤 오류나 경고도 표시하지 않지만, 생성자 주입을 하면 오류를 발생시켜 대처하기 쉬워진다.