๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด
๐Ÿ’ก ์•„์ง ๋ฐฐ์šฐ๋Š” ๋‹จ๊ณ„์— ์žˆ๋Š” iOS ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค! ํ‹€๋ฆฐ ๋‚ด์šฉ์ด๋‚˜ ๋” ์•Œ๋ ค์ฃผ๊ณ  ์‹ถ์€ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š”..!

๊ฐ„๋‹จํ•œ ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

 

์•ˆ๋…•ํ•˜์„ธ์š”! ์ด๋ฒˆ ํฌ์ŠคํŠธ๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ MVVM๊ณผ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜์— RxSwift๋ฅผ ๋„์ž…ํ•œ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜๋Š” ํฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค..! ์ €ํฌ ํŒ€์—์„œ ์ง„ํ–‰ํ•œ ํ”„๋กœ์ ํŠธ๋Š” Mate Runner๋ผ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚˜์ดํ‚ค ๋Ÿฐ ํด๋Ÿฝ๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์™€ ํ•จ๊ป˜ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ชฉํ‘œ ๊ฑฐ๋ฆฌ๋ฅผ ๋‹ฌ๋ฆด ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

 

๋” ์ž์„ธํ•œ ์†Œ๊ฐœ์™€ ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ํ˜„ํ™ฉ์€ https://github.com/boostcampwm-2021/iOS06-MateRunner ์—์„œ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ์–ด์š”!

 

GitHub - boostcampwm-2021/iOS06-MateRunner: ํ•จ๊ป˜ ๋‹ฌ๋ฆฌ๋Š” ์ฆ๊ฑฐ์›€, Mate Runner ๐Ÿƒ๐Ÿป‍โ™‚๏ธ๐Ÿƒ๐Ÿป‍โ™€๏ธ

ํ•จ๊ป˜ ๋‹ฌ๋ฆฌ๋Š” ์ฆ๊ฑฐ์›€, Mate Runner ๐Ÿƒ๐Ÿป‍โ™‚๏ธ๐Ÿƒ๐Ÿป‍โ™€๏ธ. Contribute to boostcampwm-2021/iOS06-MateRunner development by creating an account on GitHub.

github.com

 

MVVM

MVVM์€ iOS ๊ฐœ๋ฐœ์„ ํ•œ๋‹ค๋ฉด ์ต์ˆ™ํ•œ ๊ตฌ์กฐ์ผ ํ…๋ฐ์š”, View, ViewModel, Model๋กœ ์—ญํ• ์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด MVC๊ตฌ์กฐ๋Š” Controller์—์„œ, ํŠนํžˆ iOS์—์„œ๋Š” ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋„ˆ๋ฌด ๋งŽ์€ ์ผ์„ ํ•˜๋‹ค ๋ณด๋‹ˆ ์—ญํ• ์ด ๊ณผ์ค‘๋˜๊ณ , ๋‹จ์ˆœํ•œ ๋กœ์ง์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด์„œ UIkit์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. 

 

MVVM์„ ๋„์ž…ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์•ฑ์˜ ๊ตฌ์กฐ๋ฅผ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ ์˜์—ญ๋“ค๊ณผ ์—ญํ• ์„ ์ •๋ฆฌํ•ด๋ณด๋ฉด,

 

1. ๋ทฐ์™€ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ: ์ •๋ง ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. 

2. ๋ทฐ ๋ชจ๋ธ: ํ™”๋ฉด์—์„œ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๋กœ์ง์„ ์‹คํ–‰ํ•˜๊ณ  ๋ชจ๋ธ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

3. ๋ชจ๋ธ: ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

 

์šฐ๋ฆฌ ์•ฑ์—์„œ๋Š”?

๋ฉ”์ดํŠธ ๋Ÿฌ๋„ˆ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํ˜„์žฌ ๋‹ฌ๋ฆฌ๊ธฐ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•ด์ค๋‹ˆ๋‹ค.

์ด ํ™”๋ฉด์— ๋Œ€ํ•ด์„œ ์•ฑ ๊ตฌ์กฐ๋ฅผ MVVM์œผ๋กœ ๋‚˜๋ˆ„๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ทฐ ๋ชจ๋ธ์€ ํƒ€์ด๋จธ๋ฅผ ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜, ์ƒˆ๋กœ์šด ์นผ๋กœ๋ฆฌ ์ •๋ณด๋ฅผ ๊ฐฑ์‹ ํ•˜๊ณ  ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํฌํ•จํ•˜๊ณ , ๋ชจ๋ธ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ํ™”๋ฉด์— ๋ณด์ผ ์ˆ˜ ์žˆ๋„๋ก ํ˜•ํƒœ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด์„œ ๊ฒฝ๊ณผ์‹œ๊ฐ„์€ ๋ทฐ ๋ชจ๋ธ์—์„œ ํƒ€์ด๋จธ๋ฅผ ์‹œ์ž‘ํ•œ ๋’ค, ์ดˆ๋‹จ์œ„๋กœ ๋ชจ๋ธ์— ๊ณ„์† ์ €์žฅํ•˜๊ณ  ํ™”๋ฉด์— ๋ณด์ผ ๋•Œ๋Š” hh:mm:ss ํฌ๋งท์˜ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•œ ๋’ค์— ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—๊ฒŒ ๋ฌธ์ž์—ด์„ ๋„˜๊ฒจ์ฃผ๋ฉด ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋Š” ๋ฐ›์€ ๋ฌธ์ž์—ด์„ ํ‘œ์‹œํ•˜๊ธฐ๋งŒ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ทฐ๋Š” ์ •๋ง ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๋Š” ๋ฐ์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๊ณ , ๋ทฐ ๋ชจ๋ธ์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋ชจ๋ธ์˜ ๊ด€๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•˜๋ฉด์„œ ์‹ค์ œ๋กœ ์•ฑ์„ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ๋„ ๋ทฐ์— ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ์ „๋‹ฌ๋˜์–ด ๊ทธ๋ ค์งˆ์ง€ ๋ทฐ ๋ชจ๋ธ๋งŒ ๋”ฐ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋ถ„๋ฆฌ๋Š” ๋์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ณต์žกํ•ด..

