의존성 주입 (DI, Dependency Injection)
- 메인 모듈이 다른 하위 모델에 직접 의존성을 주지 않고, 중간에 의존성 주입자(dependency injector)를 이용해 메인 모듈이 하위 모듈에 간접적으로 의존성을 주입하는 방식
의존성 : (
A → B
) A 가 B에 의존한다 → B의 상태가 변하면 A도 변경되어야 하는 관계1 2 3 4 5 6 7 8 9 10 11 12 13 14
// A -> B 관계의 예 class B { go() { console.log("go 함수 실행") } } class A { go() { new B().go() } } new A().go()
- 위 코드에서 B 클래스의 메서드 이름이 변경되면 A도 수정하여야 한다.
- 유지보수성에 상당한 악영향을 끼친다.
- 메인 모듈과 하위 모듈과의 의존성을 느슨하게 만들 수 있고, 모듈을 쉽게 교체 가능한 구조로 만든다 (유지보수성 증가)
- 의존성을 주입하면 의존관계역전원칙(DIP)이 적용된다.
예시
1
2
3
4
5
6
7
8
9
10
11
// 의존성 주입 전
// 토큰인증을 통해 요청을 보냄
const response = fetch(`${url}`, {
headers: {
Authorization:localStorage.getItem("TOKEN");
}
})
// 로그아웃 시 토큰 삭제
localStorage.removeItem("TOKEN")
- 위 코드의 경우 브라우저가 제공하는
localStorage
에 의존하고 있다. - 만약 로컬스토리지 대신 세션스토리지를 사용한다면 어떻게 될까?
- 지금은 2개지만, localStorage를 사용하는 모든 코드를 sessionStorage로 일일히 수정해주어야 한다.
- 즉 localStroage에 의존하고 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 의존성 주입
/*
TokenStorageInterface
save(token:string):void
get():string
remove():void
**/
class TokenStorage {
KEY = "TOKEN"
save(token) {
localStorage.setItem(KEY, token)
}
get() {
localStorage.getItem(KEY)
}
remove() {
localStorage.removeItem(KEY)
}
}
const tokenStorage = new TokenStorage()
// 토큰인증을 통해 요청을 보냄
const response = fetch(`${url}`, {
headers: {
Authorization: tokenStorage.get();
}
})
// 로그아웃 시 토큰 삭제
tokenStorage.remove();
- 이제 코드에 토큰을 사용하는 코드가 몇개가 있든
TokenStorage
에 있는 localStorage만 수정해주면 사용할 저장소를 교체할 수 있다. - 즉 여기서 TokenStorage가 의존성 주입자 역할을 하는 것이다.
의존관계 역전
- 의존성 관계 비교
- 기존 : API 호출부 → localStorage
- 의존성 주입 : API 호출부 → TokenStorageInterface ← TokenStorage → localStorage
- 위와 같이 의존성 주입 후 특정 시점에서 의존성 흐름이 반대로 뒤집힌 것을 확인할 수 있다. 즉 의존성 주입을 통해 의존관계 역전 원칙(DIP)이 적용된 것이다.
- 이렇게 하면 변경의 여지가 적은 추상적인 요소에만 의존하고, 변경의 여지가 많은 구체적인 요소에 의존하지 않게 되어 유지보수성이 증가한다.
의존관계 역전 원칙
의존성 주입을 할 때 의존관계역전원칙을 지키는 상태여야 한다.
- 상위 모듈은 하위 모듈에 의존해서는 안된다. 둘 다 추상화에 의존해야 한다.
- 추상화는 세부사항에 의존해서는 안 된다. 세부 사항은 추상화에 따라 달라져야 한다.
위의 예시에서 TokenStorageInterface
가 추상화에 해당한다.
의존성 주입의 장점
- 모듈을 쉽게 교체할 수 있는 구조가 된다.
- 단위 테스팅과 마이그레이션이 쉬워진다.
의존성 주입의 단점
- 모듈이 늘어나게 되어 복잡도가 증가한다.
- 종속성 주입이 런타임 때 일어나므로, 종속성 주입에 대한 에러를 잡기가 어려워진다.
This post is licensed under CC BY 4.0 by the author.