위키 설명 https://ko.wikipedia.org/wiki/%EC%9D%98%EC%A1%B4%EC%84%B1_%EC%A3%BC%EC%9E%85
그림 설명 https://thebook.io/006746/part01/ch02/03/
질문 글 https://okky.kr/article/362415
좋은 글 https://medium.com/@jang.wangsu/di-dependency-injection-%EC%9D%B4%EB%9E%80-1b12fdefec4f
함수를 빈껍데기 도구로 만들기.
유지한다 : 인수를 이렇게 처리하여 결과값을 반환한다 (처리의 아이디어)
배제한다 : 결과값이 이렇게도 되고 저렇게도 될 수 있는 환경은 바깥으로 빼둔다 (처리의 간섭)
예시
"검색엔진에서 입력한 검색결과를 반환하겠다"
입력한 검색결과를 반환하겠다 : 아이디어. 이것만 내버려둠
검색엔진 : 바깥에 뺌, 안에서 선언하지 않고 인수로 받아들임.
의존성 주입 구현 전
function getSearchResult (keyword) {
searchEngine = new SearchEngine();
result = searchEngine.search(keyword)
return result;
}
의존성 주입 구현 후
function getSearchResult (searchEngine, keyword) {
result = searchEngine.search(keyword)
return result;
}
"종이를 검은색으로 색칠하겠다"
검은색으로 칠한다 : 이것만 함수로 만든다.
종이 : 바깥으로 뺀다.
"손님의 주문에 따른 정산 결과를 출력한다"
주문 : 바깥에서 인수로 받는다
가격 조회 유틸리티 : 바깥에서 인수로 받는다
가격 조회 유틸리티를 써서 주문에 따른 계산 결과를 반환 : 함수 안에서는 이 아이디어만을 구현한다
왜냐? 뭐가 좋은가?
외부 변인의 통제가 가능하다 : 테스트 코드 작성이 수월해짐, 리팩터링도 쉬워진다.
읽기 좋아짐, 편해짐 : 사용 목적만 알 수 있고 함수의 독립성이 뛰어나짐
재활용이 가능해진다
위의 예시를 생각해보자.
"검색엔진에서 입력한 검색결과를 반환하겠다" 이러면 의존성 주입 구현 이전에는 다음과 같은 과정을 거친다.
그에 따라, 우측과 같은 에러나 난해함이 발생할 가능성이 있다.
1. 함수 안에서 검색엔진을 선언한다 : 검색엔진이 정의되어 있지 않거나 선언할 수 없으면 에러 발생하기에, 단순 테스트나 구현에서 항상 검색엔진을 포함해야 한다. 즉, 검색 결과를 반환하는 함수를 만들기 위해서는 검색엔진 구현이 전제되어야 한다,
2. 그 검색엔진 내부의 검색 기능을 사용한다 : 결과값의 형태가 다양하거나 예측할 수 없어 테스트가 난해해진다
3. 검색 결과를 반환한다.
하지만 의존성 주입을 구현한다면?
1. 외부에서 검색엔진을 받는다 그게 뭐든지
2. 그 검색엔진에 검색 기능이 있다면 사용한다.
3. 검색 결과를 반환한다.
가 되는데, 이는 기실 크게 달라보이지 않으나, 테스팅을 할 때, A를 받으면 무조건 B를 반환하는 검색이라는 기능이 있는, 검색엔진이라는 이름의 간단한 클래스 구현을 해서 집어넣으면 되기 때문에, 검색엔진 자체의 완전성이나 에러 존재는 무관한 함수를 검색 엔진 구현 이전에 작성할 수 있다.
"종이를 검은색으로 색칠하겠다"
의존성 구현 전 : 종이를 내부에서 선언하고, 그 배경 속성을 검은색으로 전환하고, 그 결과를 반환한다.
의존성 구현 후 : 종이든 상자든 나뭇잎이든 밖에서 받는걸 검은색으로 칠하고 돌려보낸다.
즉, 종이의 구현 여부나 완전성과 관계 없이 완전히 독립적인 색칠 전용 변수를 구현하여, 나중에 사용할 수 있으며, 또한 함수가 일목요연해지기 때문에 에러 발생도 현저히 줄일 수 있다.
대충 이렇다.
틀렸으면 지적 바랍니다. 이해가 안되면 보충 설명을 요구해도 좋습니다.
왜냐면 그것이 제게 공부가 되기 때문입니다.