An open API service indexing awesome lists of open source software.

https://github.com/sagehabitus/pagingcomposemviapp


https://github.com/sagehabitus/pagingcomposemviapp

coroutine flow kotlin mvi-clean-architecture mvi-coroutines-flow-kotlin paging3 room-database stateflow-android viewmodel

Last synced: 11 days ago
JSON representation

Awesome Lists containing this project

README

          

### ๐Ÿ“š ์ฑ… ๊ฒ€์ƒ‰ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ (Jetpack Compose with Advanced MVI Concepts)

๋ณธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ๊ฐ€ ๋งŽ์ง€๋งŒ ์˜๋„ํ•œ ๊ฒƒ์ž„์„ ์•Œ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค. **Paging 3**์™€ **Room**, **Retrofit** ๋“ฑ์˜ ์ตœ์‹  ์•ˆ๋“œ๋กœ์ด๋“œ ๊ธฐ์ˆ  ์Šคํƒ์„ ํ™œ์šฉํ•˜์—ฌ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ์˜คํ”„๋ผ์ธ ์ €์žฅ์†Œ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋ณธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํšจ์œจ์ ์ด๊ณ  ์ผ๊ด€๋œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ๊ณ  ์ตœ๋Œ€ํ•œ ๊ตฌ๊ธ€์•„ํ‚คํ…์ณ๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.

## ์ƒ๋žตยท๋ณ‘ํ•ฉ ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„
**DataSource, UseCase ์ƒ๋žต๊ฐ€๋Šฅ, DomainModel, PresentationModel ์ƒ๋žต ๊ฐ€๋Šฅ, UiState ๋ณ‘ํ•ฉ ๊ฐ€๋Šฅ**

## ์ฃผ์š” ๊ธฐ๋Šฅ โœจ

- **์‹ค์‹œ๊ฐ„ API ํ†ต์‹  ๐ŸŒ**: ์นด์นด์˜คํ†ก API ๋˜๋Š” ๋„ค์ด๋ฒ„ API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์š”์ฒญ์— ๋”ฐ๋ผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฑ… ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. Retrofit๊ณผ OkHttp๋ฅผ ํ†ตํ•ด ์•ˆ์ •์ ์ธ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

- **MVI ์•„ํ‚คํ…์ฒ˜ ๐Ÿง **: MVI ํŒจํ„ด์„ ํ†ตํ•ด ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ(Intent)๋ฅผ ์ค‘์•™์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ UI ์ƒํƒœ(State)๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด UI์— ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. MVI์˜ ํ•ต์‹ฌ ๊ตฌ์„ฑ ์š”์†Œ์ธ **PartialStateChange**, **Intent**, **Event**, **State**๋Š” ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๊ณ , ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜์˜ ๋ช…ํ™•ํ•œ ํ๋ฆ„์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

- **๋กœ์ปฌ ๋ฐ์ดํ„ฐ ์บ์‹ฑ ๐Ÿ **: Room์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒ€์ƒ‰๋œ ์ฑ… ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ์ปฌ์— ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ๋Š๊ฒจ๋„ ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

- **ํšจ์œจ์ ์ธ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ๐Ÿ”„**: Paging 3 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ํŽ˜์ด์ง€ ๋‹จ์œ„๋กœ ๋กœ๋“œํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค. Jetpack Compose์™€ ํ†ตํ•ฉ๋˜์–ด ๋ฌดํ•œ ์Šคํฌ๋กค, ๋ฐ์ดํ„ฐ ๊ฐฑ์‹  ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

- **Jetpack Compose UI ๐Ÿ“ฑ**: ์„ ์–ธ์  UI ํ”„๋ ˆ์ž„์›Œํฌ์ธ Jetpack Compose๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Android UI๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ณ , UI ์—…๋ฐ์ดํŠธ์˜ ๋ณต์žก์„ฑ์„ ์ค„์ž…๋‹ˆ๋‹ค.

- **CI ์ž๋™ํ™” ๐Ÿš€**: GitHub Actions๋ฅผ ํ™œ์šฉํ•ด Pull Request ์‹œ ์ž๋™ ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

## ๊ธฐ์ˆ  ์Šคํƒ ๐Ÿ› ๏ธ

- **์–ธ์–ด**: Kotlin
- **UI**: Jetpack Compose
- **๋„คํŠธ์›Œํฌ ํ†ต์‹ **: Retrofit, OkHttp, Corouitne, Flow
- **๋น„๋™๊ธฐ ์ž‘์—…**: Corouitne, Flow, StateFlow, SharedFlow
- **JSON ํŒŒ์‹ฑ**: Kotlin Serialization, Parcelable
- **๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค**: Room
- **์ด๋ฏธ์ง€ ๋กœ๋”ฉ**: Coil
- **์˜์กด์„ฑ ์ฃผ์ž…**: Hilt
- **ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ**: Paging 3 (+RemoteMediator)
- **ํ…Œ์ŠคํŠธ**: JUnit, Espresso, Mokito, Compose UI Test
- **CI**: GitHub Actions

## MVI ์•„ํ‚คํ…์ฒ˜์˜ ์žฅ์  ๋ฐ MVVM์˜ ํ•œ๊ณ„ ๐Ÿš€

### MVVM์˜ ํ•œ๊ณ„
**MVVM (Model-View-ViewModel)** ์•„ํ‚คํ…์ฒ˜๋Š” Android ๊ฐœ๋ฐœ์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํŒจํ„ด์ด์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ํ•œ๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค:
- **์ƒํƒœ ๊ด€๋ฆฌ์˜ ๋ณต์žก์„ฑ**: ViewModel์ด ๋„ˆ๋ฌด ๋งŽ์€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋˜๋ฉด์„œ ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- **UI์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ**: View์™€ ViewModel ๊ฐ„์˜ ์ƒํ˜ธ์ž‘์šฉ์ด ๋ณต์žกํ•ด์ง€๋ฉด, ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- **๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ์˜ ์–ด๋ ค์›€**: ํŠนํžˆ ๋น„๋™๊ธฐ ์ž‘์—…์„ ๋‹ค๋ฃฐ ๋•Œ, ์ƒํƒœ ์ „์ด๋ฅผ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ๊ด€๋ฆฌํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

### MVI์˜ ์žฅ์ 
MVI๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:
- **๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„**: ์ƒํƒœ ๋ณ€ํ™”๊ฐ€ ๋ช…ํ™•ํ•˜๊ฒŒ Intent โ†’ State โ†’ UI๋กœ ํ๋ฅด๋ฏ€๋กœ ๋””๋ฒ„๊น…์ด ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.
- **์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ƒํƒœ ๊ด€๋ฆฌ**: ๋ชจ๋“  ์ƒํƒœ ๋ณ€๊ฒฝ์ด ๋ช…์‹œ์ ์ธ Intent์— ์˜ํ•ด ์ด๋ฃจ์–ด์ง€๋ฉฐ, ์ค‘๊ฐ„ ์ƒํƒœ(PartialStateChange)๋ฅผ ํ†ตํ•ด ์ƒํƒœ ๋ณ€ํ™”์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- **๊ณ ๋ฆฝ๋œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง**: ์ƒํƒœ ๊ด€๋ฆฌ์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋ถ„๋ฆฌ๋˜๋ฏ€๋กœ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง‘๋‹ˆ๋‹ค.
- **์˜๋„ ๊ธฐ๋ฐ˜ ์ƒํ˜ธ์ž‘์šฉ**: ์‚ฌ์šฉ์ž์˜ ์•ก์…˜(Intent)์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ UI๋ฅผ ๊ฐฑ์‹ ํ•˜๋ฏ€๋กœ, UI์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ์˜๋„๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

## ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ๐Ÿ—‚๏ธ

์ด ํ”„๋กœ์ ํŠธ๋Š” **Google Architecture** ์›์น™์„ ์ค€์ˆ˜ํ•˜๋ฉฐ, `core`, `data`, `domain`, `presentation`์˜ ๋„ค ๊ฐ€์ง€ ๋ชจ๋“ˆ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

### **๋ชจ๋“ˆ๋ณ„ ์„ค๋ช…**

- **core**: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์—ญ ์„ค์ • ๋ฐ ์ดˆ๊ธฐํ™”๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. `ComposeMVIApplication.kt` ํŒŒ์ผ์€ Hilt๋ฅผ ์‚ฌ์šฉํ•œ ์˜์กด์„ฑ ์ฃผ์ž…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

- **data**: ๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด๋กœ, API ํ˜ธ์ถœ, ๋กœ์ปฌ DB ๊ด€๋ฆฌ, ๋ฐ์ดํ„ฐ ๋งคํ•‘ ๋ฐ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ์™€ ๊ด€๋ จ๋œ ๋ชจ๋“  ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. Repository ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ Domain ๋ ˆ์ด์–ด์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค.

- **domain**: ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํฌํ•จํ•˜๋ฉฐ, Use Case๋ฅผ ํ†ตํ•ด Presentation ๋ ˆ์ด์–ด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์˜ ๋ณต์žก์„ฑ์„ ์ˆจ๊ธฐ๊ณ , ๋‹จ์ˆœํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

- **presentation**: UI๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, Jetpack Compose๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. MVI ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜์—ฌ UI ์ƒํƒœ์™€ ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ ๊ฐ„์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

## CI ๋ฐ ํ…Œ์ŠคํŠธ ๐Ÿงช

- **GitHub Actions**: PR ์ƒ์„ฑ ์‹œ ์ž๋™ ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ ์ฝ”๋“œ ํ’ˆ์งˆ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
- **Compose UI Test**: Jetpack Compose๋กœ ์ž‘์„ฑ๋œ UI์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
- **JUnit ๋ฐ Espresso**: ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ฐ UI ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.