#1 ๊ฐ๋ฐ ๋ชฉํ (Iteration Goal)
#1-1 ์ด์(Ideal)๊ณผ ์ง๊ฒ๋ค๋ฆฌ

์ด์(Ideal)
'์์ ๊ฒ์๊ธ'์์ ๋งํ๋ ๋ด์ฉ์ ์ถฉ์คํ๊ณ ์ข์ ๊ตฌํ์ด ๋ด๊ฐ ๋ฐ๋ผ๋ ์ด์์ด๋ค. ํ์ง๋ง ์ฑ์ ๋ง๋ค๋ค ๋ณด๋ฉด ๋ ๋ค๋ฅธ ํํ๋ก, ์กฐ๊ธ์ด๋ผ๋ ๋ณํ ๊ฑฐ๋ผ๋ ์ง๊ฐ์ด ๋ ๋ค. ๊ทธ๋์ ํ์์ ์ '์ด์'์ ๊ตฌ์ฒด์ ์ผ๋ก ์์ํ๋ ๊ฒ ์์ฒด๊ฐ ์๊ฐ ๋ญ๋น๋ผ๊ณ ์๊ฐํ๋ค. ๊ทธ๋ฟ๋ง ์๋๋ผ, ์คํ๋ ค ์ฒญ์ฌ์ง์ ๊ทธ๋ ค์ผ ํ๋ ์ง๊ธ ์์ ์์๋ ๋ฐฉํด๊ฐ ๋ ์๋ ์๋ค๋ ์๊ฐ๋ ๋ ๋ค. ์ง๊ธ์ '์์ฑ๋ ์ฑ์ ๋ชจ์ต'์ ๋ฏธ์ง์ x์ฒ๋ผ ์๊ฐํ๊ฒ ๋ค. x๊ฐ์ ๋ถ๋ช ์ข์ ๊ฐ์ ๊ฒ์ด๋ค.
์์ผ๋ก๋ ์ ๋ชฉ์ด "Iteration n"๊ณผ ๊ฐ์ ํ์์ ๋ธ๋ก๊ทธ ๊ฒ์๊ธ์์๋ '์ด์'์ ๋ช ์์ ์ผ๋ก ์ง๊ณ ๊ฐ ๊ฒ์ด๋ค. 'Top-down' ์ ์ผ๋ก๋ ์๊ฐํด์ผ 'Bottom-up'์ ์ ํํ๊ฒ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
Iteration 1: ๋ฉ๋ชจ ์ฑ์ ์ฒญ์ฌ์ง(๊ธฐ์ด)
์ฒ์์๋ Iteration 1์ ์ฃผ์ ๋ฅผ ๋ง์ฐํ "๋ฉ๋ชจ ์ฑ์ ๊ธฐ์ด"๋ก ์ก์๋ค. ๊ทธ๋ฌ๋ '๊ธฐ์ด'๋ผ๋ ๋จ์ด๋ ๋๋ฌด๋ ์ถ์์ ์ด๊ณ ๋ฒ์๊ฐ ๋๊ธฐ์, ์ด์ฐ ๋ณด๋ฉด ๊ต์ฅํ ๋ฌด์ฑ ์ํ ํํ์ด ๋ ์๋ ์๋ค. ๊ทธ๋์ ์ฝ๊ฐ ๋ ์ฃผ์ ๋ฅผ ๊ตฌ์ฒดํํด์, "๋ฉ๋ชจ ์ฑ์ ์ฒญ์ฌ์ง(๊ธฐ์ด)"์ผ๋ก ์ก์๋ค. ๋จ์ํ ์ด๋ค, ๋ฎ์(Low) ๋จ๊ณ์ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ค๋ ๊ฐ ์ ์ฒด์ ์ธ ๋ชจ๋ ๊ตฌ์ฑ์ ์ก๋๋ค๋๊ฐ ํ๋ ์์ด ์๋์ ๋ณด์ด๊ธฐ ์ํด์๋ค. '๋ผ๋' ๊ทธ์ค์์๋ 'ํต์ฌ ๋ผ๋', ๋ ์ ํํ๋ ๋ค๋ฅธ '๋ผ๋'๋ค์ ํ ๋๊ฐ ๋๋ ๋ผ๋๋ฅผ ๋ง๋ค ๊ฒ์ด๋ค. ์ด๋ค ๊ณ ๋ฏผ์ด๋ ๊ฐ์ง๊ณ ๋ ์ค์ฒด๊ฐ ์์ด์ผ ๋ฌธ์ ํด๊ฒฐ์ด ๋น ๋ฆฟ๋น ๋ฆฟํ๊ฒ ๋๋ค. ์์ผ๋ก ์ด๋ค ์ค๊ณ๋ฅผ ์ถ๊ฐํด ๋๊ฐ์ง ๊ณ ์ฌํ๊ธฐ ์ํ ํ(Plate)์ ๋ง๋ค์ด๋ณด๊ฒ ๋ค. ํ์คํ์ง๋ ์์ง๋ง, ์๋ง Iteration 2์ ์ฃผ์ ๋ "๋ฉ๋ชจ ์ฑ์ ๊ธฐ๋ณธ"์ด์ง ์์๊น?
#1-2 ๊ฐ๋ฐ ๋ฒ์
์ด๋ฒ ๊ฐ๋ฐ ๋ฒ์ (In Scope)
- ๋ฉ๋ชจ ์ถ๊ฐ ๊ธฐ๋ฅ (์ฌ์ฉ์๊ฐ ์ํ๋ ๋ฌธ์์ด์ ๋ฃ์ ์๋ ์๊ณ , ๊ทธ๋ฅ '๋ฉ๋ชจ ๊ฐ์ฒด'๋ง ์ถ๊ฐ)
- ๋ฉ๋ชจ ์ฝ๊ธฐ ๊ธฐ๋ฅ
- ๋ฉ๋ชจ ์นดํ ๊ณ ๋ฆฌ ์ฝ๊ธฐ ๊ธฐ๋ฅ (์๋ฅผ ๋ค๋ฉด ์นดํ ๊ณ ๋ฆฌ ๋ชฉ๋ก ๋ฆฌ์คํธ ๋ฑ)
- ๋ฉ๋ชจ ์นดํ ๊ณ ๋ฆฌ '์ ํ' ๊ธฐ๋ฅ (= ํน์ ๋ฉ๋ชจ ์นดํ ๊ณ ๋ฆฌ ์์ ๋ฉ๋ชจ๋ง ๋ชจ์ ์ฝ๋ ๊ธฐ๋ฅ)
- ์นดํ ๊ณ ๋ฆฌ ์ฝ๊ธฐ ๋ฐ ์ ํ์ ์ํ UI
- Compose ๊ธฐ๋ฐ UI
- Nutri Capture ์์ ์ ์ฝ๋ ์ค ํ Iteration์์ ๋น์ฅ ์ธ ๊ฒ ์๋๋ฉด (๋์ค์ ๋ค์ ์ถ๊ฐํ๋ ํ์ด ์๋๋ผ๋) ์ต๋ํ ์ ๊ฑฐ
๋ฒ์ ์ธ (Out of Scope)
- ๋ฐ์ดํฐ๋ฒ ์ด์ค (์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์ ๋ชฉ์ ์ผ๋ก๋ง ์งํ)
- ๋ฉ๋ชจ์ ๋ด์ฉ(์ด๋ค ๋ฌธ์์ด) ๋ฃ๊ธฐ
- ๋ฉ๋ชจ ์์
- ๋ฉ๋ชจ ์ญ์
- ๋ฉ๋ชจ ์นดํ ๊ณ ๋ฆฌ ์ถ๊ฐ (๋นํธ์ธ ๊ฐ๊ตฌ์ฒ๋ผ, ์ปดํ์ผ ๋จ๊ณ์์ ์นดํ ๊ณ ๋ฆฌ ํ๋ ์ฝ๋ฉํด์ ๋ฃ์ด์ค ๊ฒ์)
- ๋ค๋ฅธ ์นดํ ๊ณ ๋ฆฌ์ ๋ฉ๋ชจ ๋๊ฒจ์ฃผ๊ธฐ (์๋ฅผ ๋ค๋ฉด A ์นดํ ๊ณ ๋ฆฌ์์ ์์ฑํ ๋ฉ๋ชจ๋ฅผ B ์นดํ ๊ณ ๋ฆฌ๋ก ์ฎ๊ธฐ๊ธฐ)
- ๋ฉ๋ชจ ์ถ๊ฐ ์์ ์ ๋๋ฉ์ด์ (๊ธฐ๋ณธ ์ ๋๋ฉ์ด์ ์์ผ๋ฉด ๊ทธ๋๋ก๋ง ์ฌ์ฉ)
- ์นดํ ๊ณ ๋ฆฌ UI ์ฌ๋ซ์ ๋์ ์ ๋๋ฉ์ด์ (๊ธฐ๋ณธ ์ ๋๋ฉ์ด์ ์์ผ๋ฉด ๊ทธ๋๋ก๋ง ์ฌ์ฉ)
- ๊ธฐ๋ฅ ํ์ธ๋ง์ ์ํ ์ต์ UI ์ธ ๋ชจ๋ UI ์์
- 'Bubble' ๊ด๋ จ ์์
#2 ๋ณ๊ฒฝ ๋ด์ญ (์ปค๋ฐ ๋ชฉ๋ก)
#2-1 Iteration 1-1: ๊ธฐ์กด ์ฝ๋ ์ ๊ฑฐ

์์กด์ฑ ๊ทธ๋ํ๋ค. NutrientScreen()์ ํธ์ถํ๋ ์๋ฆฌ์ TestScreen()์ ๋์ ๋๋ค. TestScreen()์ ์๋ฆฌ๋ง ์ฐจ์งํ๊ฒ ๋๋, ์์ ์ปดํฌ๋ํธ์ ์ญํ ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ์ํ์์ ์ฑ ์คํ ๊ตฌ๋ ์ ์ฌ์ฉ๋์ง ์๋, '๊ฑฐ์' ๋ชจ๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๋ค. "ํน์๋ผ๋ ๋์ค์ ์ธ ์๋ ์์ง ์์๊น?"๋ผ๋ ์๊ฐ์ด ๋๋ ์ฝ๋๋ ์ญ์ ํ๋, "์ด๊ฑด ๋จธ์ง์์ ๋ฐ๋์ ์ด๋ค"๋ผ๋ ์๊ฐ์ด ๋๋ ์ฝ๋๋ ๋จ๊ฒผ๋ค. ์ญ์ ํ ์ฝ๋ ์ค ์ถํ ์ ๋ง๋ก ํ์ํ ์ฝ๋๊ฐ ์๋ค๋ฉด, ๊ทธ๋ ๊ฐ์ ๋ค์ ์ถ๊ฐํ๋ค.
๊ด๋ จ ๊ฐ๋ฐ ๋ฒ์
- Nutri Capture ์์ ์ ์ฝ๋ ์ค ํ Iteration์์ ๋น์ฅ ์ธ ๊ฒ ์๋๋ฉด (๋์ค์ ๋ค์ ์ถ๊ฐํ๋ ํ์ด ์๋๋ผ๋) ์ต๋ํ ์ ๊ฑฐ
์ฃผ์ ๋ณ๊ฒฝ์
- ๊ฑฐ์ ๋ชจ๋ ์ฝ๋ ์ ๊ฑฐ
- ์ฌ๋ฌ ์คํ์ ์ธ ์๋๋ค์ ์ํํ TestScreen() ์ปดํฌ๋ํธ ์์ฑ
์ฐธ๊ณ
#2-2 Iteration 1-2: Data entity์ Data access abstraction ์ถ๊ฐ

์ฒ์์๋ "์ผ๋จ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๋?"๋ผ๊ณ ๋ง์ฐํ ์๊ฐํ๋ค. ๊ทธ๋ฌ๋ ํ ๋จ๊ณ์์๋ ๋ถํ์ํ ๊ตฌํ์ด๋ผ๊ณ ํ๋จํ๋ค. ๊ทธ ๋์ , DIP ์์น์ ๊ณ ๋ คํด ๋จผ์ '์ ์ฑ '์ ํด๋นํ๋ 'MemoRepository'๋ฅผ ๋ง๋ค๊ธฐ๋ก ํ๋ค. ๊ทธ๋ฌ๋ ค๋ฉด Repository์์ ๋ค๋ฃฐ ๋ฐ์ดํฐ ํด๋์ค๊ฐ ํ์ํ๋ฏ๋ก Memo ํด๋์ค๋ ๋ง๋ค์๋ค.
app ๋ชจ๋์ด data ๋ชจ๋์ ์ฐธ์กฐํ ์ ์์ด์ผ ํ๋ฏ๋ก, build.gradle์
implementation(project(":data"))
๋ฅผ ์ถ๊ฐํด ์ฃผ์ด์ผ ํ๋๋ฐ, Now in Android์์๋
implementation(projects.data)
์ ๊ฐ์ ํํ๋ก ๋ชจ๋ ์์กด์ฑ ์ถ๊ฐ๋ฅผ ํ๊ณ ์์๋ค. ํ์์ ๋ฐฉ์์ Gradle์ Type-safe Project Accessors ๊ธฐ๋ฅ์ธ๋ฐ, ๋๋ ์ด๋ฒ ์ปค๋ฐ๋ถํฐ ์ ์ฉํ๋ค.
๊ด๋ จ ๊ฐ๋ฐ ๋ฒ์
- ๋ฉ๋ชจ ์ถ๊ฐ ๊ธฐ๋ฅ (์ฌ์ฉ์๊ฐ ์ํ๋ ๋ฌธ์์ด์ ๋ฃ์ ์๋ ์๊ณ , ๊ทธ๋ฅ '๋ฉ๋ชจ ๊ฐ์ฒด'๋ง ์ถ๊ฐ)
- ๋ฉ๋ชจ ์ฝ๊ธฐ ๊ธฐ๋ฅ
- Compose ๊ธฐ๋ฐ UI
์ฃผ์ ๋ณ๊ฒฝ์
- Data entity (Memo)์ Repository (MemoRepository) ์ถ๊ฐ
- FakeMemoRepository ์ถ๊ฐ ๋ฐ ์ด๋ฅผ ํ์ฉํด TestScreen()์ ์์ฃผ ๊ฐ๋จํ ํ ์คํธ UI ์์ฑ
- build.gradle์ Type-safe Project Accessors ๊ธฐ๋ฅ ์ ์ฉ
์คํฌ๋ฆฐ์ท