MVVM ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด์„œ ๋ทฐ์™€ ๋กœ์ง์€ ๋ถ„๋ฆฌํ•ด๋‚ผ ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ์š”, ์•ฑ์ด ์ ์  ๋ณต์žกํ•ด์ง€๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด์„œ ๋ทฐ ๋ชจ๋ธ์ด ๋„ˆ๋ฌด ๋งŽ์€ ์ผ์„ ํ•˜๊ฒŒ ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

 

์‹ค์ œ๋กœ ์œ„ ํ™”๋ฉด์—์„œ ์นผ๋กœ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•˜๋ ค๋ฉด Core Motion์ด๋ผ๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์˜ ์›€์ง์ž„ ์ •๋ณด๋ฅผ ์•Œ์•„์•ผ ํ•˜๊ณ , Core Location ๋„ค์ดํ‹ฐ๋ธŒ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ†ตํ•ด ์œ„์น˜ ์ •๋ณด๋„ ์•Œ์•„๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”๊ตฐ๋‹ค๋‚˜ ์นœ๊ตฌ์™€ ์‹ค์‹œ๊ฐ„ ํ†ต์‹  ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋œ๋‹ค๋ฉด ๋„คํŠธ์›Œํฌ ์š”์ฒญ๊ณผ ์ฒ˜๋ฆฌ๊นŒ์ง€ ๋ทฐ ๋ชจ๋ธ์—์„œ ๋ชจ๋‘ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ์š”.. ๋ฒŒ์จ ์—„์ฒญ ๋ณต์žกํ•ด ๋ณด์ด์ฃ ..? ๊ทธ๋ž˜์„œ ๋ทฐ ๋ชจ๋ธ์˜ ๋ถ€๋‹ด์„ ์ค„์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด์„œ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋„์ž…ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜

์ €ํฌ ํŒ€์—์„œ๋Š” ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์— ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋Š”๋ฐ์š”, ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋จผ์ € ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ• ๊ฒŒ์š”.

 

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

์ €ํฌ ํŒ€์€ ์œ„ ๋ ˆํฌ์—์„œ ์†Œ๊ฐœํ•˜๋Š” 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์„ ํ•™์Šตํ•  ๋•Œ๋Š” ๊นƒํ—ˆ๋ธŒ๋‚˜ ๊ตฌ๊ธ€์—์„œ ์ž๋ฃŒ๋“ค์„ ์ฐพ์•„๊ฐ€๋ฉด์„œ ๊ณต๋ถ€ํ–ˆ๋Š”๋ฐ ์ €๋งˆ๋‹ค ์ ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ๋‹ค ๋‹ค๋ฅด๊ณ  ํ—ท๊ฐˆ๋ฆฌ๋”๋ผ๊ณ ์š”.. ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋Š” ๊ทธ๋Ÿฐ ์ž๋ฃŒ๋“ค์—์„œ ์‹œ์ž‘ํ–ˆ์ง€๋งŒ ๊ณ ๋ฏผ์„ ๊ฑฐ๋“ญํ•˜๋ฉด์„œ ๊ทธ๋ƒฅ ๋ฌด์ž‘์ • ์˜ˆ์ œ ์ฝ”๋“œ ๋”ฐ๋ผ ํ•˜๊ธฐ๊ฐ€ ์•„๋‹ˆ๋ผ ์ƒ๊ฐ๊ณผ ๋งˆ์Œ์ด ๋‹ด๊ธด ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฒฐ์ •์ ์œผ๋กœ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„๋Š” ์ง„์งœ ์žฌ๋ฐŒ์–ด์š”!

 

๋งˆ๋ฌด๋ฆฌ

๊ธด ๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ์ €ํฌ ํŒ€ ํ”„๋กœ์ ํŠธ ๊นƒํ—™์—๋„ ๋†€๋Ÿฌ ์˜ค์„ธ์š”~!

 

GitHub - boostcampwm-2021/iOS06-MateRunner: ํ•จ๊ป˜ ๋‹ฌ๋ฆฌ๋Š” ์ฆ๊ฑฐ์›€, Mate Runner ๐Ÿƒ๐Ÿป‍โ™‚๏ธ๐Ÿƒ๐Ÿป‍โ™€๏ธ

ํ•จ๊ป˜ ๋‹ฌ๋ฆฌ๋Š” ์ฆ๊ฑฐ์›€, Mate Runner ๐Ÿƒ๐Ÿป‍โ™‚๏ธ๐Ÿƒ๐Ÿป‍โ™€๏ธ. Contribute to boostcampwm-2021/iOS06-MateRunner development by creating an account on GitHub.

github.com