12
15

 

์•ˆ๋“œ๋กœ์ด๋“œ๋ฅผ ์ ‘ํ•œ์ง€๋Š” 1๋…„์ด ๋˜์–ด๊ฐ„๋‹ค. ๊ทธ ์ค‘์— ์ •๋ง ์ง‘์ค‘ํ•ด์„œ ํ•œ ๊ธฐ๊ฐ„์€ 6๊ฐœ์›” ์ •๋„๋‹ค. ๋‚œ ๊ตฌํ˜„์—๋งŒ ์‹ ๊ฒฝ์ผ๊ธฐ ๋•Œ๋ฌธ์— ์˜์กด์„ฑ์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒŒ ์ข‹๋‹ค๋Š” ์•„์ฃผ ๊ธฐ์ดˆ์ ์ธ ์ง€์‹๋งŒ์„ ๊ฐ–๊ณ ์žˆ์—ˆ๋‹ค. ์ด๋ฒˆ์— ์ƒˆ ํ”„๋กœ์ ํŠธ์— ์ฐธ์—ฌํ•˜๊ฒŒ ๋๋Š”๋ฐ ๋ฏผํ๋ฅผ ๋ผ์น˜์ง€ ์•Š๊ธฐ์œ„ํ•ด ๊ณต๋ถ€๋ฅผ ํ•ด์•ผํ•œ๋‹ค. ์ฒซ๋ฒˆ์งธ๋กœ MVVM์ด๋‹ค.

์ผ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ ์›์น™

ํŒจํ„ด์„ ๋“ค์–ด๊ฐ€๊ธฐ ์ „์— ์•ˆ๋“œ๋กœ์ด๋“œ ๊ณต์‹ ๋ฌธ์„œ์—์„œ ์ง€์ •ํ•œ ์•„ํ‚คํ…์ฒ˜ ์›์น™์„ ํ•™์Šตํ•˜๊ฒ ๋‹ค. ๋ฒˆ์—ญ ์˜ค๋ฅ˜๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์˜๋ฌธ๊ณผ ๊ฐ™์ด ๋ดค๋‹ค.

  • ๊ด€์‹ฌ์‚ฌ๋ถ„๋ฆฌ
  • ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์—์„œ UI ๋„์ถœํ•˜๊ธฐ
  • ๋‹จ์ผ ์†Œ์Šค ์ €์žฅ์†Œ
  • ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„

์ด๋ ‡๊ฒŒ ๋„ค ๊ฐ€์ง€๊ฐ€ ์ฃผ์–ด์กŒ๋‹ค.

๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ Separation of concerns

๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ณ  ์ œ์ผ ์šฐ์„ ์‹œ ๋˜์–ด์•ผ ํ•  ์›์น™์ด๋‹ค. Activity๋‚˜ Fragment๋Š” UI๊ธฐ๋ฐ˜ ํด๋ž˜์Šค๋‹ค. ์ด ๊ฒฝ์šฐ UI ๋ฐ ์šด์˜์ฒด์ œ ์ƒํ˜ธ์ž‘์šฉ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง๋งŒ ํฌํ•จํ•ด์•ผํ•œ๋‹ค. ๋‹ด๋‹นํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ถ„๋ฆฌํ•œ๋‹ค๋Š” ๊ฐœ๋…์œผ๋กœ ๊ฐ ํด๋ž˜์Šค๋ผ๋ฆฌ ์˜์กด์„ฑ์„ ๋‚ฎ์ถ”๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. Activity๋‚˜ Fragment๋Š” ๋‹จ์ง€ Android OS์™€ ์•ฑ์„ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์ค‘๊ฐ„๋‹ค๋ฆฌ๋‹ค. OS๊ฐ€ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ์–ธ์ œ๋“ ์ง€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋‚ ๋ฆด ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ์ž‘์—…์€ ํ•„์ˆ˜๋‹ค.

๋ฐ์ดํ„ฐ ๋ชจ๋ธ์—์„œ UI ๋„์ถœํ•˜๊ธฐ Drive UI from data models