Flow ๊ฐ๋ ๋ณต์ต
@Composable
fun TestScreen() {
val repository: MemoRepository = remember { FakeMemoRepository() }
val memos by repository.getMemos().collectAsState(initial = emptyList())
val memosText = memos.joinToString("\n") { it.content }
Box(
modifier = Modifier
.fillMaxSize()
.clickable(
onClick = {
repository.insertMemo("Inserted memo")
}
),
contentAlignment = Alignment.Center
) {
Text(memosText)
}
}
Flow๋ ๋จ์ด ๊ทธ๋๋ก '๋ฐ์ดํฐ(๊ฐ)์ ํ๋ฆ'์ด๋ผ, ํ์ฌ ๊ฐ์ด๋ผ๋ ๊ฐ๋
์ด ์๋ค. ๋ฐ๋ฉด, UI(Jetpack Compose)๋ '์ง๊ธ' ๊ทธ๋ ค์ผ ํ ๊ฐ์ด ๋ฌด์์ธ์ง๋ฅผ ์์์ผ ํ๋ค. ๊ทธ๋์ ์์ ์ฝ๋์ฒ๋ผ Flow -> State๋ก ๋ณํํ๋ Flow.collectAsState()๋ฅผ ์จ์ผ ํ๋ค.
์ข ๋ ์ง์ฝ์ ์ธ ์ถ๊ฐ ์ค์ ์ ํ๋ ค๋ฉด, Flow -> StateFlow -> State๋ก ๋ณํํด์ผํ๋ค. StateFlow -> State๋ Flow.collectAsState()๋ฅผ ๋๊ฐ์ด ์ฐ๋ฉด ๋๊ณ , Flow -> StateFlow ๋ณํ์ Flow.stateIn()์ ์ฐ๋ฉด ๋๋ค. stateIn()์ Flow์ ์๋ช
์ ์ฝ๋ฃจํด๊ณผ ๋๊ธฐํ์ํฌ ์ ์๋ scope ๋งค๊ฐ๋ณ์์ Flow์ collect๋ฅผ ์ธ์ ์์ํ๊ณ ์ธ์ ๋ฉ์ถ ๊ฒ์ธ์ง๋ฅผ ์ ํ๋ started ๋งค๊ฐ๋ณ์๋ฅผ ๋ณด์ ํ๋ค.
2026-01-15 ์์
Repository์์ ๋ฐํํด์ผ ํ๋ ๊ฑด Data entity๊ฐ ์๋๋ผ, Domain model์ด๋ค. ๋ฐ๋ผ์ ์ฌ๊ธฐ์ ๋ค๋ฃฌ ๊ฑด ์ฌ์ค Domain model์ด๋ค. ์ด๋ฐ ๊นจ์ ๊ฐ์ ์ฉ์ด ๊ฐ์ง๊ณ ์ด๋ฌ๋ ๊ฑธ๋ก, ์ค์ค๋ก ์ชผ์ํ๋ค๋ ์๊ฐ๋ ์กฐ๊ธ ๋ ๋ค. ๋ค๋ง ์ฌ์ํ๋ค๋ ์ด์ ๋ก, ๋๊ฒจ์ง๋ฏ์ด ์ค๋ฅด๋ฅต ๋น ์ ธ๋๊ฐ๋ค ๋ณด๋ฉด ๋์ค์ ํํผํ(?) ๊ฐ๋ฐ์๊ฐ ๋์ด ๋ฒ๋ฆด์ง๋ ๋ชจ๋ฅธ๋ค.
์ฐธ๊ณ
- [GitHub] ์ด ์์ ์ Commit
- [Tistory] [Gradle] Type-safe Project Accessors ๋์ ๋ฐฐ๊ฒฝ ๋ฐ ์ฌ์ฉ๋ฒ
- [Tistory] Unit Testing - Test double
- [Wikipedia] Entity–relationship model
#2-3 Iteration 1-3: ์ฒญ์ฌ์ง์ ์ํ ์ต์ UI

