[iOS] ๋ฉ์ดํธ๋ฌ๋: MVVM + Clean Architecture + RxSwift ๋์ ๊ธฐ
๐ก ์์ง ๋ฐฐ์ฐ๋ ๋จ๊ณ์ ์๋ iOS ๊ฐ๋ฐ์๊ฐ ์์ฑํ ๊ธ์ ๋๋ค! ํ๋ฆฐ ๋ด์ฉ์ด๋ ๋ ์๋ ค์ฃผ๊ณ ์ถ์ ๋ด์ฉ์ด ์๋ค๋ฉด ์๋ ค์ฃผ์ธ์..!
๊ฐ๋จํ ํ๋ก์ ํธ ์๊ฐ
์๋ ํ์ธ์! ์ด๋ฒ ํฌ์คํธ๋ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ MVVM๊ณผ ํด๋ฆฐ ์ํคํ ์ฒ์ RxSwift๋ฅผ ๋์ ํ ๊ฒฝํ์ ๊ณต์ ํ๋ ํฌ์คํธ์ ๋๋ค..! ์ ํฌ ํ์์ ์งํํ ํ๋ก์ ํธ๋ Mate Runner๋ผ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ๋์ดํค ๋ฐ ํด๋ฝ๊ณผ ์ ์ฌํ์ง๋ง ๋ค๋ฅธ ์ฌ์ฉ์์ ํจ๊ป ์ค์๊ฐ์ผ๋ก ๋ชฉํ ๊ฑฐ๋ฆฌ๋ฅผ ๋ฌ๋ฆด ์ ์๋ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์ด์์ต๋๋ค.
๋ ์์ธํ ์๊ฐ์ ํ๋ก์ ํธ ์งํ ํํฉ์ https://github.com/boostcampwm-2021/iOS06-MateRunner ์์ ํ์ธํด๋ณผ ์ ์์ด์!
MVVM
MVVM์ iOS ๊ฐ๋ฐ์ ํ๋ค๋ฉด ์ต์ํ ๊ตฌ์กฐ์ผ ํ ๋ฐ์, View, ViewModel, Model๋ก ์ญํ ์ ๋ถ๋ฆฌํ๋ ๊ตฌ์กฐ์ ๋๋ค. ๊ธฐ์กด MVC๊ตฌ์กฐ๋ Controller์์, ํนํ iOS์์๋ ๋ทฐ ์ปจํธ๋กค๋ฌ์์ ๋๋ฌด ๋ง์ ์ผ์ ํ๋ค ๋ณด๋ ์ญํ ์ด ๊ณผ์ค๋๊ณ , ๋จ์ํ ๋ก์ง์ ํ ์คํธํ๊ธฐ ์ํด์ UIkit์ ์ถ๊ฐํด์ผ ํ๋ค๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
MVVM์ ๋์ ํ๋ฉด ์๋์ ๊ฐ์ด ์ฑ์ ๊ตฌ์กฐ๋ฅผ ๋๋ ์ ์์ต๋๋ค.
๊ฐ ์์ญ๋ค๊ณผ ์ญํ ์ ์ ๋ฆฌํด๋ณด๋ฉด,
1. ๋ทฐ์ ๋ทฐ ์ปจํธ๋กค๋ฌ: ์ ๋ง ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ์ญํ ์ ๋ด๋นํฉ๋๋ค.
2. ๋ทฐ ๋ชจ๋ธ: ํ๋ฉด์์ ํ์ํ ์ ๋ณด๋ฅผ ๋ง๋ค๊ธฐ ์ํ ๋ก์ง์ ์คํํ๊ณ ๋ชจ๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์ญํ ์ ๋ด๋นํฉ๋๋ค.
3. ๋ชจ๋ธ: ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค.
์ฐ๋ฆฌ ์ฑ์์๋?
๋ฉ์ดํธ ๋ฌ๋์์๋ ์๋์ ๊ฐ์ด ํ์ฌ ๋ฌ๋ฆฌ๊ธฐ์ ๋ํ ์ ๋ณด๋ฅผ ํ๋ฉด์ ํ์ํด์ค๋๋ค.
์ด ํ๋ฉด์ ๋ํด์ ์ฑ ๊ตฌ์กฐ๋ฅผ MVVM์ผ๋ก ๋๋๋ฉด ์๋์ฒ๋ผ ๋๋ ์ ์์ต๋๋ค.
๋ทฐ ๋ชจ๋ธ์ ํ์ด๋จธ๋ฅผ ์์ํ๊ฑฐ๋, ์๋ก์ด ์นผ๋ก๋ฆฌ ์ ๋ณด๋ฅผ ๊ฐฑ์ ํ๊ณ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐฑ์ ํ๋ ๋น์ฆ๋์ค ๋ก์ง์ ํฌํจํ๊ณ , ๋ชจ๋ธ์ ๋ฐ์ดํฐ๊ฐ ํ๋ฉด์ ๋ณด์ผ ์ ์๋๋ก ํํ๋ฅผ ๋ณํํ๋ ์ญํ ์ ์ํํฉ๋๋ค.
์๋ฅผ ๋ค์ด์ ๊ฒฝ๊ณผ์๊ฐ์ ๋ทฐ ๋ชจ๋ธ์์ ํ์ด๋จธ๋ฅผ ์์ํ ๋ค, ์ด๋จ์๋ก ๋ชจ๋ธ์ ๊ณ์ ์ ์ฅํ๊ณ ํ๋ฉด์ ๋ณด์ผ ๋๋ hh:mm:ss ํฌ๋งท์ ๋ฌธ์์ด๋ก ๋ณํํ ๋ค์ ๋ทฐ ์ปจํธ๋กค๋ฌ์๊ฒ ๋ฌธ์์ด์ ๋๊ฒจ์ฃผ๋ฉด ๋ทฐ ์ปจํธ๋กค๋ฌ๋ ๋ฐ์ ๋ฌธ์์ด์ ํ์ํ๊ธฐ๋ง ํฉ๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ๋ทฐ๋ ์ ๋ง ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ๋ฐ์๋ง ์ง์คํ ์ ์๊ณ , ๋ทฐ ๋ชจ๋ธ์ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ๋ชจ๋ธ์ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํ๋ฉด์ ์ค์ ๋ก ์ฑ์ ์คํํ์ง ์๊ณ ๋ ๋ทฐ์ ์ด๋ค ๋ฐ์ดํฐ๊ฐ ์ ๋ฌ๋์ด ๊ทธ๋ ค์ง์ง ๋ทฐ ๋ชจ๋ธ๋ง ๋ฐ๋ก ํ ์คํธ๋ฅผ ํ ์ ์์ต๋๋ค.
๋ถ๋ฆฌ๋ ๋์ง๋ง ์ฌ์ ํ ๋ณต์กํด..
MVVM ๊ตฌ์กฐ๋ฅผ ํตํด์ ๋ทฐ์ ๋ก์ง์ ๋ถ๋ฆฌํด๋ผ ์ ์์์ง๋ง, ๋ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋๋ฐ์, ์ฑ์ด ์ ์ ๋ณต์กํด์ง๊ธฐ ์์ํ๋ฉด์ ๋ทฐ ๋ชจ๋ธ์ด ๋๋ฌด ๋ง์ ์ผ์ ํ๊ฒ ๋๋ค๋ ๊ฒ์ ๋๋ค.
์ค์ ๋ก ์ ํ๋ฉด์์ ์นผ๋ก๋ฆฌ๋ฅผ ๊ณ์ฐํ๋ ค๋ฉด Core Motion์ด๋ผ๋ ๋ค์ดํฐ๋ธ ํ๋ ์์ํฌ๋ฅผ ํตํด ์ฌ์ฉ์์ ์์ง์ ์ ๋ณด๋ฅผ ์์์ผ ํ๊ณ , Core Location ๋ค์ดํฐ๋ธ ํ๋ ์์ํฌ๋ฅผ ํตํด ์์น ์ ๋ณด๋ ์์๋ด์ผ ํฉ๋๋ค. ๋๊ตฐ๋ค๋ ์น๊ตฌ์ ์ค์๊ฐ ํต์ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋๋ค๋ฉด ๋คํธ์ํฌ ์์ฒญ๊ณผ ์ฒ๋ฆฌ๊น์ง ๋ทฐ ๋ชจ๋ธ์์ ๋ชจ๋ ์ํํ๊ฒ ๋ฉ๋๋ค.
์ด๋ ๊ฒ์.. ๋ฒ์จ ์์ฒญ ๋ณต์กํด ๋ณด์ด์ฃ ..? ๊ทธ๋์ ๋ทฐ ๋ชจ๋ธ์ ๋ถ๋ด์ ์ค์ฌ์ฃผ๊ธฐ ์ํด์ ํด๋ฆฐ ์ํคํ ์ฒ๋ฅผ ๋์ ํ๊ฒ ๋์์ต๋๋ค.
ํด๋ฆฐ ์ํคํ ์ฒ
์ ํฌ ํ์์๋ ์ด๋ฒ ํ๋ก์ ํธ์ ํด๋ฆฐ ์ํคํ ์ฒ๋ฅผ ์ ์ฉํ๊ธฐ๋ก ํ๋๋ฐ์, ํด๋ฆฐ ์ํคํ ์ฒ๋ฅผ ๋จผ์ ๊ฐ๋จํ๊ฒ ์ค๋ช ํ ๊ฒ์.
์ ํฌ ํ์ ์ ๋ ํฌ์์ ์๊ฐํ๋ iOS ํด๋ฆฐ ์ํคํ ์ฒ์ ๋ถ์คํธ์บ ํ ๋ง์คํฐ์ด์ JK๋์๊ฒ ํ๋ จ๋ฐ์ JK-iOS-Clean-Architecture๋ฅผ ๊ธฐ์ค์ผ๋ก ์ํคํ ์ฒ๋ฅผ ๋์ ํ์ต๋๋ค.
ํด๋ฆฐ ์ํคํ ์ฒ๋ ํฌ๊ฒ ์ธ ๋ ์ด์ด(๊ณ์ธต)๋ก ๋๋๊ฒ ๋ฉ๋๋ค.
์ ๊ทธ๋ฆผ์์ ๊ฐ์ฅ ์ธ๋ถ์ ์๋ UI, API, DB ๋ฑ์ ๋จ์ ํ ์คํธ๋ฅผ ํ ์ ์๋ ์์ญ๋ค์ ๋๋ค. ์ฐ๋ฆฌ๊ฐ ์์ฑํ๋ ๋ทฐ๊ฐ ์ฌ๊ธฐ์ ํด๋น๋๊ณ ์๋ฒ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ฌ๊ธฐ์ ํด๋น๋์ฃ . ๋ทฐ ์ปจํธ๋กค๋ฌ๋ ์กฐ๊ธ ์ ๋งคํ์ง๋ง ์ฐ๋ฆฌ ์ฑ์์ ๋ทฐ ์ปจํธ๋กค๋ฌ๋ ๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๋ ์ญํ ๋ง์ ํ๋ ๊ฒ์ด ์์น์ด๊ธฐ ๋๋ฌธ์ ์ธ๋ถ ๋ ์ด์ด๋ก ๋ถ๋ฅํ ์ ์์ต๋๋ค.
Presentation์ ํ๋ฉด์ ๋ณด์ด๋ ์์ญ์ ๋ด๋นํ๋ ๋ ์ด์ด์ ๋๋ค. MVVM์์๋ ๋ทฐ ๋ชจ๋ธ์ด ์ฌ๊ธฐ์ ํด๋นํฉ๋๋ค. ๋ทฐ ๋ชจ๋ธ์ด ์ ํฌํจ๋๋๊ณ ์? ์ด์ ๋ถํฐ ๊ธฐ์กด ๋ทฐ ๋ชจ๋ธ์์ ๋น์ฆ๋์ค ๋ก์ง์ ์ ์ธํ๊ณ ํ๋ฉด์ ํ์ํ ๋ฐ์ดํฐ์๋ง ์ง์คํฉ๋๋ค. ์ด์ ์ฐ๋ฆฌ ์ฑ์์ ๋ทฐ์ ๋ทฐ ์ปจํธ๋กค๋ฌ๋ ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ์ญํ , ๋ทฐ ๋ชจ๋ธ์ ๋ทฐ์ ๊ทธ๋ ค์ง ๋ฐ์ดํฐ๋ฅผ ๋ง๋๋ ์ญํ ๋ง ์ํํ์ฃ .
๋ทฐ ๋ชจ๋ธ์์ ๋ถ๋ฆฌ๋ ๋น์ฆ๋์ค ๋ก์ง ์ ์ฆ ์ผ์ด์ค(UseCase)๋ผ๋ ์ด๋ฆ์ผ๋ก Domain ๋ ์ด์ด์ ์์นํ๊ฒ ๋ฉ๋๋ค. Domain ๋ ์ด์ด๋ ๋ฐ์ดํฐ๋ฅผ ํํํ๋ ๋ชจ๋ธ์ ๊ฐฑ์ ํ๊ฑฐ๋ ์ฑ์ ํ์ํ ์ฃผ์ํ ๋ก์ง๋ค์ ์ํํ๋ ๊ฒ์ ๋ด๋นํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋น์ฆ๋์ค ๋ก์ง์ ์ํด ์ํฅ์ ๋ฐ๊ฒ๋๋ ๋ชจ๋ธ๋ค์ด ์ด ๋ ์ด์ด์ ์์นํ๊ฒ๋ฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก Data ๋ ์ด์ด๋ Presentation ๋ ์ด์ด์ ๊ฐ์ ์์ค์ ๊ณ์ธต์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ์ญํ ์ ์ํํฉ๋๋ค. ๋คํธ์ํฌ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ Core Data์ ๊ฐ์ด ์ฑ ๋ด ์ ์ฅ์์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์์ ์ด ์ด ๊ณ์ธต์์ ์ด๋ฃจ์ด์ง๋๋ค. Data ๋ ์ด์ด์์ ์ธ๋ถ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฐ์ฒด๋ฅผ ๋ ํ์งํ ๋ฆฌ(Repository)๋ผ๊ณ ํฉ๋๋ค.
ํด๋ฆฐ ์ํคํ ์ฒ์ ํต์ฌ
ํด๋ฆฐ ์ํคํ ์ฒ์ ํต์ฌ์ ๋ด๋ถ์ ์๋ ๊ณ์ธต์ด ์ธ๋ถ์ ์๋ ๊ณ์ธต์ ์์ง ๋ชปํ๊ฒ ํ๋ ๊ฒ์ ์์ต๋๋ค. ์ฆ, Domain ๋ ์ด์ด๋ Presentaion ๋ ์ด์ด๋ Data ๋ ์ด์ด๋ฅผ ์ ๋ ์ง์ ์ฐธ์กฐํ์ง ์์ต๋๋ค. ๊ทธ๋์ ๊ฐ ๊ณ์ธต ๊ฐ ์์กด์ฑ์ ๋ฐฉํฅ์ ์ด๋ ๊ฒ ๋ฉ๋๋ค.
์ด๋ฐ ์์กด์ฑ ๊ท์น์ ์ ํด๋ ์ด์ ๊ฐ ๋ญ๊น์? ํ ์คํธ ๊ด์ ์์ ์๊ฐํด๋ณด๋ฉด ์ธ๋ถ ๋ฐฉํฅ์ผ๋ก ์์กด์ฑ์ด ์๊ฒผ์ ๋ ํ ์คํธํ๊ธฐ๊ฐ ์ด๋ ค์์ง๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ๋ง์ฝ Domain ๋ ์ด์ด์ ์ ์ฆ ์ผ์ด์ค๊ฐ ๋คํธ์ํฌ๋ก๋ถํฐ ์ด๋ค ๊ฐ์ ๋ฐ์ ์ฒ๋ฆฌํด์ผ ํ๋ค๊ณ ํด๋ด ์๋ค.
๊ทธ๋ผ ์ ์ฆ ์ผ์ด์ค๋ฅผ ํ ์คํธํ ๋๋ ํญ์ ๋ ํ์งํ ๋ฆฌ๊ฐ ์์ด์ผ ํ๊ณ , ์ด ๋ ํ์งํ ๋ฆฌ๋ ๋คํธ์ํฌ ์์ฒญ์ ๋ณด๋ด๊ธฐ ๋๋ฌธ์ ์ธํฐ๋ท ์ฐ๊ฒฐ์ด ํญ์ ํ์ํฉ๋๋ค. API์ฃผ์์ ๋ฌธ์ ๊ฐ ์๊ธฐ๊ฑฐ๋ ๋คํธ์ํฌ ์ฐ๊ฒฐ ์ํ์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋ฉด ๋ ์ด์ ์ ์ฆ ์ผ์ด์ค๋ฅผ ํ ์คํธํ ์ ์๊ฒ ๋์ฃ .
๋ฐ๋ผ์ ์ ์ฆ ์ผ์ด์ค๋ ๋ ํ์งํ ๋ฆฌ๋ฅผ ์ง์ ์์ ํ์ง ์๊ณ ๋ ํ์งํ ๋ฆฌ๋ก๋ถํฐ ๋ค์ด์ค๋ ๊ฐ์ ๋ฐ์์ผ ํฉ๋๋ค.
์ฐ๋ฆฌ ์ฑ์์๋?
๋ฉ์ดํธ ๋ฌ๋ ์ฑ์ ๋ค์ ๊ฐ์ ธ์์ ํด๋ฆฐ ์ํคํ ์ฒ๋๋ก ๋๋์ด๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ๋ญ๊ฐ ์ด์ํฉ๋๋ค.. ์์กด์ฑ์ด ๋ด๋ถ ๋ ์ด์ด๋ก๋ ์ ํฅํ๊ณ ์๋๋ฐ ์ด๋ฌ๋ฉด ๋ ํ์งํ ๋ฆฌ๋ ๋๊ฐ ํธ์ถํด์ผ ํ ๊น์..? ๋น์ฆ๋์ค ๋ก์ง์ ์ ์ฆ ์ผ์ด์ค์์ ์ด๋ฃจ์ด์ง๋๋ฐ ์ ์ฆ ์ผ์ด์ค๋ ๋ ํ์งํ ๋ฆฌ๋ฅผ ์์ ํ์ง ์์ต๋๋ค.
์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ Domain ๋ ์ด์ด์ ๋ ํ์งํ ๋ฆฌ์ ๋ํ ์ธํฐํ์ด์ค๋ฅผ ๋์ด ์์กด์ฑ ์ญ์ ์์น์ ์งํค๋ฉฐ ๋ ํ์งํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํฉ๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ์ ์ฆ ์ผ์ด์ค๋ ๊ฐ์ ๋ ์ด์ด์ ์๋ ํ๋กํ ์ฝ์ ์์ ํ๊ณ ์ค์ ๊ตฌํ์ Data ๋ ์ด์ด์ ๋์ด ์์ด ์์กด์ฑ์ ๋ฐฉํฅ์ ๋ด๋ถ๋ก ํฅํ๋๋ก ์ ์งํ๋ฉด์๋ ๋ ํ์งํ ๋ฆฌ์ ์์ฒญ์ ๋ณด๋ผ ์ ์๊ฒ ๋ฉ๋๋ค.
์ด์ ๋ ํ ์คํธ ๋ฌธ์ ๋ ํด๊ฒฐ์ด ๋๋๋ฐ์, ์ ์ฆ ์ผ์ด์ค๊ฐ ํธ์ถํ๋ ํ๋กํ ์ฝ์ ๊ตฌํ์ฒด๋ฅผ ๋คํธ์ํฌ๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฐ์ง ๋ ํ์งํ ๋ฆฌ๋ก ์ ์ํ๊ณ ํ ์คํธํ๊ณ ์ ํ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฌด์กฐ๊ฑด ๋ฐํํ๊ฒ ํ๋ค๋ฉด, ๋คํธ์ํฌ๊ฐ ์ฐ๊ฒฐ๋์ด ์์ง ์์๋, API์ฃผ์๊ฐ ์๋ชป๋์ด๋ ์ ์ฆ ์ผ์ด์ค๋ฅผ ๋จ๋ ์ผ๋ก ํ ์คํธํ๋ ๊ฒ์ด ๊ฐ๋ฅํด์ง๋๋ค.
๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ
MVVM๊ณผ ํด๋ฆฐ ์ํคํ ์ฒ์์๋ ๋ทฐ ๋ชจ๋ธ์ด ์ ๋๋ก ๋ทฐ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ ํ์ง ์์ต๋๋ค. ์ ์ด์ UI์์ญ์ ๋ทฐ ๋ชจ๋ธ์์ ๋ถ๋ฆฌํ๊ธฐ ์ํ ๋ชฉ์ ์ผ๋ก ๋๋์์ผ๋๊น์. ๊ทธ๋ผ UI๋ฅผ ์ ๋ฐ์ดํธํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์?
์ฐ๋ฆฌ๋ ๋ทฐ์ ๊ทธ๋ ค์ผ ํ ๊ฐ์ด ์ ๋ฐ์ดํธ๋์์ ๋ ๋ทฐ์ ์๋ ค์ ๋ทฐ๋ฅผ ๋ค์ ๊ทธ๋ฆฌ๋๋ก ํด์ผ ํฉ๋๋ค. ์ด๋ ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ทฐ์ ์ ์ ํ๊ฒ ์ฐ๊ฒฐ ์ง๋ ๊ฒ์ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด๋ผ๊ณ ํฉ๋๋ค. ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ํด์ ๋ช ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ํํ ์ ์๋๋ฐ์. ๊ฐ๋จํ๊ฒ ์๊ฐํ๋๋ก ํ๊ฒ ์ต๋๋ค.
1. ์ฝ๋ฐฑ ๋ฑ๋กํ๊ธฐ: ๋จผ์ ๋ทฐ ์ปจํธ๋กค๋ฌ์์ ์์ ํ ๋ด์ฉ์ ํด๋ก์ ์ ๋ด์ ๋ทฐ ๋ชจ๋ธ์ ๋๊ฒจ์ฃผ๋ ๋ฐฉ๋ฒ์ ์ ํํ ์ ์์ต๋๋ค.
์ฝ๋ฐฑ์ผ๋ก ๋ทฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ก์ง์ ๋ทฐ ๋ชจ๋ธ์ ๋ฑ๋กํด๋๊ณ ์ ์ฆ ์ผ์ด์ค์์ ๊ฐ์ด ๊ฒฝ์ ๋๋ฉด ํด๋น ์ฝ๋ฐฑ์ ์คํํ๋๋ก ํ๋ฉด ๋ทฐ ๋ชจ๋ธ์ด ์ง์ ๋ทฐ๋ฅผ ์ ๋ฐ์ดํธํ์ง ์๋๋ก ํ ์ ์์ต๋๋ค.
2. ๋ฆฌ์กํฐ๋ธ ํ๋ก๊ทธ๋๋ฐ: ์ฝค๋ฐ์ธ, Rx์ ๊ฐ์ ๋ฆฌ์กํฐ๋ธ ํ๋ก๊ทธ๋๋ฐ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค.
์ด๋ฒ์ ์ฝ๋ฐฑ์ ์ฌ์ฉํ์ง ์๊ณ ๊ฐ ๋ ์ด์ด๊ฐ ์์ ์ ๋ด๋ถ ๋ ์ด์ด์ ๊ฐ๋ค์ ๊ตฌ๋ ํ ์ฑ๋ก ๊ฐ์ด ์ ๋ฐ์ดํธ๋๋ฉด ์ง์ ๋ ์ฒ๋ฆฌ ๋ก์ง์ ์ํํฉ๋๋ค.
์ ์์์ฒ๋ผ ๊ฑฐ๋ฆฌ ๊ฐ์ ๊ฐฑ์ ์ ์์ฒญํ๋ฉด ์ ์ฆ ์ผ์ด์ค๊ฐ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐฑ์ ํ๊ณ , ์ด ๊ฐ์ ๊ตฌ๋ ํ๊ณ ์๋ ๋ทฐ ๋ชจ๋ธ์ด ์๊ฐ ํฌ๋งท์ ๋ณ๊ฒฝํฉ๋๋ค. hh:mm:ss ํํ๋ก์. ๊ทธ๋ฆฌ๊ณ ์ด ๊ฐ์ด ์๋ก์ด ๋ฌธ์์ด๋ก ๋ทฐ ๋ชจ๋ธ์ ์ ์ฅ๋๋ฉด, ์ด๋ฅผ ๊ตฌ๋ ํ๊ณ ์๋ ๋ทฐ ์ปจํธ๋กค๋ฌ๊ฐ ์์ ์ ๋ ์ด๋ธ์ ์ ๋ฐ์ดํธํฉ๋๋ค.
RxSwift
์ ํฌ ํ์ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ํ๊ธฐ ์ํด์ RxSwift๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ์ ํฌ ์ฑ์ด ๊ฐ์ง๋ ๊ธฐ๋ฅ ํน๋ณํ ๊ธฐ๋ฅ๋ค ๋๋ฌธ์ ๋๋ค. ์๋ฅผ ๋ค๋ฉด ์๋์ ๊ฐ์ด ์น๊ตฌ์ ์ ๋ณด๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ฐ์์์ผ ํ๋ ํ๋ฉด์ด ์์ต๋๋ค.
์ด ํ๋ฉด์์ ์นผ๋ก๋ฆฌ, ์๊ฐ, ๋์ ๋ฌ๋ฆฐ ๊ฑฐ๋ฆฌ, ์น๊ตฌ์ ๋ฌ๋ฆฐ ๊ฑฐ๋ฆฌ๋ ๋ชจ๋ ํ ๋ฒ์ ์์ฒญ ์ดํ์ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฐ์ด ๋ฐ์ํฉ๋๋ค.
๊ทธ์ค์์๋ ๋คํธ์ํฌ๋ฅผ ์ฌ์ฉํ๋ ์๋๋ฐฉ์ ์ค์๊ฐ ๊ฑฐ๋ฆฌ๋ ์๋์ ๊ฐ์ ํ๋ฆ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ฒ ๋ฉ๋๋ค.
์ด๋ฐ ์์ธ๋ฐ์, Firebase์์ ์ ๊ณตํ๋ ํ๋ ์์ํฌ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ํ ์ต์ ๋ฒ๋ฅผ ๊ฑธ์ด๋๋ฉด, ์๋ฒ์์ ๊ฐ์ด ๊ฐฑ์ ๋๋ ๋๋ก ์๋ก์ด ๊ฐ์ด ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌ๋ฉ๋๋ค. ์ด๋ ์ฒซ ์์ฒญ ์ดํ์๋ FirebaseService๋ถํฐ ๋ ํ์งํ ๋ฆฌ, ์ ์ฆ ์ผ์ด์ค, ๋ทฐ ๋ชจ๋ธ๋ก ์ด์ด์ง๋ ๋ฐ์ดํฐ์ ์ฐ๊ฒฐํต๋ก๊ฐ ๊ณ์ ์ด์์์ด์ผ ํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
๋ง์ฝ ๋ทฐ ๋ชจ๋ธ -> ์ ์ฆ ์ผ์ด์ค -> ๋ ํ์งํ ๋ฆฌ -> ๋คํธ์ํฌ๋ฅผ ๋ชจ๋ escaping closure๋ก ๋ฌถ์ด์ฃผ๋ฉด ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ํฌ๊ฒ ๋จ์ด์ง๊ฒ ๋ฉ๋๋ค.
๊ฐ๋จํ๊ฒ ์จ๋ณด๋ฉด ์ด๋ฐ ์์ผ๋ก ๋๊ฒ ์ฃ
// viewModel
func viewDidLoad(completionHandler: @escaping (String) -> Void) {
self.usecase.requestMateDistance() { result in
switch result {
case .success(let distance):
let distanceString = self.convertDoubleToString(distance)
completionHandler(distanceString)
case .failure:
// error handling
}
}
}
// usecase
func requestMateDistance(completionHandler: @escaping (Result<Double, Error>) -> Void) {
self.repository.requestListeningServer() { result in
switch result {
case .success(let distance):
let distance = self.convertToDistance(distanceData)
completionHandler(.success(distance))
case .failure:
// error handling
completionHandler(.failure(error))
}
}
}
// repository
func requestListeningServer(completionHandler: @escaping (Result<Data, Error>) -> Void) {
self.service.start() { result in
switch result {
case .success(let distanceData):
completionHandler(.success(distanceData))
case .failure:
// error handling
completionHandler(.failure(error))
}
}
}
์ฝ๋ฐฑ์ ์ธ์๋ก ๊ฐ์ง๋ ๋ฉ์๋๊ฐ ๋ค์ ์๋ก์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด์ ์ฝ๋ฐฑ์ ์ ์ํ๊ธฐ ๋๋ฌธ์ ์ฝ๋ฐฑ์ ์ฝ๋ฐฑ์ด ์ด์ด์ง๊ฒ ๋ฉ๋๋ค. ๋ง์ฝ ์ฌ๊ธฐ์ ๋ ์ด์ด์ ๊น์ด๊ฐ ๋ ๊น์ด์ง๋ค๋ฉด ๋ ๋ง์ ์ฝ๋ฐฑ์ ์์ฑํด์ผ๊ฒ ์ฃ .
RxSwift๋ ์์ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฃผ ๊ฐ๋จํ๊ณ ๋ช ๋ฃํ๊ฒ ๋ง๋ค์ด์ค๋๋ค.
// viewModel
func viewDidLoad() {
self.usecase.requestMateDistance()
.map(self.convertDoubleToString)
.subscribe(
onNext: { distance in self.relay.accept(distance) },
onError: { errorHandling }
)
.disposed(by: disposeBag)
}
// usecase
func requestMateDistance() -> Observable<Double> {
return self.repository.requestListeningServer()
.map(self.convertToDistance)
}
// repository
func requestListeningServer() -> Observable<Data> {
return self.service.start()
}
์ด๋ ๊ฒ์. ๋ฐํ ๊ฐ์ ๋ํ ํ์ ์ด ๋๋ฌด๋ ๋ช ํํ๊ฒ ์ ์๋์ด ์์ด ์ด ํจ์ ํธ์ถ์ ํตํด ๋น๋๊ธฐ๋ก ๋ฐ์์ผ ํ ๊ฐ์ด ๋ฌด์์ธ์ง ์ฝ๊ฒ ์ ์ ์๊ณ , ์๋ฌ ๋ํ onError ํด๋ก์ ๋ฅผ ํตํด ์ฝ๊ฒ ์ ์ดํ ์ ์์ต๋๋ค.
Rx์ Input/Output ๊ตฌ์กฐ๋ฅผ ๊ณ๋ค์ด๊ธฐ
์ ํฌ ํ์ Rx์ ์ฌ์ฉ์ ๊ทน๋ํํ๊ธฐ ์ํด์ Input/Ouput ๋ชจ๋ธ๋ง์ ์ ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. Input/Output ๋ชจ๋ธ๋ง์ ํ๋ฉด์์ ์ผ์ด๋๋ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ Input์ผ๋ก ์ ์ํ๊ณ , Ouput์ ๊ทธ ์ด๋ฒคํธ๋ค๋ก ์ธํด ํ๋ฉด์ ๋ณด์ผ ๋ฐ์ดํฐ๋ค์ ์ ์ํ๊ฒ ๋ฉ๋๋ค.
์ด๋ฒ์ ์ค์ ๋ก ์ฑ์์ ์ฌ์ฉ๋ ๋ทฐ ๋ชจ๋ธ์ ์ฝ๋ ์ผ๋ถ๋ฅผ ๊ฐ์ ธ์์ต๋๋ค. ์ด ์ฝ๋๋ ๊ณ์ ์์๋ก ์ฌ์ฉํ๊ณ ์๋ ๋ฌ๋ฆฌ๊ธฐ ํ๋ฉด์ ๋ํ Input๊ณผ Output์ธ๋ฐ์, ์ด ๋ฐ์ดํฐ๋ฅผ ์ค์ ํ๋ฉด์ด๋ ์ฎ์ด๋ณด๋ฉด ์ด๋ ๊ฒ ๋ฉ๋๋ค..!
ํ๋ฉด์์ ์ผ์ด๋๋ ์ด๋ฒคํธ๋ค์ ๋ทฐ ๋ชจ๋ธ์ ๋ฐ์ธ๋ฉ๋์ด์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๋๋ง๋ค ๋ทฐ ๋ชจ๋ธ์ด ์ ์ฆ ์ผ์ด์ค์ ๋น์ฆ๋์ค ๋ก์ง์ ์์ฒญํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ก ๊ฐฑ์ ๋๋ ์ฌ๋ฌ ๊ฐ๋ค์ Output์ ๋ฐ์ธ๋ฉํด ๋ทฐ ์ปจํธ๋กค๋ฌ๋ Ouput์ ๋ณด๊ณ ์์ ์ด ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ํ๋ฉด์ ๊ทธ๋ ค์ผ ํ ์ง ์๊ฒ ๋ฉ๋๋ค.
Output์์๋ ๊ฑฐ๋ฆฌ, ์นผ๋ก๋ฆฌ, ์๊ฐ์ฒ๋ผ ๊ณ์ ๊ฐ์ด ๊ฐฑ์ ๋๋ ๋ฐ์ดํฐ๋ค์ Rx๋ก Output์ผ๋ก ์คํธ๋ฆผ์ด ํ๋ฌ๊ฐ๋๋ก ๋ง๋ค์ด๋๊ณ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๊ณ์ ์คํธ๋ฆผ์ ๊ฐ์ ๋ฃ์ด์ฃผ๋ฉด ๋ฉ๋๋ค.
๊ทธ๋ผ Input์ Ouput์ด๋ ์ฐ๊ฒฐํด์ฃผ์ด์ผ ํ๋๋ฐ์, ์ด ๋ทฐ๋ชจ๋ธ์ ๋จผ์ ๋ทฐ์ปจํธ๋กค๋ฌ์์ ๋๊ฒจ์ค Input์ ์ด๋ฒคํธ๋ค์ ๊ตฌ๋ ํด๋๊ณ ์ด๋ฒคํธ๊ฐ ๋ค์ด์ฌ ๋๋ง๋ค,
์ด๋ ๊ฒ ํ์ํ ๋ก์ง๋ค์ ์ ์ฆ์ผ์ด์ค๋ฅผ ํตํด ํธ์ถํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๋ก์ง์ผ๋ก ๋ง๋ค์ด์ง๋ ๋ฐ์ดํฐ๋ค์ ์๋์ฒ๋ผ ๊ตฌ๋ ํ๊ณ ํฌ๋งท์ ๋ณํํด์ Ouput์ ๋ฐ์ธ๋ฉ ํด์ค๋๋ค.
๋ทฐ ์ปจํธ๋กค๋ฌ๋ ์ด Output์ ๋ด๊ฒจ์๋ Observableํ ํ๋กํผํฐ๋ค์ ๊ตฌ๋ ํด๋๊ณ
์๋ก์ด ๊ฐ์ด ์คํธ๋ฆผ์ ๋ค์ด์ฌ ๋๋ง๋ค UI๋ฅผ ์ ๋ฐ์ดํธ ํด์ฃผ๊ฒ ๋ฉ๋๋ค.
์ด๋ฐ ์์ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๋ฉด ๋ทฐ ๋ชจ๋ธ์ ํจ์๋ค์ ๋ชจ๋ ์ฝ์ด๋ณด์ง ์์๋ ๋ทฐ์์ ์ด๋ค ์ผ๋ค์ด ์ผ์ด๋๋์ง ํ๋์ ํ์ธํ ์ ์์ต๋๋ค.
์ํคํ ์ฒ ํ๋์ ๋ณด๊ธฐ
์ ์ฒด ์ํคํ ์ฒ๋ฅผ ๋์ํํ๋ฉด ์ด๋ ์ต๋๋ค. ํด๋ฆฐ ์ํคํ ์ฒ๋ฅผ ํตํด ๊ฐ ๋ชจ๋๋ค์ ์ญํ ์ ๋ถ๋ช ํ๊ฒ ๋ถ๋ฆฌํ๊ณ , RxSwift์ RxCocoa๋ฅผ ํตํด ๋น๋๊ธฐ ๋ฐ์ดํฐ์ ์์ฒญ, ๊ทธ๋ฆฌ๊ณ ์๋ก์ด ๊ฐ์ ๋ทฐ์ ์ ์ฉํ๋ ๊ฒ ๊น์ง ๋ฌผ ํ๋ฅด๋ฏ์ด ํ๋์ ํ๋ฆ์ผ๋ก ๋ง๋ค์ด๋ผ ์ ์์์ต๋๋ค.
์ํคํ ์ฒ๋ฅผ ์ค๊ณํ๋ฉด์ ํ๋ ์๊ฐ๋ค
์ต๊ทผ์ ์ค๋ฒ ์์ง๋์ด๋ง์ด๋ผ๋ ๋จ์ด๋ฅผ ์๊ฒ ๋์์ต๋๋ค. ํ์ ์ด์์ผ๋ก ์์ง๋์ด๋ง์ ํด๋ฒ๋ ค์ ์คํ๋ ค ์์ฐ์ฑ์ด ๋ ๋จ์ด์ง๋ ๊ฒ์ ๋งํ๋๋ฐ์, ์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ํ๋ฉด์๋ ํ ๋ฌ ๋ด๋ด ์ค์ค๋ก ์ค๋ฒ ์์ง๋์ด๋ง์ ํ๊ณ ์์ง๋ ์์์ง ์๋ฐฑ ๋ฒ ์์ฌ์ด ๋ค์์ต๋๋ค.
๋์์ผ๋ก ๋ณด๋ฉด ๊ฐ๋จํด ๋ณด์ด์ง๋ง, ์ค์ ๋ก๋ Presentaion ๋ ์ด์ด๋ฅผ ์ ์ธํ ๋ชจ๋ ๋ ์ด์ด์ ๊ฐ์ฒด๋ค์ ์ธํฐํ์ด์ค ํ๊ฐ ๋์ด์์ต๋๋ค. ๊ฒฐ๊ตญ ๋ทฐ ์ปจํธ๋กค๋ฌ์์๋ถํฐ ๋ ํ์งํ ๋ฆฌ๊น์ง ๊ฐ๋ค ์ค๋ ๊ธฐ๋ฅ์ ํ๋ ๊ฐ๋ฐํ๊ธฐ ์ํด์๋ ๋ง๊ฒ๋ ์ด 6๊ฐ์ ํ์ผ์ ์๋ก ์์ฑํ๊ฑฐ๋ ์ฝ๋๋ฅผ ๊ธฐ์กด ํ์ผ์ ์ถ๊ฐํ๊ฒ ๋ฉ๋๋ค. ์ด๋ฐ ๋ฒ๊ฑฐ๋ก์์ ๊ฑฐ์น๋ ๋งํผ ์ฐ๋ฆฌ ์ฑ์ ์ ์ง๋ณด์์ฑ์ด ์ ์ ์ง๋๊ณ ์๋์ง ์์ฌ์ค๋ฝ๊ณ , ์ฝ๋๋ฅผ ๋ถ์ํ ๋๋ ๊ณ์ ํ์ผ์ ํ๊ณ ํ์ ๋ค์ด๊ฐ์ผ์ง ๊ธฐ๋ฅ์ด ์ด๋ป๊ฒ ๋์ํ๋์ง ์๊ฒ ๋๋ ๋ถํธํจ๋ ์์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ํคํ ์ฒ๋ฅผ ๋ง๋ค์ด๋๊ณ ์ ๋ง ์ง๋ฆฟํ ์๊ฐ์ ์ฝ๋์ ์ ์ฉํด์ผ ํ๋ ์ฌ์ํ ์์ ๊ณผ ๋ณํ๊ฐ ์ ๋ง ์ฌ์ํ ์์ ์ผ๋ก ๋๋ ๋ค๋ ๊ฒ์ ๋๋ ๋์ ๋๋ค. ํ ๋ ์ด์ด์ ์๋ ์ฝ๋์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋ฉด ์ ๋ง๋ก ํด๋น ๋ ์ด์ด๋ง ์์ ํ๋ฉด ๋๊ณ , ๋ค๋ฅธ ํ์ผ์ ์ด์ด๋ณด์ง ์์๋ ๋ฌธ์ ๊ฐ ์๊ธฐ์ง ์์ต๋๋ค. ํ๋ฉด์ด ์ ์ ๋ง์์ง๊ณ ์๋ก์ด ๊ธฐ๋ฅ๋ค์ด ๋ง์์ง๋ค๋ฉด ์ง๊ธ ๋น์ฅ์ ์ค๋ฒ ์์ง๋์ด๋ง์ผ์ง๋ผ๋ ๋ฏธ๋๋ฅผ ์ํ ํฌ์๋ผ๊ณ ๋ณผ ์๋ ์์ง ์์๊น์?
๋ง์ง๋ง์ผ๋ก ์ํคํ ์ฒ๋ฅผ ์ง๋ด๊ธฐ ์ํด ๊ณ ๋ฏผํ๋ฉด์ ๋๋ฆ๋๋ก ์์ ์ด ์๊ธด ๊ฒ ๊ฐ์ต๋๋ค. ์ฒ์ ํด๋ฆฐ ์ํคํ ์ฒ์ MVVM์ ํ์ตํ ๋๋ ๊นํ๋ธ๋ ๊ตฌ๊ธ์์ ์๋ฃ๋ค์ ์ฐพ์๊ฐ๋ฉด์ ๊ณต๋ถํ๋๋ฐ ์ ๋ง๋ค ์ ์ฉํ๋ ๋ฐฉ์์ด ๋ค ๋ค๋ฅด๊ณ ํท๊ฐ๋ฆฌ๋๋ผ๊ณ ์.. ์ด๋ฒ ํ๋ก์ ํธ๋ ๊ทธ๋ฐ ์๋ฃ๋ค์์ ์์ํ์ง๋ง ๊ณ ๋ฏผ์ ๊ฑฐ๋ญํ๋ฉด์ ๊ทธ๋ฅ ๋ฌด์์ ์์ ์ฝ๋ ๋ฐ๋ผ ํ๊ธฐ๊ฐ ์๋๋ผ ์๊ฐ๊ณผ ๋ง์์ด ๋ด๊ธด ์ฝ๋๋ฅผ ๋ง๋ค์ด ๋ผ ์ ์์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฒฐ์ ์ ์ผ๋ก ์ํคํ ์ฒ ์ค๊ณ๋ ์ง์ง ์ฌ๋ฐ์ด์!
๋ง๋ฌด๋ฆฌ
๊ธด ๊ธ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค! ์ ํฌ ํ ํ๋ก์ ํธ ๊นํ์๋ ๋๋ฌ ์ค์ธ์~!
'๐ ์์ด-์ค-์์ค > ๐ฑ iOS ๊ฐ๋ฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote