[기본] 의존성 주입의 필요성
이전 포스팅을 통해 자바는 객체지향 언어이며, 자바를 통한 개발시 객체지향의 장점을 최대한 살려야한다고 언급했다.
객체지향의 특성 중 다형성으로 인해 부모의 참조변수로 자식 인스턴스를 참조할 수 있다.
위와 같은 상속관계에서
Parent parent = new Child1(); 로 생성할 수 있으며. Child1 인스턴스를 Parent 형 변수로 사용할 수 있다는 뜻이다.
이 다형성으로 인한 유연성을 어떻게 활용할 수 있을까?
다형성 활용
위와 같은 상황을 가정해보자. 할인 정책은 아직 미정이거나, 변화가 발생할 수 있는 영역이며 그럼에도 불구하고 우리는 주문관련 개발을 진행해야만 하는 상황이다.
주문에는 할인율 정보가 들어가므로 우리는 주문에서 할인정책 객체를 생성하여 멤버메서드로 할인율을 받아와야 한다.
public class OrderServiceImpl() {
FixDiscountPolicy fixDiscountPolicy = new FixDiscountPolicy();
public Order createOrder(int id, int price) {
int discount = fixDiscountPolicy.getDiscount();
int finalPrice = price - discount;
return new Order(id, finalPrice);
}
}
여기서 문제가 생긴다. 할인정책이 가변적인데 할인 정책이 변하면 우리는 Service에서
- 할인정책 객체 생성부분
- Service의 모든 메서드들에서 할인정책 참조변수
- 모든 할인정책 멤버 메서드 사용 부분
위의 세가지 부분을 모두 바꿔야한다. 너무 많은 수정이 필요하다.
여기에 다형성을 도입하자. 인터페이스로 할인정책의 공통 메서드들을 선언하고 구현체로 구현하며. Service에서는 부모 인터페이스 참조변수를 사용하는 것이다.
public class OrderServiceImpl() {
DisCountPolicy discountPolicy = new FixDiscountPolicy();
public Order createOrder(int id, int price) {
int discount = discountPolicy.getDiscount();
int finalPrice = price - discount;
return new Order(id, finalPrice);
}
}
다형성 도입 후 할인정책이 변경되면 2, 3번은 변경할 필요가 없어진다. 참조변수는 부모 인터페이스형으로 동일하며, 메서드 이름도 모두 동일함이 보장되기 때문이다. 단 메서드의 구현이 바뀌었기에 1번인 할인정책 객체 생성부분, 즉
DisCountPolicy discountPolicy = new RateDiscountPolicy(); 로
변경하면 된다.
다형성의 한계
다형성을 적용하여, 가변적인 영역을 인터페이스와 구현체의 설계로 분리하였다. 이를 통해 가변 객체를 생성 및 사용하는 클래스들은 변경시 객체 생성 부분만 변경하면 된다. 하지만 그 작은 수정도 확장에는 열려있고 수정에는 닫혀있어야 하는 OCP와, 사용 클래스는 구현체가 아닌 인터페이스에만 의존해야하는 DIP의 원칙을 위반하게된다.
의존성 주입
위와 같은 상황을 가정하자.
불을 지피기 위해 버너를 쓰려한다. 버너는 가스만 나오기에 점화장치가 필요하다.
말도 안되지만 버너가 인공지능 버너라 직접 점화장치를 생성해서 사용한다고 해보자. 이 때 점화장치를 변경하고 싶다면, 버너가 다른 점화 장치를 생성하기 위해 인공지능을 수정하여야 할 것이다. 즉 버너가 직접 점화장치를 생성하는게 문제인 것이다.
버너 교체센터를 따로 두면 어떨까?
버너센터는 점화장치도 생성하고. 점화장치를 탑재한 버너도 생성한다.
점화장치가 변경되면 버너 속의 점화장치도 함께 변경된다.
사람은 버너센터에서 변경된 버너를 가져다 쓰면 될 것이다.
즉 객체를 생성하며 다른 객체에 주입하는 클래스를 별도로 두자는 것이다
public class 버너센터 {
public 점화장치() {
//return new 부싯돌();
return new 라이터();
}
public 버너() {
return new 버너(점화장치());
}
}
여기서 점화장치가 부싯돌에서 라이터로 변경되면, 점화장치 생성부분만 변경하면된다.
버너속의 점화장치는 자동으로 함께 변경된다.
이전 인공지능 버너는 직접 자신이 점화장치를 선택하여 생성하여 사용한 반면. 현재 버너는 점화장치가 부싯돌인지 라이터인지는 알 수 없고, 단순 점화장치를 사용하기만 한다.
이와 같이 사용클래스는 도구클래스 참조변수만 멤버변수로 가진 뒤 기능을 사용만하고.
어떤 도구구현체를 사용할지는 사용객체를 생성하는 클래스가 주입해주는 것을 의존성 주입(DI) 이라고 한다.
이를 통해 도구클래스가 바뀌어도 사용클래스의 인터페이스 참조변수는 수정이 필요없으며, 객체지향의 OCP와 DIP 원칙이 실현된다.
본 글은 김영한님의 "스프링 핵심 원리 - 기본편" 강의내용 및 이해한 내용을 정리한 것입니다.
Author And Source
이 문제에 관하여([기본] 의존성 주입의 필요성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kiwonkim/Spring기본의존성-주입의-필요성저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)