본문 바로가기
DEV/Spring

[Spring] IoC/DI 란?

by 어쩌다개발 2023. 3. 7.
반응형

IoC(Inversion Of Control, 제어의 역전)는 간단히 프로그램의 제어 흐름 구조가 뒤바뀌는 것이라고 할 수 있다.

즉, 모든 종류의 작업을 사용하는 쪽에서 제어하는 구조를 거꾸로 뒤집는 것이다.

오브젝트가 자신이 사용 할 오브젝트를 스스로 선택하지도 생성하지도 않으며, 자신도 어떻게 만들어지고 어디서 사용되는지를 알 수 없다.
모든 제어 권한을 자신이 아닌 다른 대상에게 위임하기 때문이다.

제어권을 상위 템플릿 메소드에 넘기고 자신은 필요할 때 호출되어 사용되도록 한다는 개념이다.

IoC가 적용된 대표적인 기술은 프레임워크이다.
참고로, 프레임워크는 내가 작성한 코드를 제어하고 대신 실행한다.
만약 내가 작성한 코드가 직접 제어의 흐름을 담당한다면 그건 라이브러리이다.

스프링 프레임워크를 예로 들면 Controller, Service 같은 객체들의 동작을 우리가 직접 구현하기는 하지만, 해당 객체들이 어느 시점에 호출될 지는 개발자가 제어하지 않는다.
스프링 프레임워크가 요구하는대로 객체를 생성하면, 프레임워크가 해당 객체들을 가져다 생성하고 호출하고 소멸시킨다.

이러한 과정을 개발자의 제어권이 역전되었다고 볼 수 있다.

IoC를 통해 프레임워크가 라이브러리의 차이점을 알 수 있는데 위에 작성했듯이 라이브러리는 제어를 직접 담당한다.
개발자가 필요한 시점에 라이브러리에서 제공되는 기능들을 필요한 시점에 가져다 사용하여 직접 제어하기 때문이다.

IoC의 장점

- 객체 간 낮은 결합도
- 유연한 코드 작성 가능
- 가독성 증가
-코드 중복 방지
- 유지 보수 용이

Ioc를 적용하면, 객체를 클래스 내부에서 직접 생성하여 사용하지 않고 미리 생성해놓은 객체를 주입받아 사용하면 된다.
(프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리)


 DI에 대한 설명을 하기 전에 한가지 짚고 넘어갈 점이 있다.

바로 위에서 사용한 IoC라는 용어인데, IoC가 매우 느슨하게 정의돼서 폭 넓게 사용되는 용어라는 점이다.
때문에 스프링을 IoC 컨테이너라고 하기엔 스프링이 제공하는 기능의 특징을 명확하게 설명하지 못 한다.

스프링이 서블릿 컨테이너처럼 서버에서 동작하는 서비스 컨테이너라는 뜻인지, 아니면 단순히 IoC 개념이 적용된 템플릿 메서드 패턴을 이용해 만들어진 프레임워크인지, 아니면 또 다른 IoC 특징을 지닌 기술이라는 것인지 파악하기 힘들다.

그래서 몇몇 사람의 제안으로 스프링이 제공하는 IoC 방식의 핵심을 짚어주는 의존관계 주입이라는 좀 더 의도가 명확히 드러나는 이름을 사용하기 시작했다.

그래서 초기에는 주로 IoC 컨테이너라고 불리던 스프링이 지금은 의존관계 주입 컨테이너 또는 DI 컨테이너라고 더 많이 불리고 있다.

DI(Dependency Injection, 의존 관계 주입/의존성 주입)는 객체를 직접 생성하는 것이 아니라 외부에서 생성한 후 주입 시켜주는 방법이다.

의존성이란 무엇일까?

의존대상 B가 변하면, 그것이 A에 영향을 미친다는 뜻이다. B의 기능이 추가되거나 변경되면 그 영향이 A로 전달된다는 것이다.

의존성 주입에는 세가지 방식이 있다.

생성자 주입(Constructor Injection) - 권장

public class A {
    private B b;
    
    public A(B b) {
        this.b = b;
    }
}

Setter 주입(Setter Injection)

public class A {
    private B b;
    
    public void setB(B b) {
        this.b = b;
    }
}

인터페이스 주입(Interface Injection)

public interface B {
    test(B b);
}

public A implements B {
    private B b;
    
    @Override
    public void test(B b) {
        this.b = b;
    }
}

DI 장점

- 불변성을 활용할 수 있다 - final로 선언 가능
- NullPointerException의 발생을 막는다. - 객체가 생성되는 시점에 빈을 주입한다. 생성시에 의존성 없이 생성 불가능하기 때문에 일부러 null을 넣지 않는 한 NullPointerException이 발생하지 않는다.
- 재사용성이 높아진다.

참고:
https://isoomni.tistory.com/entry/TISPRING-IOC-DI-정의-장점
https://velog.io/@ohzzi/Spring-DIIoC-IoC-DI-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0

토비의스프링 3.1
https://inf.run/1hh8

 

반응형

댓글