๋ฐ์ดํ„ฐ ๋ชจ๋ธ์€ ์•ฑ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์•ฑ์˜ UI์š”์†Œ ๋ฐ ๊ธฐํƒ€ ๊ตฌ์„ฑ์š”์†Œ์™€ ๋…๋ฆฝ๋˜์–ด์žˆ๋Š” ๋ชจ๋ธ์ด๋‹ค(์ˆ˜๋ช…์ฃผ๊ธฐ์˜ ๋ถ„๋ฆฌ). ์•ฑ์˜ ๋ฐ์ดํ„ฐ์ด๋ฏ€๋กœ ์•ฑ์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ os๊ฐ€ ์ œ๊ฑฐํ•˜๋ฉด ๋‹น์—ฐํžˆ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋„ ์ œ๊ฑฐ๋œ๋‹ค.

๊ฐ€๊ธ‰์ ์ด๋ฉด ์ง€์†๋ชจ๋ธ(persistent models)์„ ๊ถŒ์žฅํ•˜๋Š”๋ฐ, ์ฒซ๋ฒˆ์งธ๋กœ OS๊ฐ€ ๋ฆฌ์†Œ์Šค๋ฅผ ํ™•๋ณดํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์•ฑ์„ ์ œ๊ฑฐํ•ด๋„ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ญ์ œ๋˜์ง€์•Š๋Š”๋‹ค. ์ด๊ฒƒ์€ ๋ฐฉ๊ธˆ ๋งํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ œ๊ฑฐ๋˜๋ฉด์„œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์ด ์ œ๊ฑฐ๋œ๋‹ค๋Š” ๊ฒƒ๊ณผ ์กฐ๊ธˆ ๋‹ค๋ฅธ๋ฐ, ์‚ฌ์šฉ ์ค‘์ด๋˜ ์ž„์‹œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด๊ณ  ์ด๊ฑธ ๋ณ„๋„์˜ ์ €์žฅ์†Œ์— ๋„ฃ์œผ๋ฉด ์•ฑ์„ ์ œ๊ฑฐํ•ด๋„ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ์•„์žˆ๊ฒŒ ๋œ๋‹ค. ๋‘๋ฒˆ์งธ๋กœ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ์œ ๋ฌด์— ์ƒ๊ด€ ์—†์ด ์•ฑ์ด ๋™์ž‘ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ๋„คํŠธ์›Œํฌ์— ์˜์กด์ ์ด๋ฉด ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋‹จ์ผ ์†Œ์Šค ์ €์žฅ์†Œ SSOT(Single source of truth)

์ƒˆ ๋ฐ์ดํ„ฐ๊ฐ€ ์ •์˜๋  ๋•Œ ์ด ๋ฐ์ดํ„ฐ๋ฅผ SSOT์— ํ• ๋‹นํ•ด์„œ SSOT๋งŒ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์•ผํ•œ๋‹ค. ์ด๊ฑธ ์œ„ํ•ด immutable type์œผ๋กœ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ฒŒ ํ•ด์•ผํ•œ๋‹ค. ๋‹จ์ผ ์†Œ์Šค๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ์„ ๋ฐฉ์ง€ํ•˜๊ณ  ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์‚ฌํ•ญ ์ถ”์ฒ™์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด ๋ฒ„๊ทธ ๋ฐœ๊ฒฌ์— ์šฉ์ดํ•˜๋‹ค.. ๋˜ ํŠน์ • ์œ ํ˜• ๋ฐ์ดํ„ฐ์˜ ๋ชจ๋“  ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ํ•œ๊ตฐ๋ฐ๋กœ ๋ชจ์€๋‹ค.

์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ์†Œ์Šค์— ํ•ด๋‹นํ•˜๋Š” ๊ฒƒ์œผ๋กœ๋Š” DB, ViewModel, UI ๋“ฑ์ด ์žˆ๋‹ค.

๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„ UDF(Unidirectional Data Flow)

๋ฌธ์„œ์—์„œ ์‹ฌ์‹ฌ์ฐฎ๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์šฉ์–ด๋‹ค. SSOT๊ฐ€ UDFํŒจํ„ด๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๊ธฐ๋„ ํ•œ๋‹ค. UDF์—์„œ ์ƒํƒœ(state)๋Š” ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ํ๋ฅธ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ํ๋ฆ„์ธ ์ด๋ฒคํŠธ(event)๋Š” ์ƒํƒœ์™€ ๋ฐ˜๋Œ€๋ฐฉํ–ฅ์œผ๋กœ ํ๋ฅธ๋‹ค. ๋ณดํ†ต ์ƒํƒœ๋‚˜ ๋ฐ์ดํ„ฐ๋Š” ์ƒ์œ„ ๋ฒ”์œ„์—์„œ ํ•˜์œ„ ๋ฒ”์œ„๋กœ ํ๋ฅธ๋‹ค. ์ด๋ฒคํŠธ๋Š” ํ•˜์œ„ ๋ฒ”์œ„์—์„œ ํŠธ๋ฆฌ๊ฑฐ๋ผ์„œ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ SSOT์— ๋„๋‹ฌํ•œ๋‹ค.

