[Spring] Spring DI(Dependency Injection)

NHJ·2021년 12월 25일
0

DI(Dependency Injection)이란?

자바와 같은 객체 지향 프로그래밍 언어에서 클래스는 특정 기능을 수행하는 부품 역할을 한다. 우리가 살아가는 현실에서도 어떤 부품을 사용하다가 이상이 있거나 오래되면 다른 부품으로 교체해서 사용한다. 마찬가지로 애플리케이션에서도 사용자의 요구 사항에 따라 클래스 기능을 변경하거나 다른 클래스 기능으로 대체해야 하는 경우가 자주 생긴다. 이러한 상황에서 좀 더 수월하게 대체할 수 있게 도입된 기능이 의존성 주입(DI)이다.

DI외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴으로, 인터페이스를 사이에 둬서 클래스 레벨에서는 의존관계가 고정되지 않도록 하고 런타임 시에 관계를 다이나믹하게 주입하여 유연성을 확보하고 결합도를 낮출 수 있게 해준다.

의존성이란 한 객체가 다른 객체를 사용할 때 의존성이 있다고 한다.

예를 들어 다음과 같이 Store 객체가 Pencil 객체를 사용하고 있는 경우에 우리는 Store객체가 Pencil 객체에 의존성이 있다고 표현한다.

public class Pencil {

}
public class Store { 
	private Pencil pencil; 
    
    	public Store() { 
    		this.pencil = new Pencil(); 
    	} 
}

위의 예시에는 문제가 있다. 두 클래스가 강하게 결합되어 있는것이다. 만약 Store에서 Pencil이 아닌 Food와 같은 다른 상품을 판매하고자 한다면 Store 클래스의 생성자에 변경이 필요하다. 즉, 유연성이 떨어진다. 프로젝트 규모가 점점 커지는 상황에서 자바 코드에서 직접 객체를 생성하는것은 복잡한 문제를 일으킬 수 있다. 다른 클래스의 변경 사항이 연속적으로 다른 부분에 영향을 미친다면 좋은 방법이 아니다.

위와 같은 문제를 해결하기 위해서는 우선 다형성이 필요하다. Pencil, Food 등 여러 가지 제품을 하나로 표현하기 위해서는 Product 라는 Interface가 필요하다. 그리고 Pencil에서 Product 인터페이스를 우선 구현해주도록 한다.

public interface Product {

}
public class Pencil implements Product { 

}
public class Store { 
	private Product product;
    
    	public Store() { 
        	this.product = new Pencil();
       	}
}

인터페이스를 사용해 각 클래스를 구현한 후 각 클래스의 객체를 사용할 때는 인터페이스 타입으로 선언한 참조 변수로 접근해서 사용한다. 그러면 완전하지는 않아도 앞의 경우보다 훨씬 클래스들 간 의존 관계가 약해진다. 그러나 여전히 소스코드를 수정해야 하는 작업이 필요하다.

public class Store { 
	private Product product;
    
    	public Store(Product product) { 
        	this.product = product; 
       	}
}
public class Store { 
	private Product product;
    
    	public void setStore(Product product) { 
        	this.product = product; 
       	}
}

의존 관계를 완전히 분리하기 위해 위와 같이 Store 클래스는 의존하는 Pencil 객체를 전달받기 위해 new 키워드를 사용하지 않고 생성자를 호출할 때 외부에서 객체를 주입 받아 사용하였다. 이처럼 외부에서 두 객체 간의 관계(의존성)를 맺어주는 것을 의존성 주입(DI)이라고 한다. 첫번째 코드는 생성자를 이용한 주입, 두번째 코드는 setter를 이용한 주입이다.

의존성 주입을 적용했을 때 얻을 수 있는 장점들이다.

  • 클래스들간의 의존 관계를 최소화하여 코드를 단순화 할 수 있다.
  • 애플리케이션을 더 쉽게 유지 및 관리할 수 있다.
  • 테스트 작성을 용이하게 한다.

DI는 객체의 생성, 소멸, 의존 관계를 개발자가 직접 설정하는 것이 아니라 XML이나 애너테이션 설정을 통해 Spring Framework가 제어한다. 따라서 개발자가 제어하던 객체를 Spring Framework가 제어하게 되었으므로 제어의 역전(Inversion of Control)이라고 한다.

IoC Container는 오브젝트의 생성과 관계설정, 사용, 제거 등의 작업을 대신 해준다하여 붙여진 이름이다. 이때, IoC Container에 의해 관리되는 오브젝트들을 Bean 이라고 부른다.

IoC ContainerBean을 저장한다고 하여, BeanFactory 라고도 불린다. BeanFactory는 하나의 인터페이스이며, Application ContextBeanFactory의 구현체를 상속받고 있는 인터페이스이다. 실제로 스프링에서 IoC Container 라고 불리는 것은 Application Context의 구현체이다.

의존 관계를 주입할 객체를 계속해서 생성하고 소멸한다면 부담이 된다. 그래서 Spring에서는 Bean들을 기본적으로 싱글톤(Singleton)으로 관리한다.

[참고]

profile
화이팅!

0개의 댓글

관련 채용 정보