[Spring] IoC(제어의 역전) & DI(의존성 주입)의 개념

1. IoC (Inversion of Control) 제어의 역전

출처 : https://june0122.tistory.com/18

 

IoC란 메인 프로그램에서 컨테이너나 프레임워크로 객체와 객체의 의존성에 대한 제어를 넘기는 것을 말한다. 프레임워크 없이 개발할 때는 각 객체에 대한 라이프사이클 (생성, 설정, 초기화, 호출 등)을 개발자가 직접 관리한다. 하지만 프레임워크를 사용하면 객체의 생명주기를 프레임워크에 위임하여, 프레임워크가 개발자의 코드를 호출하고 흐름을 제어하게 할 수 있다.

 

이처럼, 제어의 역전은 객체를 직접 생성하거나 제어하는 것이아니라 외부에서 관리하는 객체를 가져와서 사용하는 것으로, 클레스 간의 결합을 느슨하게 하여 테스트와 유지관리를 더 쉽게 설계하는 원칙이다.

 

IoC는 설계 패턴이 아닌 원칙이며 세부 구현은 개발자에게 달려있다. 스프링 컨테이너에서는 프로그램 내 객체의 라이프사이클을 인스턴스화하여 관리한다. XML, Java Annotation, Java 코드 등을 통해 애플리케이션에 필요한 객체 및 의존성 정보를 제공한다.

 

IoC 컨테이너의 2가지 핵심 클래스는 다음과 같다.

  • BeanFactory - 자바 객체(bean) 인스턴스의 라이프사이클을 관리하는 실질적인 컨테이너이며, 구동될 시가 아니라 요청이 있을 때 Bean 객체를 생성한다.
  • ApplicationContext - 구동되는 시점에 등록된 Bean 객체를 스캔하여 객체화한다.

결론적으로 IoC는...

  • 어플리케이션 내의 코드 양을 줄인다.
  • 클래스 간 결합을 느슨하게 한다.
  • 애플리케이션 유지관리 및 테스트를 유리하게 한다.
  • 어플리케이션 제어 책임이 개발자에서 프레임워크로 위임되므로, 핵심 비즈니스 로직에 더 집중할 수 있다.

 

2. DI (Dependency Injection, 의존성 주입)

의존성 주입은 프로그램 디자인이 결합도를 느슨하게 되도록 하고 의존관계 역전원칙과 단일 책임 원칙을 따르도록 클라이언트의 생성에 대한 의존성을 클라이언트 행위로부터 분리하는 것이다.

2-1. 의존성 주입이란?

A가 B에게 "의존"한다는 표현이 어떤 뜻일까? 한 객체가 다른 객체를 사용할 때 의존성이 있다고 표현하며 크게는 다음과 같은 상황에 의존한다고 한다.

  • 상속 또는 구현하는 경우
  • 메서드를 호출하는 경우
  • A에서 B를 호출하는 경우

예를 들면 다음과 같은 경우에 Store객체가 Pencil객체에 의존성이 있다고 표현한다.

public class Store {
    private Pencil pencil;
}

출처 : https://mangkyu.tistory.com/150

 

DI는 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴으로, 인터페이스를 사이에두고 클래스 레벨 의존관계가 고정되지 않도록 관계를 동적으로 주입하여 결합도를 낮출수 있게 해 준다. 어떤 객체가 사용하는 의존 객체를 직접 생성하는 것이 아니라, 주입을 받아 사용 하는것이다. 스프링에서의 의존성 주입은, 각 객체간의 의존관계를 스프링 컨테이너에서 개발자가 정의한 Bean 정보를 바탕으로 자동으로 주입해주는 기능을 의미한다. 이를통해 객체간 결합도를 낮추고 코드양을 줄여주며 유지보수를 편하게 해준다.

2-2. 의존성 주입 방식

생성자주입, 필드주입, 수정자 주입등의 방법이 있다.

  • 생성자 주입 (권장)
@Controller 
public class Controller{
   private Service service;

   @Autowired 
   public Controller(Service service){
     this.service = service; 
   }
}
  • 필드 주입
@Controller
public class Controller{
  @Autowired 
  private Service service;
}

 

  • 수정자 주입
@Controller 
public class Controller{
   private Service service;

   @Autowired 
   public setService(Service service){
     this.service = service; 
   }
}

 

결론적으로 DI는...

  • 객체를 직접 생성하는 것이 아닌, 외부에서 생성된 객체를 주입받아서 사용하는 것이다.
  • 강하게 결합된 클래스들을 분리하고, 애플리케이션 실행시점에 관계를 결정해 준다.
  • 결합도를 낮추고 유연성을 확보하여 테스트를 용이하게 하며 개발 및 유지보수를 쉽게 해 준다.

 

 

 

 

 

참고

https://kim-oriental.tistory.com/32

https://mangkyu.tistory.com/150

도서 : 스프링 부트 3 백엔드 개발자 되기 - 자바편

https://stackoverflow.com/questions/3058/what-is-inversion-of-control/3140#3140

https://velog.io/@virtualplastic/Spring-%EC%A0%9C%EC%96%B4%EC%9D%98-%EC%97%AD%EC%A0%84-IOC-Inversion-of-Control#:~:text=5%2F9-,IOC(Inversion%20of%20Control)%20%EC%A0%9C%EC%96%B4%EC%9D%98%20%EC%97%AD%EC%A0%84,%EB%B3%B8%EC%97%85%EC%97%90%20%EC%A7%91%EC%A4%91%ED%95%A0%20%EC%88%98%20%EC%9E%88%EB%8B%A4.