숏컷 코드
초기 composition root
-> 앱 시작 조립
Runtime composition root
-> 모드/feature 진입 시 재조립
아무 곳에서 resolve
-> root가 사라짐문법과 예시
runtime composition root는 "다시 조립이 필요한 진입 지점"에만 둔다
게임이 시작된 뒤에도 전투 모드 진입, 미니게임 로드, DLC feature 활성화처럼 별도 조립이 필요한 순간이 있습니다. 이때는 해당 진입 지점에서만 runtime composition root를 두고, 그 아래 객체들이 필요한 협력을 한 번에 연결하는 편이 읽기 쉽습니다.
App Root
-> 공통 서비스 조립
BattleEntry
-> 전투 전용 presenter, coordinator, system 조립
ShopEntry
-> 상점 전용 presenter, pricing rule, view adapter 조립root는 새 협력 graph를 만드는 곳이지 서비스 조회 포털이 아니다
runtime composition root의 목적은 새 scope의 협력 graph를 만들고 넘기는 것입니다. 개별 객체가 필요할 때마다 locator처럼 계속 resolve하는 지점으로 쓰면, root가 아니라 전역 의존성 통로가 됩니다.
가장 흔한 실패는 root를 핑계로 lazy resolve를 퍼뜨리는 것이다
BattleEntry에서 한 번 조립하면 충분한데, 실제 구현에서는 presenter와 system이 각자 다시 global container를 뒤지기 시작할 수 있습니다.
이 순간 runtime composition root는 이름만 남고 구조상 이점은 사라집니다.
runtime 조립 지점을 둘 때 핵심
| 상황 | 더 자연스러운 선택 |
|---|---|
| 새 모드나 feature 진입 때 협력 graph가 크게 달라질 때 | runtime composition root |
| 기존 공통 서비스만 재사용하면 충분할 때 | app root 재사용 |
| scope 진입 시 한 번 wiring하면 될 때 | entry root에서 조립 후 전달 |
| 컴포넌트가 실행 중간마다 resolve를 반복할 때 | locator 남용 여부 점검 |
| 새 root가 사실상 전역 service registry가 될 때 | 조립 지점 축소 |
특이 케이스와 주의할 점
흔한 실패는 "런타임이니까 유연해야 한다"는 이유로 resolve 지점을 everywhere로 풀어 버리는 것입니다. 이 방식은 feature 추가가 아니라 숨은 의존성 추가로 이어집니다.
실패 예시
- BattleHUDPresenter가 필요할 때마다 GlobalContainer에서 resolve
- ShopSystem이 실행 중간에 PricingService 구현체를 계속 교체 조회
결과
- root가 구조를 고정하지 못함
- 호출 흐름과 테스트 경계가 흐려짐