Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
레거시 프로젝트에서 의존성 주입하기
Search
Suyeol Jeon
December 05, 2019
Programming
1
2.6k
레거시 프로젝트에서 의존성 주입하기
왜 개념만 알려주고 적용 방법은 아무도 알려주지 않는가
Suyeol Jeon
December 05, 2019
Tweet
Share
More Decks by Suyeol Jeon
See All by Suyeol Jeon
성장하는 iOS 개발자 되기
devxoul
2
250
Let's TDD
devxoul
0
90
Hello, ReactorKit 👋
devxoul
0
98
Build Funnels with Google BigQuery
devxoul
0
51
RxSwift 시작하기
devxoul
1
360
ReactorKit으로 단방향 반응형 앱 만들기
devxoul
0
170
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
devxoul
10
3.2k
좋은 디자이너, 나쁜 프로젝트매니저, 이상한 개발자
devxoul
0
120
Other Decks in Programming
See All in Programming
Denoのセキュリティに関する仕組みの紹介 (toranoana.deno #23)
uki00a
0
220
[AI Engineering Summit Tokyo 2025] LLMは計画業務のゲームチェンジャーか? 最適化業務における活⽤の可能性と限界
terryu16
2
270
それ、本当に安全? ファイルアップロードで見落としがちなセキュリティリスクと対策
penpeen
6
1.9k
Go コードベースの構成と AI コンテキスト定義
andpad
0
160
從冷知識到漏洞,你不懂的 Web,駭客懂 - Huli @ WebConf Taiwan 2025
aszx87410
2
3.3k
まだ間に合う!Claude Code元年をふりかえる
nogu66
5
930
16年目のピクシブ百科事典を支える最新の技術基盤 / The Modern Tech Stack Powering Pixiv Encyclopedia in its 16th Year
ahuglajbclajep
3
600
Vibe codingでおすすめの言語と開発手法
uyuki234
0
160
フロントエンド開発の勘所 -複数事業を経験して見えた判断軸の違い-
heimusu
6
2.1k
メルカリのリーダビリティチームが取り組む、AI時代のスケーラブルな品質文化
cloverrose
2
450
DevFest Android in Korea 2025 - 개발자 커뮤니티를 통해 얻는 가치
wisemuji
0
180
「コードは上から下へ読むのが一番」と思った時に、思い出してほしい話
panda728
PRO
39
26k
Featured
See All Featured
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
420
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
2
78
A Soul's Torment
seathinner
2
2.1k
Ethics towards AI in product and experience design
skipperchong
1
170
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.3k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
65
35k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
62
Context Engineering - Making Every Token Count
addyosmani
9
590
The Language of Interfaces
destraynor
162
26k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
49
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Transcript
ۨѢद ۽ંীࢲ ઓࢿ ੑೞӝ ࣻৌ
ۨѢद ۽ંীࢲ ઓࢿ ੑೞӝ ࣻৌ ࠗઁ: ৵ ѐ֛݅ ঌ۰Ҋ ਊ
ߑߨ ইޖب ঌ۰ ঋחо
పझח য۵
పझח য۵ పझೞӝ જѱ ৈ ঋ
పझח য۵ పझೞӝ જѱ ৈ ঋ Coupling ъೞ
func fetchUser() -> Single<User> { }
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") }
✅ పझ ాҗ func fetchUser() -> Single<User> { return Networking.shared.get("/user/1")
}
✅ పझ ాҗ ⛔ పझ पಁ func fetchUser() -> Single<User>
{ return Networking.shared.get("/user/1") }
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ✅ పझ
ాҗ ⛔ పझ पಁ
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ✅ పझ
ాҗ ⛔ పझ पಁ
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ъೠ ઓ
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ъೠ ઓ
ডೠ ઓ
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ъೠ ઓ
ডೠ ઓ Networking Production
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ъೠ ઓ
ডೠ ઓ Networking NetworkingStub Production Testing
func fetchUser() -> Single<User> { return self.networking.get("/user/1") } ъೠ ઓ
ডೠ ઓ Networking NetworkingStub Production Testing
func fetchUser() -> Single<User> { return self.networking.get("/user/1") } UserService(networking: Networking())
func fetchUser() -> Single<User> { return self.networking.get("/user/1") } UserService(networking: Networking())
UserService(networking: NetworkingStub())
UserService(networking: Networking()) UserService(networking: NetworkingStub())
UserService(networking: Networking()) UserService(networking: NetworkingStub()) ب ফ֎ܳ য٣ࢲ ࢤࢿ೧ਃ?
Composition Root
Composition Root ઓࢿ Ӓېо ٜ݅যח Ҕ
Composition Root ઓࢿ Ӓېо ٜ݅যח Ҕ ۽Ӓ۔ ੑ
Composition Root ઓࢿ Ӓېо ٜ݅যח Ҕ ۽Ӓ۔ ੑ (=AppDelegate)
User Repo List Repo Detail
User Repo List Repo Detail
User Repo List Repo Detail UserService RepoService
User Repo List Repo Detail UserService RepoService Networking Networking
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module Composition
Root ীࢲ ࢤࢿ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module AppDependency
struct AppDependency { let window: UIWindow } CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
} CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
static func resolve() -> AppDependency { } } CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
static func resolve() -> AppDependency { return AppDependency( ) } } CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
static func resolve() -> AppDependency { return AppDependency( window: ... ) } } CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
} CompositionRoot static func resolve() -> AppDependency { return AppDependency( window: ... ) }
let window = UIWindow() return AppDependency( window: window )
let window = UIWindow() window.rootViewController = ... return AppDependency( window:
window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
AppDelegate AppDependency
class AppDelegate { var window: UIWindow? func application( _ application:
UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = UIWindow(...) self.window?.makeKeyAndVisible() return true } }
class AppDelegate { let dependency: AppDependency var window: UIWindow? func
application( _ application: UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = UIWindow(...) self.window?.makeKeyAndVisible() return true } }
class AppDelegate { let dependency: AppDependency var window: UIWindow? private
override init() { } func application( _ application: UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = UIWindow(...) self.window?.makeKeyAndVisible() return true } }
class AppDelegate { let dependency: AppDependency var window: UIWindow? private
override init() { self.dependency = AppDependency.resolve() } func application( _ application: UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = UIWindow(...) self.window?.makeKeyAndVisible() return true } }
class AppDelegate { let dependency: AppDependency var window: UIWindow? private
override init() { self.dependency = AppDependency.resolve() } func application( _ application: UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = self.dependency.window self.window?.makeKeyAndVisible() return true } }
Composition Rootо పझ ജ҃ীࢲ प೯غ ঋب۾
Composition Rootо పझ ജ҃ীࢲ प೯غ ঋب۾ UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, NSStringFromClass(UIApplication.self),
NSStringFromClass(NSClassFromString("MyTests.TestAppDelegate") ?? AppDelegate.self) )
Composition Rootо పझ ജ҃ীࢲ प೯غ ঋب۾ UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, NSStringFromClass(UIApplication.self),
NSStringFromClass(NSClassFromString("MyTests.TestAppDelegate") ?? AppDelegate.self) ) https://github.com/devxoul/Pure
Composition Rootח పझ ജ҃ীࢲ प೯غݶ উػ
Composition Rootח పझ ജ҃ীࢲ प೯غݶ উػ ࢤࢿ ഐ ৻ ٘ח
ઁ
ۿ જ݅ അप ޙઁ
ۿ જ݅ അप ޙઁ ઓࢿ Ӓېী ࣘೞ ޅೠ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
ઓࢿ Ӓېী ࣘೞ ޅೠ
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵?
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵? 1. ੋఠಕझী ઓೠ
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵? 1. ੋఠಕझী ઓೠ UserService.shared.fetchUser()
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵? 1. ੋఠಕझী ઓೠ 2.
ੋझఢझܳ ࢤࢿೠ UserService.shared.fetchUser()
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵? 1. ੋఠಕझী ઓೠ 2.
ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC() UserService.shared.fetchUser()
ೞաঀ ೧Ѿ೧ ࠇद.
Ҿӓ ݾ
Ҿӓ ݾ ݽٚ ېझо ઓࢿ Ӓېী ࣘೞѱ ػ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
Ҿӓ ݾ ݽٚ ېझо ઓࢿ Ӓېী ࣘೞѱ ػ അप ݾ
Ҿӓ ݾ ݽٚ ېझо ઓࢿ Ӓېী ࣘೞѱ ػ അप ݾ
যઁࠁ ؊ ա ٘ܳ ࢿೠ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module যઁ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module য়ט
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+1
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+2
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+3
1. ੋఠಕझী ઓೠ 2. ੋझఢझܳ ࢤࢿೠ let detailVC
= DetailVC() UserService.shared.fetchUser() ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵?
1. ੋఠಕझী ઓೠ UserService.shared.fetchUser()
1. ੋఠಕझী ઓೠ ࢤࢿ۽ ׳߉ח UserService.shared.fetchUser()
1. ੋఠಕझী ઓೠ ࢤࢿ۽ ׳߉ח UserService.shared.fetchUser() init(userService: UserService)
1. ੋఠಕझী ઓೠ ࢤࢿ۽ ׳߉ח UserService.shared.fetchUser() init(userService: UserService) self.userService.fetchUser()
۽షਃ? рചחਃ??
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ যب ৻ࠗীࢲ ੑೡ
ࣻ ѱ غ
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ যب ৻ࠗীࢲ ੑೡ
ࣻ ѱ غ ਃ೧ ٸ ۽షਸ ٜ݅
1.1 ੋఠಕझী बпೞѱ ઓೠ UserService.shared.fetchUser()
1.1 ੋఠಕझী बпೞѱ ઓೠ UserService.shared.fetchUser()
1.1 ੋఠಕझী बпೞѱ ઓೠ UserService.fetchUser()
1.1 ੋఠಕझী बпೞѱ ઓೠ ࢤࢿ۽ ఋੑਸ ׳߉ח UserService.fetchUser()
1.1 ੋఠಕझী बпೞѱ ઓೠ ࢤࢿ۽ ఋੑਸ ׳߉ח UserService.fetchUser() init(userServiceType:
UserService.Type)
1.1 ੋఠಕझী बпೞѱ ઓೠ ࢤࢿ۽ ఋੑਸ ׳߉ח UserService.fetchUser() init(userServiceType:
UserService.Type) self.userServiceType.fetchUser()
2. ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC()
2. ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC() ࢤࢿ۽ ಂషܻܳ
׳߉ח
2. ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC() ࢤࢿ۽ ಂషܻܳ
׳߉ח init(detailVCFactory: () -> DetailVC)
2. ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC() ࢤࢿ۽ ಂషܻܳ
׳߉ח init(detailVCFactory: () -> DetailVC) let detailVC = self.detailVCFactory()
ࠂೠ ۽о դޖೞ ঋਸөਃ??
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ যب ৻ࠗীࢲ ੑೡ
ࣻ ѱ غ
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ যب ৻ࠗীࢲ ੑೡ
ࣻ ѱ غ ࠂ೧ݶ Factory ఋੑਸ ೞ
ف ೧Ѿ ߑߨ ҕా
ف ೧Ѿ ߑߨ ҕా ઓࢿ ৻ࠗী ਤೠ. init(userService: UserService) init(detailVCFactory:
() -> DetailVC)
ف ೧Ѿ ߑߨ ҕా ઓࢿ ৻ࠗী ਤೠ. ਃী ٮۄ ਗೞח
ѐܳ ੑೡ ࣻ . ListVC(detailVCFactory: { DetailVCMock() }) UserVC(userService: UserServiceMock())
ઁ ઓࢿ Ӓېী ࣘೞѱ ٜ݅
ઁ ઓࢿ Ӓېী ࣘೞѱ ٜ݅ Rootীࢲ оө ࣽࢲ۽
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module য়ט
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+1
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+2
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+3
window.rootViewController = ListVC( ) য়ט
window.rootViewController = ListVC( userService: UserService( ) ) ղੌ
window.rootViewController = ListVC( userService: UserService( networking: networking ) ) ղੌ+1
window.rootViewController = ListVC( userService: UserService( networking: networking ), detailVCFactory: {
DetailVC( ) } ) ղੌ+2
window.rootViewController = ListVC( userService: UserService( networking: networking ), detailVCFactory: {
DetailVC( repoService: RepoService( ) ) } ) ղੌ+3
window.rootViewController = ListVC( userService: UserService( networking: networking ), detailVCFactory: {
DetailVC( repoService: RepoService( networking: networking ) ) } ) ղੌ+4
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
పझ ജ҃ীࢲ AppDelegateо प೯ظਃ DetailVCী ۄఠܳ ֈӝҊ रযਃ ಂషܻ ۽о
ցޖ ࠂ೧ઉਃ
Pure https://github.com/devxoul/Pure