'๋ฉ๋ด ๋ฐ'๋ฅผ ๊ตฌํํ๋ค. ์๋ํ๋ฉด ๊ฐ๋ฐ ๋ฒ์์ ์๋ '๋ฉ๋ชจ ์นดํ ๊ณ ๋ฆฌ ์ฝ๊ธฐ ๊ธฐ๋ฅ' ๊ตฌํ์ ์ํด ์นดํ ๊ณ ๋ฆฌ ๋ฆฌ์คํธ๋ฅผ ๋ ์ฅ์๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ฒ์์๋ ๋ฉ๋ด ๋ฐ๊ฐ ์์ UI๋ก๋ ๋ถ์ ํฉํ๋ค๊ณ ํ๋จํ๋ค. ๋ฉ๋ด ๋ฐ ๊ตฌํ์ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋, Jetpack Compose์ ๊ธฐ๋ณธ ์ ๊ณต๋๋ ModalNavigationDrawer์ ์กด์ฌ๋ฅผ ์์๋ค. ์ด๋ฅผ ์ด์ฉํด ์ฝ๊ณ ๋น ๋ฅด๊ฒ ๊ตฌํํ ์ ์์๋ค.
๊ด๋ จ ๊ฐ๋ฐ ๋ฒ์
- ์นดํ ๊ณ ๋ฆฌ ์ฝ๊ธฐ ๋ฐ ์ ํ์ ์ํ UI
- Compose ๊ธฐ๋ฐ UI
์ฃผ์ ๋ณ๊ฒฝ์
- :feature:test ๋ชจ๋ ๋ง๋ค๊ณ ํด๋น ๋ชจ๋๋ก TestScreen() ์ฎ๊น
- ModalNavigationDrawer๋ฅผ ์ด์ฉํด TestScreen()์ '๋ฉ๋ด ๋ฐ' ์ถ๊ฐ
์คํฌ๋ฆฐ์ท