App Data -> UI, UI(ํ„ฐ์น˜์™€ ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ) -> SSOT์—์„œ ๋ฐ์ดํ„ฐ ์ˆ˜์ •

UDF๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ์ ์€ ์˜ค๋ฅ˜์™€ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค. ์ผ๊ด€์„ฑ์€ ๋””๋ฒ„๊ทธ๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ ๋‹ค.

MVVMํŒจํ„ด

MVVM์€ Model - View - ViewModel์˜ ์•ฝ์ž๋‹ค.

img

๋ทฐ๋Š” UI๋ฅผ ์ƒ๊ฐํ•˜๋ฉด ๋˜๊ณ , Model์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(๋ฐฑ์—”๋“œ ๋กœ์ง)์„ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์•ฑ์˜ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ, ์ €์žฅ, ๋ณ€๊ฒฝ ๋ฐฉ์‹ ๋“ฑ์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ทœ์น™์ด๋‹ค. ์ด ๋ทฐ์™€ ๋ชจ๋ธ์„ ๋ถ„๋ฆฌ์‹œํ‚ค๋ฉด ๋ทฐ๋ฅผ ์–ด๋Š ํŠน์ • ๋ชจ๋ธ์— ์ข…์†์‹œํ‚ค์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ๋ถ„๋ฆฌ์‹œํ‚ค๊ธฐ ์ „์—๋Š” ํŠน์ • ๋ชจ๋ธ์—๋Š” ํŠน์ • ๋ทฐ๊ฐ€ ์ข…์†๋˜์–ด์žˆ๋Š” ํ˜•ํƒœ๋‹ค. ๋ทฐ ๋ชจ๋ธ์€ ๋ชจ๋ธ์˜ ๋ฐ์ดํ„ฐ ๊ฐ์ฒด๋ฅผ ๋ทฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฐ’ ๋ณ€ํ™˜๊ธฐ๋‹ค. ๊ทธ๋ž˜์„œ ๋ทฐ ๋ชจ๋ธ์€ ๋ทฐ๋ณด๋‹ค ๋ชจ๋ธ์— ๊ฐ€๊น๊ณ  ๋ทฐ์˜ ๋””์Šคํ”Œ๋ ˆ์ด ๋กœ์ง ์ด์™ธ์˜ ๋Œ€๋ถ€๋ถ„ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. MVVM์€ ๋ชจ๋ธ - ๋ทฐ - ๋ฐ”์ธ๋”๋ผ๊ณ ๋„ ํ•˜๋Š”๋ฐ ์ด๊ฑด ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์ข€ ๋” ์‚ดํ”ผ๋ฉด์„œ ์•Œ์•„๋ณด๊ฒ ๋‹ค.

๋ชจ๋ธ Model

๋ชจ๋ธ์€ ์‹ค์ œ ์ƒํƒœ/๋ฐ์ดํ„ฐ ๋‚ด์šฉ์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต์„ ์ฐธ์กฐํ•œ๋‹ค. ๋ฐ์ดํ„ฐ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ ˆ์ด์–ด๋‹ค.

๋ทฐ View

๋ทฐ๋Š” UI์— ํ•ด๋‹นํ•œ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋Š” ๋ชจ๋“  ๊ฒƒ์„ ์ง€์นญํ•˜๋ฉฐ, ๋ชจ๋ธ์„ ๋ณด์—ฌ์„œ ํ‘œํ˜„ํ•˜๊ณ  ๋ทฐ์™€ ์‚ฌ์šฉ์ž ๊ฐ„์˜ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•ด์„œ ๋ทฐ-๋ทฐ๋ชจ๋ธ ์‚ฌ์ด์˜ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ํ†ตํ•ด ๋ทฐ๋ชจ๋ธ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

๋ทฐ ๋ชจ๋ธ ViewModel

