본문 바로가기

스프링

[스프링] DI, IoC, Bean

제어의 역전 IoC(Inversion of Control)

할리우드 원칙

“Don’t call us, we’ll call you” 우리한테 연락하지 마세요. 우리가 연락할께요.

 

IoC를 설명하기위해 할리우드 원칙을 종종 예시로 들곤 한다.

예를들어 한명의 배우가 영화사에 오디션을 본다고 가정할때

  • 배우 ->  채용을 위한 이력서를 영화사에 제출
  • 영화사 -> 구인을 위해 배우들의 이력서를 수집 및, 채용활동
  • 이력서 -> 배우의 희망 역할, 정보

위와같이 크게 세가지로 분류할 수 있다. 여기서 배우는 이력서를 작성 후 영화사에 제출하고, 영화사는 추가적인 로직을 수행하고, 채용할 배우를 선택하게 될것이다.

여기서 추가적인 로직이란, 배우들의 연기활동 검토, 이력서 검토, 배우에게 추가적인 정보요청 등등을 의미한다.

배우들은 이력서를 제출하곤, 영화사가 하는 채용 과정에 참여할 수 없다. 즉, 배우가 합격을 위해 하는 일들이 이력서를 제출한 후부터는 영화사의 의사에 맞춰서 진행이되는 것이다. 

 

이와 같은 일련의 프로세스를 제어의 역전이라 한다. 

개발 친화적인 용어로 설명하자면 IoC란 코드의 흐름을 제어하는 주체가 바뀌는 것이다. 라고 할 수 있다. 코드의 흐름을 제어한다는것은 객체의 생성, 초기화, 소멸 등 객체의 생명주기를 제어하는것을 의미하며, 일반적인 프로그램은 이러한 제어를 스스로 수행한다. 

 

의존성 주입 DI(Dependency Injection)

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

위 A클래스가 있는 코드가 있다고 할때, 만약 B클래스에 final 필드가 추가되면 new B(); 부분에 컴파일 에러가 발생하게 된다. 즉, B의 변경이 A에게까지 영향을 미치게 되는 것이다. 이를 A가 B에 의존한다고 하는데, 이렇게 되면 객체들간의 관계가 아니라 클래스간의 관계가 맺어진다. 의존성 주입을 통해 이러한 클래스간의 결합을 약하게 만들어 줄 수 있다.

 

DI는 외부에서 두객체간의 의존 관계를 결정해주는 디자인 패턴이다.

  • 클래스 모델이나 코드에는 런타임 시점에 의존관계가 들어나지 않는다.
  • 런타임 시점의 의존관계는 컨테이너 같은 제 3자가 결정한다.
  • 의존관계는 사용할 오브젝트에 대한 참조를 외부에서 주입함으로써 만들어진다.

의존성 주입은 주로 세가지 방법으로 가능하다.

 

생성자 주입

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

Setter 주입

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

Interface 주입

public interface BInjection {
    void inject(B b);
}

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

DI의 장점

  • 코드의 재사용성과 유연성이 늘어난다.
  • 클래스간의 결합도가 낮아지므로, 한 클래스를 수정할때 다른 클래스를 수정해야하는 상황을 방지해준다.
  • 유지보수가 쉬우며 테스트가 용이해진다.
  • 확장성이 높다.

DI의 단점

  • 초기 개발의 노력이 많아진다.
  • 주입된 객체들의 추적이 어렵다.