[Spring] IoC / DI 컨테이너

LDB·2025년 1월 18일
0

Spring

목록 보기
2/6
post-thumbnail

작성계기

나는 Spring Boot를 주로 사용하면서 IoC 컨테이너와 DI 컨테이너에 대해 정리하지 않았다는 사실을 알았는데 IoC와 DI는 스프링계열 프레임워크에서는 정말 중요한 내용이기에 이번에 정리를 해보고자 작성하게 되었다.

IoC 란?

IoC는 제어반전이라는 의미로 객체의 생성, 생명주기 관리까지 모든 객체에 대한 제어권이 바뀌었다는 것을 의미한다.

컴포넌트 의존관계 설정, 설정(Configuration), 생명주기(LifeCycle)을 해결하기 위한 디자인 패턴이다.

IoC 컨테이너

컨테이너 : 컨테이너는 보통 객체의 생명주기를 관리하고 생성된 인스턴스들에게 추가적인 기능을 제공하도록 하는 것

그렇다면 IOC 컨테이너는 직역하자면 제어반전 컨테이너 그러니까 개발자가 아닌 프레임워크에 존재하는 컨테이너가 객체의 생성관리 및 의존성을 관리한다는 의미이다.

여기서 Spring의 장점중에 하나가 나오는데 앞에서 설명한 IoC 컨테이너가 객체를 관리해주기 때문에 개발자는 로직에 집중할 수 있다는 장점이 나온다. 또한 객체생성 코드가 없기 때문에 TDD가 용이하다는 장점도 따라온다.

IoC 컨테이너의 방식은 둘로 나누어지는데 DL(Dependency Lookup)DI(Dependency Injection) 방식으로 나뉜다.

(스프링에서는 DL과 DI를 사용할 수는 있지만 DL을 사용하면 컨테이너 종속이 증가하기에 주로 DI를 사용한다.)


DI (Dependency Injection)

DI는 일명 의존성 주입이라고 말하는데 간단히 이야기하면 우리가 흔히 쓰는 Controller와 Service의 관계라고 할 수 있다.

@Controller
public class mainController {
    private final MainService mainService;
    
    public mainController(MainService mainService){
    	this.mainService = mainService;
    }
}

위와 같이 mainController에 필요한 MainService를 즉 의존 받는 객체를 주입하는 것을 의존성 주입이라고 한다.

이렇게하면 다음과 같은 이점을 얻을 수 있다.

  • 객체간의 결합도가 낮아진다.
  • 객체의 유연성이 증가한다.
  • 테스트 작성이 용이해진다.

의존성 주입에는 여러가지 방법이 있는데 그 중에서 생성자 주입방식을 사용했다, 그 외의 방법들은 별도로 작성할 계획이다.

DI 컨테이너

그렇다면 DI 컨테이너는 (의존성 주입 + 컨테이너) 개념이기에 외부에서 객체를 생성하고 관리하면서 의존관계를 연결해주는 기능을 가지고 있다.

DI 컨테이너 개념은 Spring 뿐만 아니라 다른 프레임워크에도 존재하는 개념이다. 나도 처음 듣는 프레임워크인데 구아바(Guava), 오토팩(Autofac)등의 프레임워크에도 존재하는 개념이다.

DI 컨테이너는 앞에서 말한 DI(Dependency Injection)의 장점에 추가로 장점이 있다.

  • 객체간의 결합도가 낮아진다.
  • 객체의 유연성이 증가한다.
  • 테스트 작성이 용이해진다.
  • 가독성과 유지보수성이 증가한다. (의존성을 주입하는 코드가 명확하기 때문이다.)
  • 메모리 누수를 방지할 수 있다. (객체의 생명주기를 관리해주기 때문에 불필요한 메모리가 남지 않는다.)

하지만 DI 컨테이너에도 단점은 존재한다.

  • DI 컨테이너는 런타임 시점에 의존성을 주입하기 때문에 의존성 오류를 발견하기가 어렵다.
  • 만약 DI 컨테이너를 직접적으로 사용하면 많은 코드와 설정이 필요하기 때문에 초기 설정이 복잡하다.

스프링 IoC/DI 컨테이너

(스프링에서는 IoC 컨테이너와 DI 컨테이너를 하나로 묶어 IoC/DI 컨테이너라고 부른다.)

스프링에서 IoC/DI 컨테이너는 애플리케이션의 객체를 생성하고(IoC), 이들 간의 의존성(DI)을 관리한다, 이 과정에서 생성된 객체를 (Bean) 이라고 하며 이 객체는 생성부터 소멸까지 컨테이너가 담당한다.

참고로 Spring Boot에서 Bean을 등록하기 위해서 Component-Scan 이라는 기술을 사용하는데 @Component, @Bean 어노테이션이 붙은 클래스 혹은 메서드로 Bean객체를 등록한다.


Bean객체의 생명주기

  1. 스프링 IoC 컨테이너 생성
  2. 스프링 Bean 생성
  3. 의존관계 주입
  4. 초기화 콜백 메서드 호출
  5. 객체 사용
  6. 소멸전 콜백 메서드 호출
  7. 스프링 종료

스프링은 의존관계 주입이 완료되면 스프링 Bean에게 콜백 메소드를 통해 초기화 시점을 알려주고 IoC/DI 컨테이너가 종료되기 직전에 소멸 콜백 메서드를 통해 소멸 시점을 알려준다.


참고 사이트

https://dev-coco.tistory.com/80

https://pamyferret.tistory.com/33

https://mangkyu.tistory.com/150

https://velog.io/@wogud7587/Spring-1-DI-컨테이너를-사용하는-이유

https://f-lab.kr/insight/dependency-injection-and-di-container-20240802

(항상 감사합니다.)

profile
가끔은 정신줄 놓고 멍 때리는 것도 필요하다.

0개의 댓글

관련 채용 정보