MVVMํŒจํ„ด์˜ ํ•ต์‹ฌ์ด๋‹ค. MVC์—์„œ ์ปจํŠธ๋กค๋Ÿฌ, MVP์—์„œ ํ”„๋ฆฌ์  ํ„ฐ๋ฅผ ๋Œ€์‹ ํ•˜๋Š” ์—ญํ• ์ด๋ฉฐ ๋ชจ๋ธ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์ƒํƒœ๋ฅผ ๋ทฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฐ’ ๋ณ€ํ™˜๊ธฐ์ด๋‹ค. ํ”„๋ฆฌ์  ํ„ฐ์™€ ๋ทฐ๋ชจ๋ธ์˜ ์ฐจ์ด์ ์€ ๋ทฐ์— ๋Œ€ํ•œ ์ฐธ์กฐ ์œ ๋ฌด์ธ๋ฐ ๋ทฐ๋ชจ๋ธ์€ ๋ทฐ๋ฅผ ์ฐธ์กฐํ•˜์ง€์•Š๋Š”๋‹ค. ๊ฐ„์ ‘์—ฐ๊ฒฐ์ธ ์ฐธ์กฐ๊ฐ€ ์•„๋‹ˆ๋ผ, ์ง์ ‘ ๋ฐ”์ธ๋”ฉ์„ ํ•ด์„œ ์—…๋ฐ์ดํŠธ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ”์ธ๋”๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๋ฐ”์ธ๋”/์—ฐ๊ฒฐ์ž Binder

๋ฐ”์ธ๋”๋Š” ๋ทฐ๋ชจ๋ธ์— ์žˆ๋Š” ๋ทฐ์™€ ์—ฐ๊ฒฐ๋œ ์†์„ฑ๊ณผ ๋ทฐ ์‚ฌ์ด์˜ ํ†ต์‹ ์„ ๋‹ด๋‹นํ•œ๋‹ค. ๋ฐ”์ธ๋”๊ฐ€ ์žˆ์–ด์•ผ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ์„ ํ†ตํ•ด MVVMํŒจํ„ด์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ž‘๋™ ๋ฐฉ์‹

  1. View์—์„œ ์œ ์ €์™€ ์ด๋ฒคํŠธ ๋ฐœ์ƒ
  2. ViewModel์— ์žˆ๋Š” ์†์„ฑ๊ณผ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ์„ ํ†ตํ•ด ์ด๋ฒคํŠธ ์ „๋‹ฌ
  3. ViewModel์ด Model์—๊ฒŒ ๋ฐ์ดํ„ฐ ์š”์ฒญ
  4. Model์ด ViewModel์—๊ฒŒ ๋ฐ์ดํ„ฐ ์‘๋‹ต
  5. ViewModel์ด ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณต(View์— ์“ธ ์ˆ˜ ์žˆ๊ฒŒ)
  6. View ์—…๋ฐ์ดํŠธ

๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ํ†ตํ•ด์„œ MVP์— ์žˆ๋˜ View์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ์—†์•ด๋‹ค๊ณ  ์œ„์—์„œ ๋งํ–ˆ๋Š”๋ฐ, ๋ทฐ๋ชจ๋ธ์„ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ์ด์šฉํ•ด ํ•˜๋‚˜์˜ ํ•œ ๊ฐ€์ง€ ๋ทฐ ๋ชจ๋ธ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ทฐ๋ฅผ ๋ถ™์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 1๋Œ€1 ๊ด€๊ณ„์˜€๋˜ MVP์˜ View-Presenter์—์„œ ViewModel์ด 1์ธ 1:N ๊ด€๊ณ„๋กœ ๋ฐœ์ „ํ–ˆ๋‹ค.

์ฆ‰ MVVM์€ MVC๊ฐ€ ๊ฐ–๋Š” ์žฅ์ ์ธ ๊ธฐ๋Šฅ์š”์†Œ ๊ฐœ๋ฐœ์˜ ๋ถ„๋ฆฌ์™€ MVP์˜ ๋‹จ์ ์„ ์—†์• ์ค„ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ์„ ํ•ฉ์ณค๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋ฌธ์ œ๋Š” ๊ฐ ์š”์†Œ๊ฐ€ ๋…๋ฆฝ์ ์ด๋‹ค ๋ณด๋‹ˆ ์ด๊ฑธ ๋ถ„๋ฆฌํ•˜๋Š”๋ฐ ๋“œ๋Š” ๋น„์šฉ์ด ๋” ์ปค์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ๊ณผ ๊ทธ์— ๋”ฐ๋ผ ViewModel์˜ ์„ค๊ณ„๊ฐ€ ์–ด๋ ค์›Œ์ง„๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์ด์ œ MVVMํŒจํ„ด์˜ ์ •์˜๋ฅผ ํ•™์Šตํ–ˆ์œผ๋‹ˆ ์•ˆ๋“œ๋กœ์ด๋“œ ๊ณต์‹๋ฌธ์„œ์—์„œ ๋งํ•˜๋Š” ๊ถŒ์žฅ ์•ฑ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋ณด๊ฒ ๋‹ค.

