[Spring/SpringBoot] 의존 관계 주입 DI(Dependency Injection)

2024. 12. 15. 23:06CS/Spring

 

의존 관계 주입 

  • 애플리케이션 실행 시점(런타임)에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달해서 클라이언트와 서버의 실제 의존관계가 연결되는 것을 의존관계 주입이라고 함
    • 객체 인스턴스를 생성하고, 그 참조값을 전달해서 연결함
  • 의존 관계 주입의 장점
    1. 클라이언트 코드를 변경하지 않고, 클라이언트가 호출하는 대상의 타입 인스턴스를 변경할 수 있음
    2. 정적인 클래스 의존관계를 변경하지 않고, 동적인 객체 인스턴스 의존관계를 쉽게 변경할 수 있음
    • (ex) AppConfig의 의존관계 인스턴스 이름나 변경해주면됨 다른 코드/클래스 건드릴 필요 없음

의존 관계 주입 예시 코드

**import hello.core.discount.DiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;**

@Component
public class OrderServiceImpl implements OrderService{

    //DIP 위반 -> 인터페이스 뿐만 아니라, 구현에도 의존하고 있다.
		//private final MemberRepository memberRepository= new MemoryMemberRepository();
		//private final DiscountPolicy discountPolicy= new FixDiscountPolicy();
		//private final DiscountPolicy discountPolicy = new RateDiscountPolicy();

    //해결책 -> 인터페이스에만 의존하도록 의존관계 변경
   private final MemberRepository memberRepository;
   **private final DiscountPolicy discountPolicy;**

    @Autowired
		//생성자를 통해서 의존관계 주입
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy){
        this.memberRepository = memberRepository;
        this.discountPolicy = rateDiscountPolicy;
    }
public class AppConfig{
	public MemberService memberService(){
		return new MemberServiceImpl(memberRepository());
	}
	
	public OrderService orderService(){
		return new OrderServiceImpl(memberRepository(), discountPolicy());
	}
}
  • public interface DiscountPolicy { int discount(Member member, int price); }
  • OrderServiceImpl은 DiscountPolicy인터페이스에 의존함 → 실제 어떤 구현 객체가 사용될지는 모름
  • 의존 관계는 정적인 클래스 의존 관계와, 실행 시점에 결정되는 동적인 객체(인스턴스) 의존 관계 둘을 분리해서 생각해야함

정적인 클래스 의존관계

  • 클래스가 사용하는 import 코드만 보고 쉽게 의존관계 판단 가능 → 애플리케이션을 실행하지 않아도 분석 가능
  • but, 이러한 클래스 의존관계 만으로는 실제 어떤 객체가 OrderServiceImpl에 주입될지 알 수 없음
//OrderServiceImpl의 import문 일부
import hello.core.discount.DiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;

동적인 객체 인스턴스 의존 관계

//AppConfig의 코드 일부
	public DiscountPolicy discountPolicy(){
		return new RateDiscountPolicy();
	}

 

@Component
public class RateDiscountPolicy implements DiscountPolicy{
    private int discountPercent = 10;
    @Override
    public int discount(Member member, int price) {
        if(member.getGrade()== Grade.VIP){
            return price * discountPercent/100;
        }else{
            return 0;
        }
    }
}
  • 애플리케이션 실행 시점에 실제 생성된 객체 인스턴스의 참조가 연결된 의존관계
  • OrderServiceImpl에 주입될 구현 객체는 DiscountPolicy 인터페이스를 구현한 RateDiscountPolicy가 될 것