์๋ ํ์ธ์.
์ค๋์ ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ์ ์ฉํ๋ ํด๋ฆฐ ์ํคํ ์ฒ์ ๋ํด์ ํ๊ณ ํด ๋ณด๋ ์๊ฐ์ ๊ฐ์ ธ๋ณด๋ ค๊ณ ํฉ๋๋ค.
ํด๋ฆฐ ์ํคํ ์ฒ์ ๋ํด์๋ ๋ง์ ๋ธ๋ก๊ทธ ํฌ์คํ ์ด ์กด์ฌํ๊ณ ์์ด์ ํด๋ฆฐ ์ํคํ ์ฒ์ ๊ตฌ์กฐ๋ ์ด๋ค์ง, ์ ์ฌ์ฉํ๋์ง, ๋๊ฐ ํด๋น ์ํคํ ์ฒ๋ฅผ ์๊ฐํ๋์ง ๋ฑ๋ฑ ์๊ธฐ ์ฌ์ธ ๊ฑฐ๋ผ๊ณ ์๊ฐํฉ๋๋ค.
ํด๋น ํฌ์คํ ์๋ ๊ทธ์ ๊ด๋ จ๋ ๋ด์ฉ๋ณด๋ค๋ ํ๊ธฐ ์์ฃผ๋ ์ฐธ๊ณ ๋ถํ๋๋ฆฝ๋๋ค.
ํด๋ฆฐ ์ํคํ ์ฒ?
์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ํ๊ธฐ์ ์์์
iOS ๊ฐ๋ฐ์ ๋ด๋นํ๋ ์ธ์์ด ์ ํ๋์๊ธฐ ๋๋ฌธ์ ์ด๋ค ์์ผ๋ก ์ค๊ณ๋ฅผ ํด์ผ ํ ์ง ๊ณ ๋ฏผ์ด ๋ง์์ต๋๋ค.
๊ธฐ์กด์๋ ๊ฐ๋จํ ์ฑ๋ค์ MVVM ๋์์ธ ํจํด์ ์ฌ์ฉํด์ ๊ตฌํํด์์ง๋ง
๊ท๋ชจ๊ฐ ๊ธฐ์กด๋ณด๋ค๋ ์ปค์ก๊ธฐ ๋๋ฌธ์ ๋์์ธ ํจํด์ด ์๋ ์ํคํ ์ฒ๊ฐ ํ์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ฐ์ฅ ๋๋ฆฌ ์๋ ค์ง๊ธฐ๋ ํ๊ณ , ๋ง์ ์ฌ๋๋ค์ด ์ฌ์ฉํ๊ณ ์๋ ํด๋ฆฐ ์ํคํ ์ฒ๋ฅผ ์ ํํ๊ฒ ๋์๋๋ฐ
์๋ฌด๋๋
๊ฐ ์ ์ง๋ณด์ ์ธก๋ฉด์์ ํฐ ์ฅ์ ์ด ์๋๊ฒ์ด ์ ํ์ ์ฃผ๋ ์ด์ ์์ต๋๋ค.
์ฆ, ํผ์ ๊ฐ๋ฐํ๋ค๋ ์ ๋ ์์ง๋ง ์ด๊ธฐ ์ปจ์ ์ด๋ ์๊ตฌ๋๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์๋ค๋ ์ ์ ๊ฐ์ํด์
๊ฐ์ฅ ์ ํฉํ ์ํคํ ์ฒ๊ฐ ๋ ๊ฑฐ๋ผ๊ณ ์๊ฐํ์ต๋๋ค.
์ด๊ฑฐ ํ๋๋ฉด ์๋ฉด ํด๋ฆฐ ์ํคํ ์ฒ ๋ค ์๋๊ฑธ์ง๋?
ํด๋ฆฐ ์ํคํ ์ฒ์ ๋ํด์ ๊ณต๋ถํ๋ฉด์
๊ฐ์ฅ ๋์์ด ๋์๋ ๊ฒ์ ์๋์ ์ด๋ฏธ์ง์์ต๋๋ค.
ํด๋ฆฐ ์ํคํ ์ฒ๋ฅผ ๊ณต๋ถํ๋ค ๋ณด๋ฉด์ ๋ง์ ์๋ค๊ณผ ๋ง์ฃผํ๊ฒ ๋๋๋ฐ
๊ทธ ์๋ง์ ์๋ค๋ ์ดํด์ ๋์์ ์ฃผ์ง๋ง
์ ๋ ์ด ๋ค๋ชจ๋ค๋ชจ๋ค์ด ์ดํดํ๊ธฐ์๋ ๋ ์์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
UI layer์ Presenter layer๊ฐ ๋ถ๋ฆฌ๋์ด ์๋๋ฐ ์ด๋ ๊ธฐ์กด์ Present layer๋ฅผ ์ธ๋ถํํด์ ๋ฃ์ด ๋๋ค๊ณ ์๊ฐํ๋ฉด ํธํ ๊ฒ ๊ฐ์ต๋๋ค.
์ตํ ์๊ณ ์๋ฏ์ด View์ ๊ฒฝ์ฐ, ViewModel์ ์์กด์ฑ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ViewModel์ ๊ฒฝ์ฐ, ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๋นํ๋ Domain layer์ Use Case์ ์์กด์ฑ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ViewModel์ Use Case์ ๋ทฐ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๊ณ ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํด View์ Binding ๋๋ ๊ฒ์ ๋๋ค. ์์ ์ด๋ฏธ์ง์์ ๋ณด์ด๋ Data flow๋ ์ด ๋ด์ฉ์ ๋งํฉ๋๋ค.
๋ฐ๋๋ฐฉํฅ์์ ์์ํด ๋ณธ๋ค๋ฉด Data layer์ Repository๋ค์ API๋ DB๋ฅผ ํตํด์(์์ฒญ) ๋ฐ์์จ ๋ฐ์ดํฐ๋ค์ Use Case์์ ์กฐํฉํ์ฌ ViewModel์ ์ ๋ฌํ๊ฒ ๋ฉ๋๋ค.
์ฌ๊ธฐ์ Use Case๊ฐ Repository์ ์์กด์ฑ์ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ด ์๋๊ฐ ํ๋ ์๋ฌธ์ด ์๊ฒผ์์ต๋๋ค.
Use Case๋ repository๋ฅผ ๊ฐ์ง๊ณ ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๊ณ ๋ฐ์์ค๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์๋ฌธ์ด ์๊ฒผ๋๋ฐ ์์ ์ด๋ฏธ์ง์ฒ๋ผ DIP(Dependency Inversion Principple)์ด ์ ์ฉ๋๊ธฐ ๋๋ฌธ์ ์์กด์ฑ์ด ์ญ์ ๋ฉ๋๋ค.
๊ฐ๋จํ ์์๋ฅผ ๋ค์ด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
class Person {
let car = Tesla()
init() {
}
}
class Tesla {
}
class Hyundai {
}
์์ ๊ฐ์ด Person๋ Tesla์ ์์กดํ๊ณ ์๊ฒ ๋ฉ๋๋ค. ์ฆ, Tesla ์ธ์คํด์ค๋ฅผ Person์์ ์ง์ ์์ฑํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
protocol Vehicle {
func start()
}
class Person {
let car: Vehicle
init(car: Vehicle) {
self.car = car
}
func start() {
car.start()
}
}
class Tesla: Vehicle {
func start() {
}
}
class Hyundai: Vehicle {
func start() {
}
}
์์ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด ์์กด์ฑ์ ์ธ๋ถ๋ก๋ถํฐ ์ ๋ฌ๋ฐ์ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ ํ๋กํ ์ฝ์ ์ด์ฉํด car์ ๊ตฌํ์ฒด์ธ Tesla๋ Hyundai๊ฐ ์๋ Vehicle ํ๋กํ ์ฝ ํ์ ์ ์ฃผ์ ์ํจ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด๋ ๊ฒ ๋๋ฉด DIP ์์น์ ๋ฐ๋ผ ์ถ์ํ๋ ๊ฒ์ด ๊ตฌ์ฒด์ ์ธ ๊ฒ์ ์์กดํ์ง ์๊ณ ๋ฐ๋์ธ ๊ตฌ์ฒด์ ์ธ ๊ฒ์ด ์ถ์ํ๋ ๊ฒ์ ์์กดํ ์ ์๊ฒ ๋์ด ์์กด์ฑ ์ญ์ ์ด ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค. ์ฆ, ๊ตฌ์ฒด์ ์ธ ํด๋์ค(Tesla, Hyundai)์์ ์์กด๊ด๊ณ๊ฐ ์๋ ํ๋กํ ์ฝ(Vehicle)๊ณผ ๊ด๊ณ๋ฅผ ๋งบ์์ผ๋ก์จ ๋์จํ ๊ฒฐํฉ์ด ๋ง๋ค์ด์ง๊ฒ ๋๊ณ ํด๋ฆฐ ์ํคํ ์ฒ์ ํน์ฑ์ธ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ๋ฅผ ์งํฌ ์ ์๊ฒ ๋ฉ๋๋ค.
ํด๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๋ณด์
๋ง์ ์์ํ๋ ค๊ณ ํ๋ ๋ญ๋ถํฐ ํด์ผ ํ ์ง ๋ชจ๋ฅด๊ฒ ์ด์
๊ฐ์ฅ ๋จผ์ Github์ ๋ค์ด๊ฐ ์ข์ ๋ ํฌ๋ค์ ํ์ํด ๋ดค์์ต๋๋ค.
ํ๊ฐ๊ฐ ์ข์ ๋ ํฌ๋ค ์ค์์ ์๋์ ๋ ํฌ๊ฐ ๊ฐ์ฅ ์ ๋ช ํ๊ธฐ๋ ํด์ ํด๋น ํ๋ก์ ํธ๋ฅผ ์์ธํ๊ฒ ๋ค์ฌ๋ค๋ดค์์ต๋๋ค.
ํด๋น ๋ ํฌ๋ฅผ ๋ณด๋ฉด์ ์ ์ฒด์ ์ธ ํด๋ฆฐ ์ํคํ ์ฒ์ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๊ฐ๋๋ฐ ์ ๋ง ๋ง์ ๋์์ด ๋์๋ ๊ฒ ๊ฐ์ต๋๋ค.
GitHub - kudoleh/iOS-Clean-Architecture-MVVM: Template iOS app using Clean Architecture and MVVM. Includes DIContainer, FlowCoor
Template iOS app using Clean Architecture and MVVM. Includes DIContainer, FlowCoordinator, DTO, Response Caching and one of the views in SwiftUI - GitHub - kudoleh/iOS-Clean-Architecture-MVVM: Tem...
github.com
์ผ๋จ,
์ฒ์์๋ Kudoleh๋๊ณผ ๋น์ทํ ํด๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด ๋๊ณ ์์ํ์์ต๋๋ค.
ํฌ๊ฒ 5๊ฐ์ ํด๋๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ๋๋ฐ ์๋์ ๊ฐ์ต๋๋ค.
Application: plist ํ์ผ์ด๋ ํ๊ฒฝ๋ณ์์ ๊ฐ์ ํ์ผ์ ๋ณด๊ดํด์ ์ฌ์ฉํ์๋๋ฐ Kudoleh๋์ ์์กด์ฑ ๊ด๋ จ ํ์ผ์ด๋, ์ฑ์ ์ ์ฒด์ ์ธ Appearance ๋ฑ Base๊ฐ ๋๋ ํ์ผ๋ค์ ์ด๊ณณ์ ๋๊ณ ์ฌ์ฉํ์์ต๋๋ค. ์ถํ์ Swinject์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋์ ํ๊ฒ ๋๋ค๋ฉด ๊ทธ์ ๊ด๋ จ๋ ํ์ผ์ ์ถ๊ฐํด๋ด์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค.
Domain: ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๋นํ๋ Use Case๊ฐ ๋ค์ด์๋ ํด๋์ ๋๋ค. ์ถ๊ฐ์ ์ผ๋ก Repository Interface์ entities๋ค์ด ์ด๊ณณ์ ๊ฐ์ด ์์ต๋๋ค. Repository Interface๊ฐ ์ด ํด๋์ ์๋ ์ด์ ๋ ํด๋ฆฐ ์ํคํ ์ฒ์ ๊ตฌ์กฐ์ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ์ ์ข ์์ฑ ๋๋ฌธ์ ๋๋ค. ๋๋ฉ์ธ ๊ณ์ธต์ ๊ฒฝ์ฐ, ์ธ๋ถ ๊ณ์ธต(Data layer, Present layer)์ ์์กดํด์๋ ์๋๊ธฐ ๋๋ฌธ์ ์ธํฐํ์ด์ค๋ฅผ ์ด๊ณณ์ ๋ฐฐ์นํจ์ผ๋ก์จ ์ค์ ๋ก ๋ฐ์ดํฐ ์์ค ๊ตฌํ์ ์์กดํ์ง ์๊ณ ์ ์ํจ์ผ๋ก์จ ํด๋น ์์ฑ์ ์ค์ํ ์ ์๊ฒ ๋ฉ๋๋ค.
Presentation: ์ด๋ฆ ๊ทธ๋๋ก View์ ๊ด๋ จ๋ ์ฆ, ํ๋ฉด์ ๋ณด์ด๋ ๊ฒ๋ค์ ๋ฃ์ ํด๋์ ๋๋ค. ViewModel์ ๊ฒฝ์ฐ์๋ Presentation layer์ ํฌํจ๋๊ธฐ ๋๋ฌธ์ ํด๋น ํด๋์ ๋ฐฐ์นํ์ต๋๋ค.
Data: Network์ ๊ด๋ จ๋ ํ์ผ ๊ทธ๋ฆฌ๊ณ Repository๋ค์ด ๋ค์ด์๋ ํด๋์ ๋๋ค. ํ์ฌ ํ๋ก์ ํธ์์๋ CoreData๋ realm๊ฐ ๊ฐ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง๋ ์ฌ์ฉํ์ง ์๊ณ API๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ์ฌ์ฉํด ํด๋น ํ์ผ๋ค์ด ๋ฐฐ์น๋์ด ์์ต๋๋ค.
Infrastructure: Network์ Base ํ์ผ๋ค์ด ๋ค์ด์์ต๋๋ค. ์ ์ ๊ฒฝ์ฐ, Moya ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋๋ฐ Target ํ์ผ๋ค๊ณผ Moya plugin๋ค, Moya intercepter, APIError ๋ฑ์ ์ ์ํ ํ์ผ์ ๋ฐฐ์นํ์ต๋๋ค.
์ฒ์์๋ ์ด๋ค ๊ฒ ์ด๋์ ๋ค์ด๊ฐ์ผ ํ ์ง ํก์ค์์ค ๋ง์ด ํ์ง๋ง
์ธ์ ๊ฐ๋ถํฐ๋ ์์ฐ์ค๋ฝ๊ฒ ํ์ผ๋ค์ ๋ฐฐ์นํ ์ ์๊ฒ ๋์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์๊ฐ์ด ๋๋ฉด ์ ์ฒด์ ์ผ๋ก ๋ค์ ํ๋ฒ ์ ๋ฆฌํด ๋ณผ ํ์๋ ์์ ๊ฒ ๊ฐ๋ค์.
์์ง ํ๋ก์ ํธ๋ ๋๋์ง ์์์ง๋ง..
๊ตฌ์กฐ๋ ์ก๊ณ ์ค์ ๋ก ์ฌ์ฉํ๋ฉด์ ๋๊ผ๋ ์ฅ์ ์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ์ง๋ณด์์ ์ฉ์ด์ฑ์ด์์ต๋๋ค.
์ด๋ ํ ๊ธฐ๋ฅ์ด๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์ถ๊ฐ๋๋๋ผ๋
๊ฐํธํ๊ฒ ๊ตฌํํ ์ ์์๋ ๊ฒ ๊ฐ์ฅ ํฐ ์ด์ ์ด ์๋์๋ ์๊ฐ์ด ๋๋ค์.
์๋ฅผ ๋ค์ด์
๋น์ฆ๋์ค ๋ก์ง์ด ์ถ๊ฐ๋๋ค๋ฉด ํด๋น ๋น์ฆ๋์ค ๋ก์ง์ ์๊ตฌํ๋ ViewModel์ Use Case๋ฅผ ํ์ ํ๊ณ
Repository Interface์ ํด๋น ์๊ตฌ์ฌํญ์ ์์ฑํ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ Repository์ ์๊ตฌ์ฌํญ์ ๊ตฌํํ๊ณ ์ด๋ฅผ Use Case์
์ ViewModel์ ์ ๋ฌํ๊ณ , ์ด๋ฅผ View์ ๋ฐ์ธ๋ฉํ๋ฉด ๋์์ต๋๋ค.
๋ค์ ์๊ฐํด ๋ณด๋ฉด ๊ฐ ๊ณ์ธต์, ํด๋์ค์ ์ญํ ์ด ํ์คํ๊ธฐ ๋๋ฌธ์
์์ ์ ์งํํ ๋์ ์์ด์ ์ค์ค๋ก๋ ๋ช ํํ๊ฒ ๊ตฌํํ ์ ์์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ค๋์ ๋๋ต์ ์ธ Clean Architecture ํ๊ธฐ๋ฅผ ๋จ๊ฒจ๋ดค์ต๋๋ค.
๊ทธ๋ผ ์ด๋ง ๐๐ป ๐๐ป
'iOS > ์ํคํ ์ฒ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์ํคํ ์ฒ] ReactorKit์ ๋ํด์(feat.Flux) (0) | 2023.09.23 |
---|