TestScreen()์ ๊ตฌ์กฐ
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TestScreen() {
...
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
...
}
) {
...
Column(
modifier = Modifier.fillMaxSize()
) {
TopAppBar(
...
navigationIcon = {
IconButton(
...
},
actions = {
IconButton(
...
}
)
Text(
text = memosText,
modifier = Modifier.fillMaxWidth()
)
}
}
}
ModalNavigationDrawer๋ ํ์ํ ์ปดํฌ๋ํธ์ '์์ฐ๋ฏ์ด' ์ฌ์ฉํ๋ฉด ๋๋ค. ์ง๊ธ์ Column์ ์์ ์ง๋ง, ๋์ค์๋ ์๋ง Scaffold์ ์์ฐ์ง ์์๊น?
์ฐธ๊ณ
- [GitHub] ์ด ์์ ์ Commit
- [Android Developers] Navigation drawer | Jetpack Compose
- [Material Design] Navigation drawer
#2-4 Iteration 1-4: Fake Catetory ๋ฐ ์ํธ์์ฉ

#2-2์ ์ ์ฌํ ๋ฐฉ์์ผ๋ก, Category๋ผ๋ Data entity๋ฅผ ์ถ๊ฐํ๋ค. ์ด์ ๋ง์ถฐ MemeRository์ Memo ํด๋์ค๋ฅผ ์์ ํ๋ค. ๋ง์ง๋ง์ผ๋ก ์ฌ์ฉ์๊ฐ (UI์์) ์นดํ ๊ณ ๋ฆฌ์ ์ํธ์์ฉ์ ํ ์ ์๊ฒ ํ๋ค.
๊ด๋ จ ๊ฐ๋ฐ ๋ฒ์
- ๋ฉ๋ชจ ์นดํ ๊ณ ๋ฆฌ ์ฝ๊ธฐ ๊ธฐ๋ฅ (์๋ฅผ ๋ค๋ฉด ์นดํ ๊ณ ๋ฆฌ ๋ชฉ๋ก ๋ฆฌ์คํธ ๋ฑ)
- ๋ฉ๋ชจ ์นดํ ๊ณ ๋ฆฌ '์ ํ' ๊ธฐ๋ฅ (= ํน์ ๋ฉ๋ชจ ์นดํ ๊ณ ๋ฆฌ ์์ ๋ฉ๋ชจ๋ง ๋ชจ์ ์ฝ๋ ๊ธฐ๋ฅ)
์ฃผ์ ๋ณ๊ฒฝ์
- Data entity (Category) ์ถ๊ฐ
- data class์ธ Memo์ ์นดํ ๊ณ ๋ฆฌ ํ์๋ฅผ ์ํ ํ๋กํผํฐ("categoryName") ์ถ๊ฐ
- MemoRepository์ ๋ฉ์๋๋ค์ด ์นดํ ๊ณ ๋ฆฌ ๊ฐ๋ ์ ํฌํจํ๋๋ก ์ ๋ฐ์ดํธ
- TestScreen() ์ '๋ฉ๋ด ๋ฐ'(#2-3)์ ์นดํ ๊ณ ๋ฆฌ ๋ชฉ๋ก์ ํ์, ์นดํ ๊ณ ๋ฆฌ์ ๊ฐ ํญ๋ชฉ ํด๋ฆญ ์ ํด๋น ํญ๋ชฉ์ ์ํ๋ ๋ฉ๋ชจ๋ง ํ์
์คํฌ๋ฆฐ์ท

#2-3์ ์๋ ์คํฌ๋ฆฐ์ท๊ณผ ๋น๊ตํ๋ฉด TopAppBar()์ ์์ด ๋ค๋ฅธ๋ฐ, #2-3์ ๋คํฌ ๋ชจ๋์ผ ๋ ์คํฌ๋ฆฐ์ท์ ์ฐ์๊ณ ์ฌ๊ธฐ์๋ ๋ผ์ดํธ ๋ชจ๋์ผ ๋ ์ฐ์๊ธฐ ๋๋ฌธ์ด๋ค. ์์ผ๋ก๋ ๋ชจ๋์ ์ผ๊ด์ฑ์ ์ง์ผ์ ์คํฌ๋ฆฐ์ท์ ์ฐ์ด์ผ๊ฒ ๋ค.
์นดํ ๊ณ ๋ฆฌ๋ณ ๋ฉ๋ชจ ๋ฐ์ดํฐ ์กฐํ (FakeMemoRepository)
package com.example.data
...
class FakeMemoRepository : MemoRepository {
private val categoriesFlow = MutableStateFlow<List<Category>>(
...
)
private val memosFlow = MutableStateFlow<List<Memo>>(
listOf(
Memo(content = "Fake memo 1 (category 1)", categoryName = "category 1"),
Memo(content = "Fake memo 2 (category 1)", categoryName = "category 1"),
Memo(content = "Fake memo 3 (category 2)", categoryName = "category 2"),
Memo(content = "Fake memo 4 (category 2)", categoryName = "category 2"),
Memo(content = "Fake memo 5 (category 3)", categoryName = "category 3"),
Memo(content = "Fake memo 6 (category 3)", categoryName = "category 3"),
)
)
...
override fun getMemosByCategory(categoryName: String?): Flow<List<Memo>> {
return memosFlow.map { memos ->
if (categoryName == null) {
memos
} else {
memos.filter { it.categoryName == categoryName }
}
}
}
...
}
Test double์์ ์นดํ ๊ณ ๋ฆฌ๋ณ ๋ฉ๋ชจ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋.
์ฐธ๊ณ
'๊ฐ๋ฐ ์ผ์ง ๐ป > Swemo' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Swemo - Iteration 2: UI ๋์์ธ ๋ฐฉํฅ ํ์(Exploration) (0) | 2026.01.13 |
|---|---|
| Swemo - Nutri Capture ๊ฒ์๊ธ ์๋ฆฌ์ฆ๋ก ์ด๋ (0) | 2025.12.09 |
| Nutri Capture - Swemo ๊ฒ์๊ธ ์๋ฆฌ์ฆ๋ก ์ด๋ (0) | 2025.12.09 |
| Nutri Capture - ๋ฐฉํฅ ์ฌ์ค๊ณ (ํ๋ก์ ํธ ์ด๋ฆ ๋ณ๊ฒฝ) (0) | 2025.12.02 |
| Nutri Capture - ๋ฒ์ ์นดํ๋ก๊ทธ ์ ํ๋กํผํฐ๋ช ์ Now in Android ์คํ์ผ๋ก ํต์ผ (0) | 2025.10.31 |