0. 글을 작성하는 이유
- 클린아키텍처 책을 읽다가.. DIP가 궁금해서
- DI, DIP 대해 정의만이라도 정확히 알고 싶어서
TL;DR
- Case1
- User 객체는 MySQLDAL 의존하고 있다.
- 문제 : MySQLDAL이 바뀌면, 의존하고 있는 User도 수정해야 된다
- Case2
- Case1 해결 : 해당 의존 관계를 외부로 부터 주입받아 Case1 문제를 해결할 수 있다.
- 문제: DB가 바뀌었다면(MySQL → Oracle 변경) User가 수정되어야 한다.
- Case3
- 해결: Interface 주입함으로써, DB가 어떤 종류 인지 알 필요가 없다(결합도 ↓)
1. 의존성이란?
- 두 모듈(컴포넌트) 관계(객체지향에서는 두 클래스 간의 관계)
- 둘 중 하나가 다른 하나를 어떤 용도를 위해 사용함
1) 기본적인 소스코드 의존성 및 제어흐름
- 전형적인 호출 트리의 경우 main 함수가 고수준 함수 호출
- 고수준 함수 → 중간함수 → 저수준 함수 호출
- 소스 코드 의존성의 방향은 반드시 제어 흐름을 따르게 된다.
Source code dependencies vs flow of control — Martin, Robert C. 2017. Clean Architecture — A Craftsman’s Guide to Software Structure and Design. Prentice Hall. Ch. 5. Figure 5.1.
2. 의존성 문제
-
User는 MySQLDAL 의존하고 있는 상태
-
MySQLDAL 변경된다면, 의존하고 있는 User도 수정해야 되는 문제!!
class MySqlDal {} class User { protected $dal constructor() { this.$dal = new MySqlDal() } }
1) DI - 의존성 주입
-
외부로 부터 의존성을 주입받아 의존성 문제를 해결 할 수 있다.
-
단, 해당 User는 Mysql에 의존되고 있는 상황... 만약 DB가 Oracle로 변경된다면?
class MySqlDal {} class User { protected $dal constructor(MySqlDal: MySqlDal) { this.$dal = MySqlDal } }
2) DIP - 의존성 역전
-
인터페이스 주입을 통해 User는 Oracle, MySql인지 알 필요가 없어졌다.(결합도 ↓)
-
인터페이스를 기준으로 기능 구현을 강제하기 때문, 어떤 DB든지 상관없다.
interface DBConnnect { connect: () => void } class MySql implements DBConnnect { connect() { console.log('connet') } } class Oracle implements DBConnnect { connect() { console.log('connet') } } class User { protected $dal constructor(dal: DBConnnect) { this.$dal = dal } }
-