alt
Home 의존성 주입(Dependency injection)과 세가지 방법
Post
Cancel

의존성 주입(Dependency injection)과 세가지 방법


  • 스프링은 빈 컨테이너를 통해 빈 객체를 관리해준다 (IoC). 이 때, 필요한 곳에 적절히 객체를 주입해 사용해야 한다. (DI)
  • 사실 스프링을 사용하지 않더라도, 객체 지향적 관점에서 사용되는 개념


의존성

: 어떠한 객체 A가 다른 객체 혹은 인터페이스 B를 사용할 때 A는 B에 대한 의존성이 발생하며, “A는 B에 의존한다.” 라고 말한다.


강한 결합

  • A클래스에서 B 객체를 생성하고 있다고 가정 할 때 A는 B에 강한 의존 관계를 갖는다.
    • e.g.) Person 클래스 내부에 Chicken 객체를 생성하는 부분이 있다고 할 때, Chicken이 아니라 Pizza가 되려면 Person 클래스 내부를 변경해야한다.
  • 유연성을 떨어트리고, 변경을 어렵게 만든다.


약한(느슨한) 결합

  • 객체를 주입받음.
    • 외부에서 생성된 객체를 Interface를 통해 넘겨받아 결합도를 낮추고, 유연한 구조를 갖으며 변경을 용이하게 만듦
    • 위의 예시에서 Person 클래스는 Food Interface를 갖도록 하면, Chicken이든 Pizza든 Food에 주입(?)하도록 만들면 됨(implement)
  • 이렇게 하면 Chicken -> Pizza로 변경할때 그 구현체만 변경하면 됨.


의존성 주입 방법 세가지

의존성 주입받을 클래스 A, 주입될 객체 B라고 가정.


1. Field Injection

: @Autowired로 의존성 주입받는 방법

  • 일단 간편하다. 그러나 많은 단점이 존재.
  • DI 컨테이너와의 결합성과 테스트 용이성
    • 일단 의존성을 받았으면, 독립적으로 Instance화 가능한 POJO여야 한다. Test 환경에서 Spring Been 컨테이너 없이 돌아가야 하는데, 이 방식으로 사용한다면 일단 테스트에 용이하지 않다.
  • 단일 책임 원칙 위반 가능성
    • 의존성을 주입하기 쉬워지고, 의존 객체가 많아지면 하나의 클래스가 많은 책임을 갖게 될 수 있음
  • 의존관계가 보이지 않음
    • DI 컨테이너에게 의존성 관리 책임을 위임하는 것이기 때문에 클래스 의존관계가 명확히 보이지 않는다.
  • 불변성 불가
    • (자바 기준) final 선언 불가. 따라서 객체가 불변성이 아님. Contructor Injection에서는 final로 명시해 불변 객체로 만들 수 있다.


2. Setter Injection

: setter를 통해 선택적으로 주입된 객체를 사용할 때

  • 런타임에 수정자를 통해 의존성 주입을 하게 됨. -> 런타임 에러 우려
  • setter를 통해 주입하려는 객체가 주입 되지 않았어도 베이스 객체는 얼마든지 생성, 사용될 수 있다는 것이 문제
    • e.g) 만약 주입된 객체 본체(구현체)가 없는 상황이라고 가정할 때
      • 일단 컴파일타임에는 생성, 사용 가능.
      • 그러나 해당 의존 객체를 사용하려한다면 주입이 되지 않았기 때문에 NPE 발생 우려


3. Constructor Injection - 가장 권장.

: 객체를 생성하는 시점에 바로 의존성 주입.

  • Spring에서 가장 권장하는 방식
  • 순환 의존성을 알 수 있다.
    • 컴파일 단계에서 확인 가능. BeanCurrentlyInCreationException 발생
  • 필수적으로 사용해야하는 것 없이는 Instance를 만들지 못하도록 강제할 수 있음.
    • 항상 의존관계가 주입되기 때문에 Setter에서의 NPE 문제를 피할 수 있다.
  • 의존성 주입이 번거롭다
    • 따라서 만약 생성자에서 너무 의존관계가 많아진다면 SRP 원칙을 고려하게 되고, 리팩토링이 필요한 시점이라는 것을 알 수 있게 된다.
  • 테스트 용이
    • DI 컨테이너와 결합도가 낮아 갖고 있는 의존성을 Instance화 할 수 있음.
  • 불변으로 만들 수 있다.
    • Kotlin에서는 기본적으로 val로 선언, java -> final



Reference)

https://velog.io/@gillog/Spring-DIDependency-Injection-%EC%84%B8-%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95

https://velog.io/@damiano1027/Java-%EA%B0%95%ED%95%9C-%EA%B2%B0%ED%95%A9%EA%B3%BC-%EC%95%BD%ED%95%9C-%EA%B2%B0%ED%95%A9

https://ohjongsung.io/2017/06/02/%ED%95%84%EB%93%9C-%EC%A3%BC%EC%9E%85-field-injection-%EC%9D%84-%ED%94%BC%ED%95%98%EC%9E%90

This post is licensed under CC BY 4.0 by the author.