๊ถŒ์žฅ ์•ฑ ์•„ํ‚คํ…์ฒ˜

img

์ผ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ ์›์น™์—์„œ ์–˜๊ธฐํ•˜๋Š” ๋ ˆ์ด์–ด๋Š” UI๋ ˆ์ด์–ด์™€ ๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด๋‹ค. ์—ฌ๊ธฐ์— ๋‘ ๋ ˆ์ด์–ด ๊ฐ„ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ฐ„์†Œํ™”ํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ, ์ฆ‰ ์˜์กด์„ฑ์„ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•œ ๋„๋ฉ”์ธ ๋ ˆ์ด์–ด๋ฅผ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ™”์‚ดํ‘œ๋Š” ์ข…์† ๊ด€๊ณ„๋‹ค. ๋„๋ฉ”์ธ ๋ ˆ์ด์–ด๊ฐ€ ๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด์— ์ข…์†๋œ๋‹ค๋Š” ์˜๋ฏธ๋‹ค.

UI ๋ ˆ์ด์–ด (ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ๋ ˆ์ด์–ด)

img

UI๋Š” UI elements์™€ State holders๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

UI elements๋Š” ํ™”๋ฉด์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” UI์š”์†Œ๋กœ MVVM์˜ View์™€ ๋น„์Šทํ•˜๊ณ , State holders๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์œ ํ•˜๊ณ  UI์— ๋ฟŒ๋ฆด ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด

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

๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด๋Š” SSOT, UDF๋ฅผ ์ค€์ˆ˜ํ•ด์•ผํ•œ๋‹ค.

๋„๋ฉ”์ธ ๋ ˆ์ด์–ด

๋„๋ฉ”์ธ ๋ ˆ์ด์–ด๋Š” ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด๋‚˜ ์—ฌ๋Ÿฌ ViewModel์—์„œ ์žฌ์‚ฌ์šฉ๋˜๋Š” ๊ฐ„๋‹จํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ์บก์Šํ™”๋ฅผ ๋‹ด๋‹นํ•œ๋‹ค. MVVMํŒจํ„ด ์กฐ๊ธˆ ์ˆ˜์›”ํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ ˆ์ด์–ด์ด๋‹ค. ๋„๋ฉ”์ธ ๋ ˆ์ด์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด

์ฝ”๋“œ ์ค‘๋ณต, ๊ฐ€๋…์„ฑ ๊ฐœ์„ , ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ, ์ฑ…์ž„๋ถ„ํ• (๋Œ€ํ˜• ํด๋ž˜์Šค ๋ฐฉ์ง€)

๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด์˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํด๋ž˜์Šค์— ์ข…์†๋˜์–ด ์ฝ”๋ฃจํ‹ด์„ ์‚ฌ์šฉํ•ด UI๋ ˆ์ด์–ด์™€ ํ†ต์‹ ํ•œ๋‹ค. ๋„๋ฉ”์ธ๋ ˆ์ด์–ด์˜ ํด๋ž˜์Šค๋Š” UseCase๋ผ๊ณ  ์ด๋ฆ„์ด ๋ถ™๋Š”๋ฐ ๊ฐ ํด๋ž˜์Šค๋‹น ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•ด์•ผํ•œ๋‹ค. ๋˜ํ•œ ๋„๋ฉ”์ธ ๋ ˆ์ด์–ด์˜ UseCase๋Š” main-safeํ•ด์•ผํ•˜๋ฏ€๋กœ ๋ฉ”์ธ์Šค๋ ˆ๋“œ์—์„œ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค. ๋งŒ์•ฝ UseCase ํด๋ž˜์Šค๊ฐ€ ์˜ค๋žซ๋™์•ˆ blocking operation์„ ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด(๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ˆ˜์‹ ๊ณผ ๊ฐ™์€), ์ ์ ˆํ•œ ์Šค๋ ˆ๋“œ๋กœ ๋กœ์ง์„ ์˜ฎ๊ธฐ๊ฒŒ ๋œ๋‹ค.

