DI / IoC 정리

김도연·2020년 5월 21일
0
post-custom-banner

DI (Dependency Injection : 의존성 주입 )

객체 자체가 아니라 Framework에 의해 객체의 의존성이 주입되는 설계 패턴

Framework에 의해 동적으로 주입되므로 여러 객체 간의 결합이며, Dependency Injection은 Spring Framework에서 지원하는 IoC의 형태로 클래스 간의 의존관계를 빈 설정 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것.

Container가 bean 객체를 생성하고 종속성 주입 수행

DI를 사용하는 이유

  • 객체 내부에서 다른 객체를 생성하는 것은 강한 결합도를 가지는 구조. 객체를 주입받는 다는 것은 외부에서 생성된 객체를 인터페이스를 통해서 넘겨받는 것이기 때문에 결합도를 낮출 수 있고, 런타임시에 의존관계가 결정되기 때문에 유연한 구조를 가짐.
  • new를 통해 직접 객체를 생성할 경우, 내용을 수정할 때 코드를 수정해야 함. 하지만, DI를 사용할 경우, 이를 정의하고 있는 파일만 수정하면 됨.

IoC(Inversion Of Control : 제어의 역전)

프로그램 제어권을 Framework가 가져가는 것으로 DI를 통해 달성됨.

생성된 객체의 생명주기 '전체' 에 대한 권한과 관리를 프레임워크에 주어, 개발자는 비즈니스 로직에만 신경쓰면 됨.

개발자가 annotation, xml 등을 통해 설정을 해놓으면 Container가 알아서 처리함.

스프링 DI 주입방식

  1. XML 구성 파일을 생성하여 주입하는 방식

    XML 구성 파일을 생성하여 설정 값을 입력하고 기능을 사용하고자 하는 클래스에서 불러 사용하는 방식.

    XML 구성 파일을 수정하면 자바 코드를 최대한 수정하지 않기 때문에 재컴파일하지 않더라도 변경사항 쉽게 적용함.

    모델 클래스, 서버 클래스, XML 설정 파일이 분산되어 있어, 데이터 처리정보를 확인하기 위해서는 3파일 모두 봐야됨.

  1. 자바 파일을 생성하여 주입하는 방식

    어노테이션을 이용하는 방식.

    @Configuration 어노테이션으로 주입하고자 하는 클래스 이름 설정하고, @Bean 어노테이션으로 Bean 객체 주입.

    데이터에 대한 유효성을 모델클래스에 직접 명시하기 때문에 컴파일 시 바로 확인이 가능함.

    자바 클래스로 생성된 구성파일은 컴파일 될 시, 내부적으로 XML 파일 형식으로 변경되어 주입하게 됨.

  2. 자바 파일과 XML 파일 두 가지를 사용하여 주입하는 방식

    1) 자바 구성 파일에 XML 파일을 import 하는 방식

    2) XML 파일에 자바 파일을 가지고 와서 XML 파일을 주입하는 방식

의존성 주입 방법

Field Injection : 멤버 변수를 통한 전달

Bean으로 등록된 객체를 사용하고자 하는 클래스에 Field로 선언한 뒤 @Autowired 키워드를 붙여주면 자동으로 주입됨

@Autowired
@Qualifier("myBoardDao") // Qualifier는 동일한 class의 bean이 여러개 존재할 경우 사용함
  private BoardDAO boardDao;

단점

  1. 단일 책임의 원칙 위반

    의존성 주입이 쉬움

  2. 의존성이 숨음

  3. DI 컨테이너의 결합성과 테스트 용이성

    필요한 의존성을 가진 클래스를 곧바로 인스턴스화 시킬 수 없음

  4. 불변성 (Immutability)

    final을 선언할 수 없기 때문에 객체가 변할 수 있음.

  5. 순환 의존성

    순환참조 발생 가능

Method(Setter) Injection : setter() 를 통한 전달

외부에서 생성된 객체를 setter를 통해 사용하는 방법.

순환 참조, coupling (결합도) 등의 문제로 인해 constructor injection 권장함

// java
@Service
public class BoardService{
  private BoardDAO boardDao;
  
  @Autowired
  public void setBoardDao(BoardDao boardDao){
    this.boardDao = boardDao;
  }
}
// XML
<property name="myName" value="poodle"></property>
Constructor Injection : 생성자를 통한 전달

생성자에 @Autowired 어노테이션을 붙여 의존성을 주입하는 방법.

의존관계에 있는 객체들은 반드시 의존관계 주입이 되어야 하기 때문에 이 방법을 권장

// java
//Spring 4.3 버젼 부터 @Autowired 생략가능
// @Autowired 
    public BoardService(BoardDao boardDao) {
        this.boardDao = boardDao;
}
//XML
<constructor-arg ref = "cat"></constructor-arg>

장점

  1. 결합도 제거
    • 종속성이 감소해 변경에 민감하지 않음.
  2. 재사용 코드
    • 일부 인터페이스의 다른 구현이 필요한 경우, 해당 구현을 사용해 components를 구성할 수 있음
  3. 테스트 코드
  • 더 많은 테스트 코드 생성 가능함.
  • Mock 객체는 실제 구현의 테스트로 사용하는 객체로, 종속성을 components에 주입할 수 있을 경우, mock 구현 주입이 가능함.
  1. 가독성 코드
  • components의 종속성을 보다 쉽게 파악 가능

예시1

DI구조

필요한 클래스를 직접 생성하는 것이 아니라 주입함으로써 객체 간의 결합도를 줄이고 유연한 코드 작성 가능함.

출처

DI / IoC 정의 , 방법 및 예시

https://gmlwjd9405.github.io/2018/11/09/dependency-injection.html

DI 주입 방법

https://leejisoo860911.tistory.com/2

profile
지금 나를 알아가는 중입니다
post-custom-banner

0개의 댓글