IoC와 DI란

rvlwldev·2023년 4월 4일
0

Spring

목록 보기
3/8

IoC와 DI란

IoC는 메소드나 객체의 호출작업을 개발자가 결정하는 것이 아니라,
외부에서 결정되는 디자인패턴을 말하는데 이 객체에 대한 제어권을 스프링 컨테이너가 가지고 있기때문에 제어의 역전이라고 불린다.

대표적 예시 중 하나로 스프링부트에서 @SpringBootApplication 어노테이션이 보통 프로젝트 메인 클래스에 정의되어 있다.
이 어노테이션이 스프링 컨테이너를 생성하고 컴포넌트 스캔을 수행하여 빈 객체를 찾아 의존성을 자동으로 주입한다.

주로 @Component, @Service, @Repository, @Controller 등의 어노테이션이 붙은 클래스들이 빈으로 등록될 대상이 되며
@ComponentScan 어노테이션으로 basePackages, basePackageClasses, includeFilters, excludeFilters 등의 옵션으로 Spring Container의 빈 객체 관리에 대해 세밀하게 지정할 수 있다.

개발자가 직접 객체 간의 의존성을 생성하고 관리하면 추후 코드의 가독성과 유지보수성을 떨어뜨리는 문제 등이 발생할 수 있어 고안된 방법이며 코드의 가독성과 유지보수성을 높일 수 있다.

IoC의 구현 방식 중 하나인 DI(Dependency Injection)은 IoC를 구현하는 방법 중 하나이다.
IoC가 제어의 역전 개념을 통틀어 말한다면 DI는 이 개념을 구현하기 위해 의존관계를 외부에서 주입(Injection)하는 방식이다.


어떻게 DI는 객체끼리 결합도를 낮추는가

일단 결합도가 낮다는 의미는 객체끼리의 영향을 끼치는 정도로 말할 수 있다.

이전글과 비슷한 예시로

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

이 코드는 A가 B를 직접 생성하기에 객체끼리 결합도가 높다고 볼 수 있다.
B의 생성자에서 파라미터가 추가된다면? , A의 코드도 수정되어야 할 것이다.

// 예시2)

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

A에 생성자나 Setter로 외부에서 생성된 B를 받는다면?
A는 수정될 필요가 없다.

이런 방법은 결합도를 낮춰 재사용성을 높여 유연하게 만들 뿐만 아니라
코드도 간결해지고 모의객체를 활용해 테스트도 불편함 없이 수행할 수 있다.

왜 DI만 쓰는가

IoC를 구현하는 방법에는 여러가지가 있었는데 DI 방식보다 비효율적이라서 사장된듯 하다.

Service Locator Pattern

객체를 생성하기 위해 InitialContext 클래스로 객체를 확인하고 생성하는 방식
객체끼리의 결합도는 낮출수는 있으나 테스트에 어려움이 있꼬 코드가 길어진다.

InitialContext 클래스는 javax.naming 패키지에 위치해 있으며
패키지와 클래스 이름으로 프로젝트 내에서 해당 클래스를 찾아볼 수 있는 클래스이다.

Service Provider Framework Pattern

Provider (제공자) 클래스를 따로 구현하여 이 제공자 클래스로 객체를 요청하고 제공자 클래스가 객체를 반환해주는 방식이다.

이 경우 객체를 제공해주는 클래스 자체가 인터페이스와 구현객체들에게 의존하고 있어서 결합도를 높이는 방식으로 동작할 수 밖에 없으며 소스코드 또한 길어지게 된다.

간단한 프로그램에선 적용시키기 어렵고 적용시키더라도 불필요한 과정이 추가되며
북잡한 프로그램에선 성능에 악역향을 끼칠 수 있다.

0개의 댓글