์˜ฎ๊ธฐ๊ธฐ ์ „์— ์ด๋ฏธ ๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด์—์„œ ๋ณต์žกํ•œ ์—ฐ์‚ฐ์ž‘์—…์„ ๋‹ด๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋Œ€์šฉ๋Ÿ‰ ๋ชฉ๋ก์„ ๋Œ€์ƒ์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•˜์—ฌ ์•ฑ ์—ฌ๋Ÿฌ ๋ทฐ์—์„œ ์žฌ์‚ฌ์šฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” ๋ฆฌ์†Œ์Šค ์ง‘์•ฝ์ ์ธ ์ž‘์—…์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด์— ๋ฐฐ์น˜๋œ๋‹ค.

/**
 * This use case fetches the latest news and the associated author.
 */
class GetLatestNewsWithAuthorsUseCase(
  private val newsRepository: NewsRepository,
  private val authorsRepository: AuthorsRepository,
  private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
    suspend operator fun invoke(): List<ArticleWithAuthor> =
        withContext(defaultDispatcher) {
            val news = newsRepository.fetchLatestNews()
            val result: MutableList<ArticleWithAuthor> = mutableListOf()
            // This is not parallelized, the use case is linearly slow.
            for (article in news) {
                // The repository exposes suspend functions
                val author = authorsRepository.getAuthor(article.authorId)
                result.add(ArticleWithAuthor(article, author))
            }
            result
        }
}

์˜ˆ์ œ ์ฝ”๋“œ์ธ๋ฐ ๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด์— ์กด์žฌํ•  Repository ๊ฐ์ฒด๋“ค์„ ๋ฐ›์•„์„œ ์ฝ”๋ฃจํ‹ด์ธ withContext๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค. Dispatcher๋ฅผ Default๋กœ ์ค˜์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋กœ ์˜ฎ๊ฒจ withContext๋กœ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์™€๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค.

withContext

withContext๋Š” ๋น„๋™๊ธฐ์ž‘์—…์„ ๋™๊ธฐ์ ์œผ๋กœ ์ž‘๋™ํ•˜๊ฒŒ ํ•˜๋Š” ๋ฌธ๋ฒ•์ด๋‹ค. withContext์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์‚ฌ์šฉํ•  ๋””์ŠคํŒจ์ฒ˜๋ฅผ ๋„ฃ๊ณ (์—ฌ๊ธฐ์„œ๋Š” Default๋‹ค), ํ•ด๋‹น ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—…์ด ๋๋‚˜๊ธฐ ์ „๊นŒ์ง€ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ˆ˜ํ–‰๋˜๋˜ ์ฝ”๋ฃจํ‹ด์„ ์ผ์‹œ์ค‘๋‹จํ•œ๋‹ค. ๋˜ ๋งˆ์ง€๋ง‰ ์ค„์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— return์ด ๋”ฐ๋กœ ์—†์–ด๋„ ์œ„ ์ฝ”๋“œ์—์„œ result๊ฐ€ invoke()์˜ return ๊ฐ’์ธ List<ArticleWithAuthor>์— ๋“ค์–ด๊ฐ„๋‹ค. ์ฆ‰ ๊ฒฐ๊ณผ๊ฐ’ ์ˆ˜์‹ ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ withContext๋ฅผ ์ด์šฉํ•ด ์ˆ˜์‹ ์„ ํ™•์‹คํžˆ ํ•˜๊ณ  ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.


 

์ฐธ์กฐ:

https://developer.android.com/topic/architecture?authuser=1&hl=ko#common-principles

๋ชจ๋ธ-๋ทฐ-๋ทฐ๋ชจ๋ธ - ์œ„ํ‚ค๋ฐฑ๊ณผ, ์šฐ๋ฆฌ ๋ชจ๋‘์˜ ๋ฐฑ๊ณผ์‚ฌ์ „

[๋””์ž์ธํŒจํ„ด] MVC, MVP, MVVM ๋น„๊ต

https://developer.android.com/jetpack/guide/domain-layer?authuser=1&hl=ko

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html

๋„์›€์ด ๋๋‹ค๋ฉด ๋Œ“๊ธ€์ด๋‚˜ ๊ณต๊ฐ ๋ฒ„ํŠผ ํ•œ ๋ฒˆ์”ฉ ๋ˆ„๋ฅด๊ณ  ๊ฐ€์ฃผ์„ธ์š”! ๋กœ๊ทธ์ธ ์•ˆํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค ^_^
๋ฐ˜์‘ํ˜•
COMMENT