[Android App Architecture] Intro

์žฅ์„ฑ์ค€ยท2023๋…„ 4์›” 8์ผ
0

Android App Architecture

๋ชฉ๋ก ๋ณด๊ธฐ
1/3
post-thumbnail

๐Ÿ’กํ•ด๋‹น ๊ธ€์€ ์•ฑ ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

์ข‹์€ ์•„ํ‚คํ…์ฒ˜๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”?

ํ•„์ž๋Š” ๋ณธ์ธ์˜ ์•ฑ์ด ํ•ด๊ฒฐํ•ด์•ผํ•˜๋Š” ๋ฌธ์ œ๋“ค์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์•„ํ‚คํ…์ฒ˜๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ ์ฝ”๋“œ๊ฐ€ ์–ด๋””์—์„œ/์–ด๋–ป๊ฒŒ ๋™์ž‘ ํ• ์ง€ ์ดํ•ดํ•˜๊ณ  ์˜ˆ์ธกํ•˜๊ธฐ ์‰ฌ์›Œ์•ผํ•˜์ฃ .

"์–ด๋–ป๊ฒŒํ•˜๋ฉด ์ข‹์€ ์•„ํ‚คํ…์ฒ˜๋กœ ์งค ์ˆ˜ ์žˆ์„๊นŒ?"๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋‹ค ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐœ๋…๋“ค์„ ์ ‘ํ•˜๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

  • Clean Architecture

    ๊ฐœ๋ฐœ์ž๋“ค์ด๋ผ๋ฉด ๋ชจ๋‘ ํ•œ๋ฒˆ์ฏค ๋ณธ ๊ทธ ๊ณผ๋…ํŒ.

  • MVVM (+Repository)

    MVC MVP MVI์™€ ํ•จ๊ป˜ ๋งŽ์ด ์“ฐ์ด๋Š” ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด

์ด๋Ÿฌํ•œ ๋‚ด์šฉ๋“ค์€ ์ž๋ฃŒ๊ฐ€ ๋ฐฉ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์—์„œ๋Š” ๋”ฐ๋กœ ์„ค๋ช…ํ•˜์ง€ ์•Š๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ๊ฐœ๋…๋“ค์„ ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ ์šฉํ•ดํ–ํ• ๊นŒ์š”?
์‚ฌ์‹ค ์ •๋‹ต์€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
ํšŒ์‚ฌ๋งˆ๋‹ค ์•ฑ์˜ ๊ธฐ๋Šฅ์ด ๋‹ค๋ฅด๊ณ  ๊ฐœ๋ฐœ์ž๋“ค์˜ ์ƒ๊ฐ์ด๋‚˜ ์Šคํƒ€์ผ๋„ ์ œ๊ฐ๊ฐ์ด๋‹ˆ๊นŒ์š”.

"๊ทธ๋ ‡๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์–ด๋–ป๊ฒŒ ๊ณต๋ถ€ํ•ด์•ผ ํ• ๊นŒ์š”?"

ํ•„์ž์˜ ๊ฒฝ์šฐ ์ด ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋‹ต์„ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ๊ธ€์€ ์•ˆ๋“œ๋กœ์ด๋“œ ๊ณต์‹๋ฌธ์„œ์˜ ์•ฑ ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ ๊ฐœ์š”๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.


ํ•ต์‹ฌ ์›์น™

๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ

Activity์™€ Fragment๋Š” ์ตœ๋Œ€ํ•œ ๊ฐ€๋ณ๊ฒŒ ์œ ์ง€ํ•ด์•ผํ•˜๋ฉฐ UI Logic๋งŒ์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ Context๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋ชจ๋‘ ์—ฌ๊ธฐ์—์„œ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • UI Logic : ํŠน์ • ์ด๋ฒคํŠธ๋‚˜ ์ƒํƒœ์— ๋”ฐ๋ผ UI๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์ค„์ง€์— ๋Œ€ํ•œ ๋กœ์ง

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

Room, DataStore์™€ ๊ฐ™์€ ๊ณณ์— ์ €์žฅ๋˜๋Š” ์ง€์†์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ UI๋ฅผ ๊ตฌ์„ฑํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•˜๋Š” ์ง€์†์ ์ธ ๋ฐ์ดํ„ฐ๋Š” ViewModel์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ(์ƒํƒœ๋ผ๊ณ  ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.)๊ฐ€ ์•„๋‹Œ ์•ฑ์„ ์ข…๋ฃŒํ•ด๋„ ์ €์žฅ๋˜๋Š” ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.

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

ํŠน์ • ์œ ํ˜• ๋ฐ์ดํ„ฐ์˜ ๋ชจ๋“  ๋ณ€๊ฒฝ์‚ฌํ•ญ์€ ํ•œ ๊ณณ์—์„œ ์ฒ˜๋ฆฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ๋ณธ์ธ์ด ์ง  ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„ ๋ฐ์ดํ„ฐ์˜ ๋ณ€๊ฒฝ์ด ์–ด๋””์—์„œ ์ผ์–ด๋‚ ์ง€ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

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

์ƒํƒœ : Repository -> ViewModel -> View ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ์ „๋‹ฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฒคํŠธ : View -> ViewModel -> Repository ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ์ „๋‹ฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ผ๊ด€์„ฑ์œผ๋กœ ์ธํ•ด ์ฝ”๋“œ๊ฐ€ ์–ด๋””์—์„œ/์–ด๋–ป๊ฒŒ ๋™์ž‘ ํ• ์ง€ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ๊ฒŒ๋ฉ๋‹ˆ๋‹ค.


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

