[CS]DI : Dependency Injection

김피자·2023년 2월 1일
0

CS

목록 보기
7/22

DI(Dependency Injection)

Dependency

공부를 하다보면 의존성 의존성 굉장히 자주 나옴
근데 "A가 B에 의존한다" 라는 표현은 나한테 굉장히 개솔개솔 추상적인 표현이다.

토비의 스프링에서 의존관계에 대해 정의한 글에는

의존대상 B가 변하면, 그것이 A에 영향을 미친다.

라고 나와있는데 설명하면 B의 기능이 추가 또는 변경되거나 형식이 바뀌면 A에도 영향을 미치는 것을 말한다.

나는 강아지를 안키우지만 아무튼 우리집에 강아지가 있다고 가정했다.
우리집 강아지가 물을 마시는 행위를 객체지향 관점에서 바라보자면

public class Dog{
	private Water water = new Water();
    
    public void drink(){
    	water.isDrink();
    }
}
public class Water{
	private Integer capacity;
    
    public Water(){
    	this.capacity = 500;
    }
    public void isDrunk(){
    	this.capacity -= 1;
    }
}
public static void main(String[] args){
	Dog dog = new Dog();
    dog.drink();
}

Dog 객체에 Water가 없다면, 우리집 강아지는 물을 마시는 행위를 할 수 없을 것이다.
Dog에게는 Water이 필요하다.

이렇게 Dog객체가 drink라는 행위를 하기 위해 Water객체를 Dog객체 내부에 가지고 있는 것을 의존관계, 의존성을 가지고 있다라 한다.

Dog는 Water와 의존관계이고,
Dog는 Water에 대한 의존성을 가진 것이다.

객체지향에서의 객체들은 상호작용하며 어떠한 목표를 달성하는 역할을 한다.
객체들은 또 다른 객체들과 메시지를 주고받으며 그들이 가지고 있는 행위(메소드)를 호출한다.


보통 애플리케이션을 설계할 땐 인터페이스와 구현체들이 굉장히 다양하게 존재많다.

Dog객체 내부에 Milk 인터페이스가 있고, SeoulMilk라는 구현체가 있다면 객체 Dog는 Milk에도 의존하고, SeoulMilk에도 의존하게 된다.

public class Dog{
	private Milk milk = new SeoulMilk();
    
	public void drink(){
    	milk.isDrunk();
    }
}

애플리케이션 전체에서 사용하는 SeoulMilk를 일괄적으로 NamyangMilk로 변경하면 이에 따른 수정은 피할 수 없다.

왜냐하면, Dog객체가 추상화(인터페이스)에만 의존하지 않고, 구체화(구현클래스)에도 의존하기 때문이다.

SOLID원칙 중 OCP와 DIP 위배
OCP : SW요소는 확장에는 열려있고 변경에는 닫혀있어야 한다.
DIP : 추상화에 의존하고 구체화에 의존하면 안된다.


의존관계 주입

위 코드의 SeoulMilk와 NamyangMilk의 의존관계를 프로그래머가 정하지 않고 외부에서 정해준다면 소스의 수정 없이 외부의 도움을 받아 구현 클래스를 변경할 수 있을 것이다.

public class Dog{
	private Milk milk;
    
    public Dog(Milk milk){
    	this.milk = milk;
    }
    
    public void drink(){
    	milk.isDrunk();
    }
}
public static void main(String[] args){
	SeoulMilk seoulMilk = new SeoulMilk();
    
    Dog dog = new Dog(seoulMilk);
    dog.drink();
}

이렇게 하면 다른 객체 혹은 설정 파일에서 의존관계를 외부에서 주입해줄 수 있다.

여기서 우리 강아지가 좋아하는 우유가 SeoulMilk가 아닌 NamyangMilk로 변경이 된다면 Milk에 의존하는 모든 객체들이 소스 수정없이 SeoulMilk에서 NamyangMilk로 변경될 수 있다.

public static void main(String[] args){
	NamyangMilk namyangMilk = new NamyangMilk();
    
    Dog dog = new Dog(namyangMilk);
    dog.drink();
}

의존관계 주입에서 수정하지 않아도 된다는 말은 외부 설정의 수정이 아닌 실제 의존하고 있는 객체 내에서 로직 수정이나 구현 클래스를 갈아 끼우기위한 수정이 필요없다는 말임


DI의 장점

  1. 의존성이 줄어든다.
    의존한다는 것은 말 그 의존대상의 변화에 취약하다는 것이다.
    (대상이 변화하면 이에 맞게 수정이 필요함)
    하지만 DI로 구현하게 된다면, 주입받는 대상이 변하더라도 그 구현 자체를 수정할 일이 없거나 줄어들게 된다.

  2. 재사용성이 높은 코드가 된다.

  3. 테스트하기 좋은 코드가 된다.

  4. 가독성이 높아진다.


출처
https://tecoble.techcourse.co.kr/post/2021-04-27-dependency-injection/
https://velog.io/@cgw981/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9D%98%EC%A1%B4%EA%B4%80%EA%B3%84-%EC%A3%BC%EC%9E%85-%EC%A0%95%EB%A6%AC

profile
제로부터시작하는코딩생활

0개의 댓글