본문 바로가기
백수/java

22. 스프링 DI에 대해 아는 대로 말씀해 주세요.

728x90
반응형

22. 스프링 DI에 대해 아는 대로 말씀해 주세요

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

장점

  • 객체 간의 결합도, 의존성이 줄어듭니다.
    • DI로 의존 관계를 분리하게 되면 주입받는 대상이 수정되어도 그 구현을 수정할 필요가 없어지므로 줄어듭니다.
  • 코드의 재활용성이 높아집니다.
  • Unit Test가 용이해집니다.
    • DI로 구현하면 A의 테이스트를 B 테스트와 분리하여 진행할 수 있게 됩니다.
  • 가독성이 높아집니다.

 

주입 방법

  1. 생성자 주입
@Controller
public class Controller{
	private Service service;

	@Autowired
	public Controller(Service service){
		this.service = service;
	}

}

 

생성자에 @Autowired를 붙여 의존성을 주입받을 수 있습니다.

Spring 4.3 이후로는 클래스 내 생성자가 하나이고 그 생성자로 주입받을 객체가 빈으로 등록되어 있다면 @Autowired 생략 가능 합니다.

인스턴스 생성 시 1회 호출되는 것이 보장되기 때문에 주입받은 객체가 변하지 않거나 반드시 객체 주입이 필요한 경우 강제하기 위해 사용됩니다.

 

  1. 필드 주입
@Controller
public class Controller{
	@Autowired
	private Service service;
}

코드가 간결하고 편하지만 의존관계를 정확히 파악하기 힘듭니다.

필드 주입 시 final 키워드를 선언할 수 없어 객체가 변할 수 있습니다.

주입이 동시에 일어나는 겹치는 경우 순환참조 에러가 발생됩니다.

 

  1. 수정자 주입
@Controller
public class Controller{
	private Service service;

	@Autowired
	public setService(Service service){
		this.service = service;
	}

}

 

setter 혹은 사용자정의 메서드를 통해 의존관계를 주입시킵니다.

setter의 경우 객체가 변경될 필요성이 있을 때만 사용됩니다.

 

스프링 권장 방식

생성자 주입 방식을 권장

  1. 객체의 불변성
    1. 객체가 생성되는 시점에 생성자를 호출하여 최초 1회만 주입합니다.
    2. 이와 같은 특성으로 불변 객체를 보장합니다.
    3. 객체를 포함한 클래스가 생성되는 시점에 포함된 객체들도 반드시 생성되기 때문에 객체가 비어있을 가능성도 배제합니다.
  2. 순환 참조 문제 방지 가능
    1. A, B 두 객체가 각각 서로를 필드에 포함하여 참조하고 있는 상태를 말합니다.
    2. 서로가 서로를 참조하고 있기 때문에 A,B 두 클래스가 맞물려서 서로의 객체를 계속 생성하는 무한반복 상태에 빠지는 문제가 발생됩니다.
    3. 3가지 방식 모두 순환 참조 문제가 발생되지만 발생 시점이 다릅니다.
      • 필드 주입, 수정자 주입은 실제 메서드가 호출되었을 때 runtime 에러나 함께 수정자 주입 문제가 불거지게 됩니다.
      • runtime에 에러가 발생하게 되면 미리 예측이 어렵기 때문에 서비스 진행 중에 문제를 야기할 수 있습니다.
      • 생성자 주입은 스프링 애플리케이션이 구동되는 순간에 에러가 발생됩니다.
      • 컴파일 타임에 발생하는 에러는 개발자가 쉽게 추적이 가능하여 서비스 진행 전 미리 예방이 가능합니다.
  3. 테스트 용이
    • 단위 테스트 진행 시 순수 자바 코드로 테스트가 가능합니다.
    • 필드 주입을 사용하는 경우에 순수 자바 코드에서는 DI가 이루어지지 않기 때문에 필드가 null 상태가 되어 에러가 발생됩니다.
728x90
반응형