공부/Spring
[Spring] DI(의존성 주입) 3가지 방법
맴썰
2022. 2. 21. 19:12
DI(의존성 주입, 종속객체 주입)은 IoC(제어의 역행)의 테크닉 중 하나로 하나의 객체가 다른 객체한테 의존성을 주입하는 테크닉으로, 의존성이란 곧 서비스로 사용가능한 객체를 뜻한다. 테스트의 용이성, 코드 재사용성 향상 및 결합도와 의존도 감소의 효과가 있다.
Spring MVC 프로젝트 초기 생성 시 주어지는 HomeController에 단순히 Hello World 문자열을 반환하는 기능을 가진 서비스를 선언하고, HomeController에 3가지 방법으로 주입시켜볼 것이다.
- DI의 3가지 방법
- 생성자 주입
2. 필드 주입
3. 수정자 주입
스프링 레퍼런스에 따르면 생성자 주입을 가장 추천한다고 한다.
가장 간단해보이는 필드 주입이나 생성자 주입과 별반 다를바 없어 보이는 수정자 주입은 왜 추천하지 않을까?
필드 주입의 단점
- DI Container와의 결합이 매우 강해진다.
- 필드 주입을 하면 모든 스프링 설정이 끝나고, 모든 빈을 읽어야지만 테스트가 가능하다. 따라서 외부에서 사용하기 어려워진다.
- 의존관계가 명확하게 보이지 않아 단일 책임 원칙을 위배하는지 알아채기 힘들다.
- 단순히 @AutoWired를 이용해서 선언만 하면 의존성을 주입시켜주므로 단일 책임 원칙을 위배하는지 잘 보이지 않아 문제점 발견에 힘이 든다는 단점이 있다.
수정자 주입의 단점
- NullPointer Exception
- 위의 사진을 보면 HomeController의 인스턴스는 setHelloService 메소드를 실행시키지 않고도 만들 수 있다. 그 말은 초기화 되지 않은 ReturnHelloService의 변수나 메소드에 접근할 수 있다는 말이고, 이는 NullPointer Exception을 야기할 수 있다.
생성자 주입의 장점
- NullPointer Exception이 발생하지 않는다
- 생성자에 null을 주입시키지 않는 이상 HomeController 객체를 만들기 위해서는 ReturnHelloService 객체가 필요하므로 NullPointer Exception이 발생하지 않는다.
- 의존 관계가 명확히 보인다.
- 생성자의 매개변수로 의존성을 주입하는 객체가 모두 보이므로, 많으면 많아질수록 생성자의 코드가 지저분해지고, 단일 책임 원칙을 위배하는지 쉽게 알 수 있고, 리펙토링을 생각할 수 있다.
- final 키워드 사용가능
- 생성자를 사용하면 final 키워드를 사용할 수 있는데, 이는 중간에 객체를 바꿔치지 할 수 없도록 객체의 불변성을 보장해주기 때문에 보다 안정적인 프로그램을 만들 수 있다.
- 순환참조를 방지할 수 있다.
- A 클래스에서 필드주입이나 수정자 주입을 이용해 의존성을 주입시킨 B를 얻고, B 클래스에서도 마찬가지로 의존성을 주입시킨 A를 얻고 각 생성자에서 반대의 함수를 계속 실행시키면 A 실행-> B 실행의 순서가 무한히 반복되지만 실행상의 문제가 없기 때문에 어떤 오류나 경고도 표시하지 않지만, 생성자 주입을 하면 오류를 발생시켜 대처하기 쉬워진다.