UI Layer

์ƒํƒœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ UI๋ฅผ ํ‘œ์‹œํ•˜๋Š” ์˜์—ญ

์‚ฌ์šฉ์ž์™€์˜ ์ƒํ˜ธ์ž‘์šฉ(ex. ํด๋ฆญ ์ด๋ฒคํŠธ)๊ณผ ์ƒํƒœ ๋ณ€๊ฒฝ์— ๋”ฐ๋ผ UI๊ฐ€ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.
UI๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‘ ๊ฐ€์ง€๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • UI Elements : XML or Jetpack Compose, Activity, Fragment
  • State Holder : ViewModel

Activity์™€ Fragment๋Š” UI Logic์„ ์ฒ˜๋ฆฌํ• ๋•Œ UI Controller๋ผ๊ณ ๋„ ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค.
ViewModel์€ UI์— ์‚ฌ์šฉ๋  ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋กœ์ง์€ ํด๋ฆญ ์ด๋ฒคํŠธ์™€ ๊ฐ™์€ ์ƒํ™ฉ์— ์ˆ˜ํ–‰ํ•ด์•ผํ•  ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ ์ ˆํ•œ ์ €์žฅ์†Œ ํด๋ž˜์Šค์— ์œ„์ž„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ˜น์€ ์—ฌ๊ธฐ์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์„ค๊ณ„๋ฅผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ Repository๋Š” ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋“ค์„ ๋ชจ์•„๋†“์€ ์ €์žฅ์†Œ์˜ ์—ญํ™œ๋งŒ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Data Layer

Business Logic์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์˜์—ญ

  • Business Logic : ์ง€์†์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ• ์ง€์— ๋Œ€ํ•œ ๋กœ์ง

์•ฑ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๋ณ„๋กœ Repository๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
Repository๋Š” ํŒŒ์ผ, ๋„คํŠธ์›Œํฌ, ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๊ฐ™์€ DataSource๋“ค์„ ํ•œ ๊ณณ์œผ๋กœ ๋ชจ์•„ ๊ด€๋ฆฌํ•˜๋Š” ์ €์žฅ์†Œ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

Domain Layer

UI Layer์™€ Data Layer ์‚ฌ์ด์— ์žˆ๋Š” ์˜์—ญ

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

ํ•ด๋‹น ๋ ˆ์ด์–ด๋“ค์˜ ์ž์„ธํ•œ ์„ค๋ช…์€ ๋‹ค์Œ ๊ธ€์—์„œ ๋ถ€ํ„ฐ ์ˆœ์ฐจ์ ์œผ๋กœ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.

์˜์กด์„ฑ ์ฃผ์ž… (DI)

์˜์กด์„ฑ ์ฃผ์ž…์€ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์„œ๋น„์Šค ๋กœ์ผ€์ดํ„ฐ ํŒจํ„ด์œผ๋กœ ์ง์ ‘ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
Hilt Dagger Koin ๋“ฑ์ด ์žˆ์œผ๋ฉฐ ๊ณต์‹๋ฌธ์„œ์—์„œ๋Š” Hilt์˜ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ๊ถŒ์žฅ์‚ฌํ•ญ

์•„๋ž˜์˜ ๋ชฉ๋ก์€ ๊ณต์‹๋ฌธ์„œ์—์„œ ๊ถŒ์žฅํ•˜๋Š” ์‚ฌํ•ญ๋“ค์ž…๋‹ˆ๋‹ค.

  • ์ƒํƒœ๋Š” Activity์™€ Fragment๊ฐ€ ์•„๋‹Œ ViewModel์—์„œ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  • Activity์™€ Fragment๋Š” Context๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์œ ์ผํ•œ ํด๋ž˜์Šค์—ฌ์•ผ๋งŒํ•ฉ๋‹ˆ๋‹ค. (+ 4๋Œ€ ์ปดํฌ๋„ŒํŠธ)
  • ์ฑ…์ž„์ด ์ž˜ ์ •์˜๋œ ๊ฒฝ๊ณ„๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. (์–ด๋ ค์šธ ์ˆ˜๋„ ์žˆ๋Š” ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.)
    ex) ๋„คํŠธ์›Œํฌ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ฝ”๋“œ๋ฅผ ์—ฌ๋Ÿฌ ํด๋ž˜์Šค์— ๋ถ„์‚ฐ์‹œํ‚ค๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.
    ex) ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ด€๋ จ ์—†๋Š” ์ฑ…์ž„์„ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์— ์ •์˜ํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.
  • Jetpack ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๊ธฐํƒ€ ๊ถŒ์žฅ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋กํ•ฉ๋‹ˆ๋‹ค.
  • ์˜คํ”„๋ผ์ธ ์šฐ์„  ์•ฑ : ๊ฐ€๋Šฅํ•œํ•œ ์ตœ์‹ ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ์ปฌ์— ๋ณด์กดํ•ฉ๋‹ˆ๋‹ค.
    ์ด๋ ‡๊ฒŒํ•˜๋ฉด ๊ธฐ๊ธฐ๊ฐ€ ์˜คํ”„๋ผ์ธ์ผ ๋•Œ๋„ ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์˜ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ ํ•˜๋ฉด ์ข‹์€ ์ž๋ฃŒ

https://developer.android.com/topic/architecture?hl=ko
https://developer.android.com/courses/android-basics-kotlin/course
https://github.com/android/sunflower/tree/main
https://fastcampus.co.kr/dev_red_ksr

profile
Backend Engineer

0๊ฐœ์˜ ๋Œ“๊ธ€