본문 바로가기
CS/디자인패턴

[CS] 의존성주입(DI, Dependency Injection)과 의존관계역전원칙(DIP, Dependency Inversion Principle)

by Johnny's 2023. 9. 3.

 

의존성주입(DI, Dependency Injection)과 의존관계역전원칙(DIP, Dependency Inversion Principle) 

의존성주입(DI, Dependency Injection)

의존성주입(DI, Dependency Injection)이란 메인 모듈(main mudule)이 ‘직접’ 다른 하위 모듈에 대한 의존성을 주기보다는 중간에 의존성 주입자(dependency injector)가 이 부분을 가로채 메인 모듈이 ‘간접’적으로 의존성을 주입하는 방식

 

이를 통해 메인 모듈과 하위 모듈간의 의존성을 조금 더 느슨하게 만들 수 있으며 모듈을 쉽게 교체 가능한 구조로 만듬

 

'의존한다' 라는 의미

A가 B에 의존한다. == B가 변하면 A에 영향을 미치는 관계 == A → B 를 의미 (B가 변경이 되면, A도 변경이 되어야 함)

코드로는 이러한 것을 A가 B에 의존한다고 함

 

import java.util.*;

class B { // B 코드가 수정이되면 A 코드도 수정이 되어야 함
  public void go() {
    System.out.println("B의 go()함수");
  }
}

class A {
  public void go() {
    new B().go(); // 클래스 B의 go 함수를 호출
  }
}

public class main {
  public static void main(String args[]) {
    new A().go();
  }
}
// B의 go()함수

 

프로젝트의 DI를 적용하지 않은 사례

프로젝트라는 클래스를 만든다고 가정

 

 

프론트엔드 개발자, 백엔드 개발자가 필요하고 이를 다음과 같은 코드로 구현

 

클래스 총 3개

1. BackendDeveloper

2. FrontEndDeveloper

3. Project

 

BackendDeveloper와 FrontEndDeveloper의 함수가 변경이되면 Project 에서 호출하는 메서드도 변경을 해줘야함

즉, Project는 BackendDeveloper와 FrontEndDeveloper에 의존함

 

import java.util.*;

class BackendDeveloper {
  public void writeJava() {
    System.out.println("자바가 좋아 인터네셔널~");
  }
}

class FrontEndDeveloper {
  public void writeJavascript() {
    System.out.println("자바스크립트가 좋아 인터네셔널~");
  }
}

public class Project {

  private final BackendDeveloper backendDeveloper;
  private final FrontEndDeveloper frontEndDeveloper;

  public Project(
    BackendDeveloper backendDeveloper,
    FrontEndDeveloper frontEndDeveloper
  ) {
    this.backendDeveloper = backendDeveloper;
    this.frontEndDeveloper = frontEndDeveloper;
  }

  public void implement() { //각각의 다른 함수들(메서드) 호출
    backendDeveloper.writeJava();
    frontEndDeveloper.writeJavascript();
  }

  public static void main(String args[]) {
    Project a = new Project(new BackendDeveloper(), new FrontEndDeveloper()); //프로젝트 정의
    a.implement(); //실행
  }
}

 

프로젝트의 DI를 적용한 사례 (DI 적용)

여러명의 개발자를 추가할 수도 있으며 또 프론트엔드 개발자 말고 안드로이드 개발자 등으로 교체도 쉽게 할 수 있는 구조임을 보여줌. 또한 의존적인 화살표가 “역전"된 것을 볼 수 있음
DI를 하게 되면 의존관계역전원칙(Dependency Inversion Principle)이 적용되는 것

 

 

FrontendDeveloper의 writeJavascript() 함수를 변경하면, develop() 의 writeJavascript()만 수정해주면 됨

별도로 Project 클래스의 메서드를 수정할 필요 없음

 

import java.util.*;

interface Developer {
  void develop();
}

class BackendDeveloper implements Developer { //Developer로부터 파생

  @Override
  public void develop() {
    writeJava();
  }

  public void writeJava() {
    System.out.println("자바가 좋아~ 새삥새삥");
  }
}

class FrontendDeveloper implements Developer { //Developer로부터 파생

  @Override
  public void develop() {
    writeJavascript(); //2. develop()만 수정하면 됨
  }

  public void writeJavascript() { // 1. 수정을 하게 되더라도
    System.out.println("자바스크립트가 좋아~ 새삥새삥");
  }
}

public class Project {

  private final List<Developer> developers;

  public Project(List<Developer> developers) {
    this.developers = developers;
  }

  public void implement() {
    developers.forEach(Developer::develop); //Developer - develop
  }

  public static void main(String args[]) {
    List<Developer> dev = new ArrayList<>();
    dev.add(new BackendDeveloper());
    dev.add(new FrontendDeveloper());
    Project a = new Project(dev);
    a.implement();
  }
}

 

의존관계역전원칙(DIP, Dependency Inversion Principle)

의존성 주입을 할 때는 의존관계역전원칙(DIP, Dependency Inversion Principle)이 적용

이는 2가지의 규칙을 지키는 상태
- 상위 모듈은 하위 모듈에 의존해서는 안되고, 둘다 추상화에 의존해야 함
- 추상화는 세부사항에 의존해서는 안되고, 세부 사항은 추상화에 따라 달라져야 함

 

의존성 주입의 장점

1. 외부에서 모듈을 생성하여 dev.add(new BackendDeveloper()) 이런식으로 집어넣는 구조가 되기 때문에 모듈들을 쉽게 교체할 수 있는 구조가 됨
2. 단위 테스팅마이그레이션이 쉬워짐
3. 애플리케이션 의존성 방향이 좀 더 일관되어 코드를 추론하기가 쉬워짐


마이그레이션 : 다른 운영 환경으로 이동하는 것(DB이동, 데이터 이동 등)

 

의존성 주입의 단점

1. 결국에는 모듈이 더 생기게 되므로 복잡도가 증가
2. 종속성 주입 자체가 컴파일을 할때가 아닌 런타임 때 일어나기 때문에 컴파일을 할 때 종속성 주입에 관한 에러를 잡기가 어려워질 수 있음

 

* 참고

- CS 지식의 정석 | 디자인패턴 네트워크 운영체제 데이터베이스 자료구조 -인프런

 

'CS > 디자인패턴' 카테고리의 다른 글

[CS] 옵저버 패턴  (0) 2023.09.06
[CS] 전략 패턴  (0) 2023.09.05
[CS] 이터레이터 패턴  (0) 2023.09.02
[CS] 팩토리 패턴  (0) 2023.09.01
[CS] 싱글톤 패턴을 구현하는 7가지 방법  (0) 2023.08.31

댓글