์๋๋ก์ด๋ ์ฑ์ ๋ง๋ค๋ค ๋ณด๋ฉด UI ์ํ(UI state)๋ฅผ ์ด๋ป๊ฒ ๊ด๋ฆฌํ ์ง ๊ณ ๋ฏผ์ด ๋ง์์ง๋ค. ํนํ ์ํ๋ฅผ ์ด๋์ ๋ง๋ค๊ณ , ๋๊ฐ ์ฑ ์์ง๊ณ , ์ด๋ป๊ฒ UI์ ์ฐ๊ฒฐํ ์ง๊ฐ ์ค์ํ๋ค.
UI ์ํ๋?
์ฑ ํ๋ฉด(UI)์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐ์ดํฐ์ ๋ฐ๋ผ ๋ฐ๋๋ค. ์๋ฅผ ๋ค์ด ๋ก๋ฉ ์ค์ผ ๋๋ ์คํผ๋๊ฐ ๋๊ณ , ๋ฐ์ดํฐ๊ฐ ๋ก๋๋๋ฉด ๋ฆฌ์คํธ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ , ์๋ฌ๊ฐ ๋๋ฉด ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ์์ด๋ค.
์ด์ฒ๋ผ ํ๋ฉด์ ๊ตฌ์ฑํ๋ ๋ฐ ํ์ํ ๋ฐ์ดํฐ๋ฅผ UI ์ํ(UI State)๋ผ๊ณ ๋ถ๋ฅธ๋ค. ๋ณดํต ๋ค์ ์ธ ๊ฐ์ง ์ํ๊ฐ ์๋ค.
- ๋ก๋ฉ ์ํ (Loading)
- ์ฑ๊ณต ์ํ (Success)
- ์๋ฌ ์ํ (Error)
๊ทธ๋ฆฌ๊ณ ์ด ์ํ๋ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ(Unidirectional Data Flow) ์์์ ๊ด๋ฆฌ๋์ด์ผ ํ๋ค. ์ฆ, ๋ฐ์ดํฐ๋ ํ ๋ฐฉํฅ์ผ๋ก๋ง ํ๋ฌ๊ฐ์ผ ์์ธก ๊ฐ๋ฅํ๊ณ ๋ฒ๊ทธ๊ฐ ์ค์ด๋ ๋ค.
UI ์ํ๋ฅผ ์ด๋์ ๋ง๋ค์ด์ผ ํ ๊น?
์ํ๋ฅผ ๋ง๋๋ ๊ณณ์ UI ์ํ์ ์์ฐ์ง(state producer)๋ผ๊ณ ํ๋ค. ๋ณดํต ์ธ ๊ฐ์ง ์์น ์ค ํ๋์์ ์ํ๊ฐ ๋ง๋ค์ด์ง๋ค.
1. UI ์์ฒด์์ ๋ง๋๋ ๊ฒฝ์ฐ (View/UI State as Source of Truth)
์ด ๊ฒฝ์ฐ์๋ UI ์ปดํฌ๋ํธ(์: Fragment, Activity, Compose ๋ฑ)๊ฐ ์ง์ ์ํ๋ฅผ ๋ง๋ ๋ค. ์๋ฅผ ๋ค์ด remember { mutableStateOf(...) }๋ LiveData๋ฅผ UI์์ ์ ์ธํ๋ ๋ฐฉ์์ด๋ค.
์ด ๋ฐฉ์์ ๋จ์ํ ํ๋ฉด์์๋ ๊ด์ฐฎ์ง๋ง, ๋ก์ง์ด ๋ณต์กํด์ง๋ฉด ๋ฌธ์ ๊ฐ ๋ง์์ง๋ค.
๋ฌธ์ ์ :
- ์ํ๊ฐ UI์ ๋ฌถ์ฌ ์์ด ์ฌ์ฌ์ฉ์ด๋ ํ ์คํธ๊ฐ ์ด๋ ค์
- ํ๋ฉด ํ์ ๋ฑ ์๋ช ์ฃผ๊ธฐ ๋ณํ์ ์ทจ์ฝ
- ์ฌ๋ฌ UI์์ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๊ธฐ ์ด๋ ค์
์ธ์ ๊ด์ฐฎ์๊น?
- ๋งค์ฐ ๋จ์ํ UI
- ์ผํ์ฑ ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฑ
2. ViewModel์์ ์ํ๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ (Recommended)
๊ฐ์ฅ ๊ถ์ฅ๋๋ ๋ฐฉ์์ด๋ค. ์ํ๋ฅผ ViewModel์์ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ฉด์ UI๋ ์ด๋ฅผ ๊ตฌ๋ ๋ง ํ๋ค. ์๋ฅผ ๋ค์ด
val uiState: StateFlow<UiState> = _uiState
ViewModel์ด StateFlow๋ LiveData ๋ฑ์ ํตํด UI ์ํ๋ฅผ ๋ง๋ค์ด ๋ด๊ณ , UI๋ ์ด๋ฅผ collectAsState() ํน์ observe() ๋ฑ์ผ๋ก ๊ฐ์งํด์ ํ๋ฉด์ ๊ฐฑ์ ํ๋ค.
์ฅ์ :
- ViewModel์ ์๋ช ์ฃผ๊ธฐ์ ๋ ๋ฆฝ์ ์ด๊ธฐ ๋๋ฌธ์ UI๊ฐ ์ฌ์์ฑ๋์ด๋ ์ํ ์ ์ง ๊ฐ๋ฅ
- ํ ์คํธ์ ์ ์ง๋ณด์์ ์ ๋ฆฌ
- ๋ณต์กํ UI ๋ก์ง๋ ๊น๋ํ๊ฒ ๋ถ๋ฆฌ ๊ฐ๋ฅ
3. Repository ๋๋ Domain Layer์์ ๋ง๋๋ ๊ฒฝ์ฐ
์ผ๋ถ ์ฑ์์๋ ์ํ๋ฅผ Repository์์ ๋ง๋๋ ๊ฒฝ์ฐ๋ ์๋ค. ์๋ฅผ ๋ค์ด ์๋ฒ ํต์ ๊ฒฐ๊ณผ๋ฅผ Resource<Success, Error, Loading> ๋ฑ์ ํํ๋ก ๋ด๋ณด๋ด๋ ๋ฐฉ์์ด๋ค.
ํ์ง๋ง Repository๋ ๋ฐ์ดํฐ ์์ค์ ์ง์ค๋ ์์ค(Source of Truth)๊ฐ ๋์ด์ผ์ง, UI ์ํ์ ์์ฐ์ง๊ฐ ๋์ด์ ์ ๋๋ค.
์๋ํ๋ฉด UI ์ํ๋ UI์ ๋ฐ์ ํ๊ฒ ์ฐ๊ด๋์ด ์์ด์, ์ฑ์ UI ์ ์ฑ ์ ๋ฐ๋ผ ์ํ ๊ตฌ์กฐ๊ฐ ๋ฌ๋ผ์ง ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ฅผ ๋ค์ด ๋ก๋ฉ ์ํ๋ฅผ UI์์๋ง ๋ณด์ฌ์ค์ง, ์ฌ๋ฌ ์ข ๋ฅ๋ก ๊ตฌ๋ถํ ์ง ๋ฑ์ UI ์ค๊ณ์ ๋ฌธ์ ๋ค.
Repository๋ ๋๋ฉ์ธ ๋ฐ์ดํฐ๋ง ๊ด๋ฆฌํ๊ณ , UI ์ํ๋ ViewModel์์ ์์ฐํด์ผํ๋ค.
UI ์ํ๋ฅผ ์ด๋ป๊ฒ ํํํ ๊น?
๋ณดํต UI ์ํ๋ sealed class๋ data class๋ก ํํํ๋ค. ์๋ฅผ ๋ค์ด:
sealed interface UiState {
object Loading : UiState
data class Success(val data: List<Item>) : UiState
data class Error(val message: String) : UiState
}
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ ์ํ๋ณ๋ก ๋ถ๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์ด ์์ ํ๊ณ ๋ช ํํ๋ค.
Compose์์๋ when(uiState)๋ก ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ UI๋ฅผ ๋ณด์ฌ์ฃผ๋ฉด ๋๋ค. ์:
when (val state = uiState) {
is UiState.Loading -> CircularProgressIndicator()
is UiState.Success -> ItemList(items = state.data)
is UiState.Error -> Text("์๋ฌ ๋ฐ์: ${state.message}")
}
๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ์งํค์
UI ์ํ๋ฅผ ์ ๋๋ก ๊ด๋ฆฌํ๋ ค๋ฉด ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ(Unidirectional Data Flow, UDF)์ ์ง์ผ์ผ ํ๋ค.
ํ๋ฆ์ ๋ค์๊ณผ ๊ฐ๋ค:
- UI๊ฐ ์ฌ์ฉ์ ์ ๋ ฅ์ ๋ฐ๋๋ค
- ViewModel์ด ์ ๋ ฅ์ ๋ฐ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ค
- ๋ณ๊ฒฝ๋ ์ํ๋ฅผ UI๊ฐ ๊ตฌ๋ ํ๊ณ ๋ ๋๋งํ๋ค
์ฆ, UI๋ ์ํ๋ฅผ ๋ง๋ค์ง ์๊ณ , ViewModel์ด ์ํ๋ฅผ ์์ฐํ๊ณ UI๋ ๋ฐ์๋ง ํ๋ค.
์ด ํจํด์ ๋ฐ๋ฅด๋ฉด ์ฑ์ด ์ปค์ ธ๋ ์ ์ง๋ณด์๊ฐ ์ฌ์์ง๋ค. ๋ฒ๊ทธ๊ฐ ์ ๊ณ , ํ ์คํธ๋ ์ฉ์ดํ๋ค.
๊ฒฐ๋ก
- UI ์ํ๋ ํ๋ฉด์ ๊ตฌ์ฑํ๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋งํ๋ค
- ์ํ์ ์์ฐ์ง๋ ViewModel์ด ๊ฐ์ฅ ์ด์์ ์ด๋ค
- Repository๋ ๋ฐ์ดํฐ ์์ฒ์ผ๋ก์ ์ญํ ๋ง ์ํํ๊ณ , UI ์ํ๋ฅผ ๋ง๋ค์ง ์๋๋ค
- ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ์ ์งํด์ผ ์ฑ์ด ์์ธก ๊ฐ๋ฅํ๊ณ ์์ ์ ์ด๋ค
- sealed class๋ฅผ ์ด์ฉํด ์ํ๋ฅผ ๋ช ํํ ํํํ๊ณ , UI์์ ๋ถ๊ธฐ ์ฒ๋ฆฌ ํด์ผํ๋ค
์ฑ์ ๊ท๋ชจ๊ฐ ์ปค์ง์๋ก UI ์ํ ๊ด๋ฆฌ๋ ํต์ฌ์ด ๋๋ค. ๊ฒฐ๊ตญ ์ค์ํ ๊ฑด, ๋๊ฐ ์ํ๋ฅผ ๋ง๋ค๊ณ ๋๊ฐ ๋ฐ์ํ ์ง๋ฅผ ๋ช ํํ ๋๋๋ ๊ฒ์ด๋ค.
'๐ค ์๋๋ก์ด๋ > ์ํคํ ์ฒ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์๋๋ก์ด๋] ๋ทฐ๋ฐ์ธ๋ฉ (0) | 2025.04.09 |
---|---|
[์๋๋ก์ด๋] UI ์ํ ๊ด๋ฆฌ: ์ํ ์์ฑ 2 (0) | 2025.04.08 |
[์๋๋ก์ด๋] UI ์ํ ๊ด๋ฆฌ: ์ํ ํ๋(State Holder) (0) | 2025.03.30 |
[์๋๋ก์ด๋] UI ์ด๋ฒคํธ (1) | 2025.03.29 |
[์๋๋ก์ด๋] UI ๋ ์ด์ด ์ํคํ ์ฒ (0) | 2025.03.28 |
์๋๋ก์ด๋ ์ฑ์ ๋ง๋ค๋ค ๋ณด๋ฉด UI ์ํ(UI state)๋ฅผ ์ด๋ป๊ฒ ๊ด๋ฆฌํ ์ง ๊ณ ๋ฏผ์ด ๋ง์์ง๋ค. ํนํ ์ํ๋ฅผ ์ด๋์ ๋ง๋ค๊ณ , ๋๊ฐ ์ฑ ์์ง๊ณ , ์ด๋ป๊ฒ UI์ ์ฐ๊ฒฐํ ์ง๊ฐ ์ค์ํ๋ค.
UI ์ํ๋?
์ฑ ํ๋ฉด(UI)์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐ์ดํฐ์ ๋ฐ๋ผ ๋ฐ๋๋ค. ์๋ฅผ ๋ค์ด ๋ก๋ฉ ์ค์ผ ๋๋ ์คํผ๋๊ฐ ๋๊ณ , ๋ฐ์ดํฐ๊ฐ ๋ก๋๋๋ฉด ๋ฆฌ์คํธ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ , ์๋ฌ๊ฐ ๋๋ฉด ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ์์ด๋ค.
์ด์ฒ๋ผ ํ๋ฉด์ ๊ตฌ์ฑํ๋ ๋ฐ ํ์ํ ๋ฐ์ดํฐ๋ฅผ UI ์ํ(UI State)๋ผ๊ณ ๋ถ๋ฅธ๋ค. ๋ณดํต ๋ค์ ์ธ ๊ฐ์ง ์ํ๊ฐ ์๋ค.
- ๋ก๋ฉ ์ํ (Loading)
- ์ฑ๊ณต ์ํ (Success)
- ์๋ฌ ์ํ (Error)
๊ทธ๋ฆฌ๊ณ ์ด ์ํ๋ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ(Unidirectional Data Flow) ์์์ ๊ด๋ฆฌ๋์ด์ผ ํ๋ค. ์ฆ, ๋ฐ์ดํฐ๋ ํ ๋ฐฉํฅ์ผ๋ก๋ง ํ๋ฌ๊ฐ์ผ ์์ธก ๊ฐ๋ฅํ๊ณ ๋ฒ๊ทธ๊ฐ ์ค์ด๋ ๋ค.
UI ์ํ๋ฅผ ์ด๋์ ๋ง๋ค์ด์ผ ํ ๊น?
์ํ๋ฅผ ๋ง๋๋ ๊ณณ์ UI ์ํ์ ์์ฐ์ง(state producer)๋ผ๊ณ ํ๋ค. ๋ณดํต ์ธ ๊ฐ์ง ์์น ์ค ํ๋์์ ์ํ๊ฐ ๋ง๋ค์ด์ง๋ค.
1. UI ์์ฒด์์ ๋ง๋๋ ๊ฒฝ์ฐ (View/UI State as Source of Truth)
์ด ๊ฒฝ์ฐ์๋ UI ์ปดํฌ๋ํธ(์: Fragment, Activity, Compose ๋ฑ)๊ฐ ์ง์ ์ํ๋ฅผ ๋ง๋ ๋ค. ์๋ฅผ ๋ค์ด remember { mutableStateOf(...) }๋ LiveData๋ฅผ UI์์ ์ ์ธํ๋ ๋ฐฉ์์ด๋ค.
์ด ๋ฐฉ์์ ๋จ์ํ ํ๋ฉด์์๋ ๊ด์ฐฎ์ง๋ง, ๋ก์ง์ด ๋ณต์กํด์ง๋ฉด ๋ฌธ์ ๊ฐ ๋ง์์ง๋ค.
๋ฌธ์ ์ :
- ์ํ๊ฐ UI์ ๋ฌถ์ฌ ์์ด ์ฌ์ฌ์ฉ์ด๋ ํ ์คํธ๊ฐ ์ด๋ ค์
- ํ๋ฉด ํ์ ๋ฑ ์๋ช ์ฃผ๊ธฐ ๋ณํ์ ์ทจ์ฝ
- ์ฌ๋ฌ UI์์ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๊ธฐ ์ด๋ ค์
์ธ์ ๊ด์ฐฎ์๊น?
- ๋งค์ฐ ๋จ์ํ UI
- ์ผํ์ฑ ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฑ
2. ViewModel์์ ์ํ๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ (Recommended)
๊ฐ์ฅ ๊ถ์ฅ๋๋ ๋ฐฉ์์ด๋ค. ์ํ๋ฅผ ViewModel์์ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ฉด์ UI๋ ์ด๋ฅผ ๊ตฌ๋ ๋ง ํ๋ค. ์๋ฅผ ๋ค์ด
val uiState: StateFlow<UiState> = _uiState
ViewModel์ด StateFlow๋ LiveData ๋ฑ์ ํตํด UI ์ํ๋ฅผ ๋ง๋ค์ด ๋ด๊ณ , UI๋ ์ด๋ฅผ collectAsState() ํน์ observe() ๋ฑ์ผ๋ก ๊ฐ์งํด์ ํ๋ฉด์ ๊ฐฑ์ ํ๋ค.
์ฅ์ :
- ViewModel์ ์๋ช ์ฃผ๊ธฐ์ ๋ ๋ฆฝ์ ์ด๊ธฐ ๋๋ฌธ์ UI๊ฐ ์ฌ์์ฑ๋์ด๋ ์ํ ์ ์ง ๊ฐ๋ฅ
- ํ ์คํธ์ ์ ์ง๋ณด์์ ์ ๋ฆฌ
- ๋ณต์กํ UI ๋ก์ง๋ ๊น๋ํ๊ฒ ๋ถ๋ฆฌ ๊ฐ๋ฅ
3. Repository ๋๋ Domain Layer์์ ๋ง๋๋ ๊ฒฝ์ฐ
์ผ๋ถ ์ฑ์์๋ ์ํ๋ฅผ Repository์์ ๋ง๋๋ ๊ฒฝ์ฐ๋ ์๋ค. ์๋ฅผ ๋ค์ด ์๋ฒ ํต์ ๊ฒฐ๊ณผ๋ฅผ Resource<Success, Error, Loading> ๋ฑ์ ํํ๋ก ๋ด๋ณด๋ด๋ ๋ฐฉ์์ด๋ค.
ํ์ง๋ง Repository๋ ๋ฐ์ดํฐ ์์ค์ ์ง์ค๋ ์์ค(Source of Truth)๊ฐ ๋์ด์ผ์ง, UI ์ํ์ ์์ฐ์ง๊ฐ ๋์ด์ ์ ๋๋ค.
์๋ํ๋ฉด UI ์ํ๋ UI์ ๋ฐ์ ํ๊ฒ ์ฐ๊ด๋์ด ์์ด์, ์ฑ์ UI ์ ์ฑ ์ ๋ฐ๋ผ ์ํ ๊ตฌ์กฐ๊ฐ ๋ฌ๋ผ์ง ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ฅผ ๋ค์ด ๋ก๋ฉ ์ํ๋ฅผ UI์์๋ง ๋ณด์ฌ์ค์ง, ์ฌ๋ฌ ์ข ๋ฅ๋ก ๊ตฌ๋ถํ ์ง ๋ฑ์ UI ์ค๊ณ์ ๋ฌธ์ ๋ค.
Repository๋ ๋๋ฉ์ธ ๋ฐ์ดํฐ๋ง ๊ด๋ฆฌํ๊ณ , UI ์ํ๋ ViewModel์์ ์์ฐํด์ผํ๋ค.
UI ์ํ๋ฅผ ์ด๋ป๊ฒ ํํํ ๊น?
๋ณดํต UI ์ํ๋ sealed class๋ data class๋ก ํํํ๋ค. ์๋ฅผ ๋ค์ด:
sealed interface UiState {
object Loading : UiState
data class Success(val data: List<Item>) : UiState
data class Error(val message: String) : UiState
}
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ ์ํ๋ณ๋ก ๋ถ๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์ด ์์ ํ๊ณ ๋ช ํํ๋ค.
Compose์์๋ when(uiState)๋ก ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ UI๋ฅผ ๋ณด์ฌ์ฃผ๋ฉด ๋๋ค. ์:
when (val state = uiState) {
is UiState.Loading -> CircularProgressIndicator()
is UiState.Success -> ItemList(items = state.data)
is UiState.Error -> Text("์๋ฌ ๋ฐ์: ${state.message}")
}
๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ์งํค์
UI ์ํ๋ฅผ ์ ๋๋ก ๊ด๋ฆฌํ๋ ค๋ฉด ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ(Unidirectional Data Flow, UDF)์ ์ง์ผ์ผ ํ๋ค.
ํ๋ฆ์ ๋ค์๊ณผ ๊ฐ๋ค:
- UI๊ฐ ์ฌ์ฉ์ ์ ๋ ฅ์ ๋ฐ๋๋ค
- ViewModel์ด ์ ๋ ฅ์ ๋ฐ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ค
- ๋ณ๊ฒฝ๋ ์ํ๋ฅผ UI๊ฐ ๊ตฌ๋ ํ๊ณ ๋ ๋๋งํ๋ค
์ฆ, UI๋ ์ํ๋ฅผ ๋ง๋ค์ง ์๊ณ , ViewModel์ด ์ํ๋ฅผ ์์ฐํ๊ณ UI๋ ๋ฐ์๋ง ํ๋ค.
์ด ํจํด์ ๋ฐ๋ฅด๋ฉด ์ฑ์ด ์ปค์ ธ๋ ์ ์ง๋ณด์๊ฐ ์ฌ์์ง๋ค. ๋ฒ๊ทธ๊ฐ ์ ๊ณ , ํ ์คํธ๋ ์ฉ์ดํ๋ค.
๊ฒฐ๋ก
- UI ์ํ๋ ํ๋ฉด์ ๊ตฌ์ฑํ๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋งํ๋ค
- ์ํ์ ์์ฐ์ง๋ ViewModel์ด ๊ฐ์ฅ ์ด์์ ์ด๋ค
- Repository๋ ๋ฐ์ดํฐ ์์ฒ์ผ๋ก์ ์ญํ ๋ง ์ํํ๊ณ , UI ์ํ๋ฅผ ๋ง๋ค์ง ์๋๋ค
- ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ์ ์งํด์ผ ์ฑ์ด ์์ธก ๊ฐ๋ฅํ๊ณ ์์ ์ ์ด๋ค
- sealed class๋ฅผ ์ด์ฉํด ์ํ๋ฅผ ๋ช ํํ ํํํ๊ณ , UI์์ ๋ถ๊ธฐ ์ฒ๋ฆฌ ํด์ผํ๋ค
์ฑ์ ๊ท๋ชจ๊ฐ ์ปค์ง์๋ก UI ์ํ ๊ด๋ฆฌ๋ ํต์ฌ์ด ๋๋ค. ๊ฒฐ๊ตญ ์ค์ํ ๊ฑด, ๋๊ฐ ์ํ๋ฅผ ๋ง๋ค๊ณ ๋๊ฐ ๋ฐ์ํ ์ง๋ฅผ ๋ช ํํ ๋๋๋ ๊ฒ์ด๋ค.
'๐ค ์๋๋ก์ด๋ > ์ํคํ ์ฒ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์๋๋ก์ด๋] ๋ทฐ๋ฐ์ธ๋ฉ (0) | 2025.04.09 |
---|---|
[์๋๋ก์ด๋] UI ์ํ ๊ด๋ฆฌ: ์ํ ์์ฑ 2 (0) | 2025.04.08 |
[์๋๋ก์ด๋] UI ์ํ ๊ด๋ฆฌ: ์ํ ํ๋(State Holder) (0) | 2025.03.30 |
[์๋๋ก์ด๋] UI ์ด๋ฒคํธ (1) | 2025.03.29 |
[์๋๋ก์ด๋] UI ๋ ์ด์ด ์ํคํ ์ฒ (0) | 2025.03.28 |