๐ŸŒŠ UiState Architecture

UiState ๋ผ๋Š” sealed interface๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. UiState๋Š” (ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•˜๊ณ ) ๊ฐ ํ™”๋ฉด ๋‹น ํ•˜๋‚˜์”ฉ ์กด์žฌํ•˜๋ฉฐ, ViewModel ํ•˜๋‹จ์— ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ sealed interface๋Š” ๋ณดํ†ต์˜ ๊ฒฝ์šฐ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž์‹์„ ๊ฐ–์Šต๋‹ˆ๋‹ค.

sealed interface MyPageUiState {
    data class Success(val userInfo: UserInfo) : MyPageUiState
    data object Loading : MyPageUiState
    data object LoadFailed : MyPageUiState
}

์ด์ œ ContainerHost์˜ STATE ํƒ€์ž…์œผ๋กœ ํ•ด๋‹น UiState๋ฅผ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.

class MyPageViewModel(
    ...
) : ContainerHost<MyPageUiState, Nothing>, ViewModel() {
    ...
}

์ด UiState๋ฅผ ์–ด๋–ป๊ฒŒ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ๋˜๋Š” ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š”์ง€๋Š” ์ดํ›„์— ํ™•์ธํ•˜๊ณ , ์šฐ์„ ์€ ์œ„์™€ ๊ฐ™์€ UiState๋ฅผ UI์—์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

โ™ฃ๏ธ UiState in Composable

UiState๋ฅผ ์“ฐ์ง€ ์•Š๋Š” ๋ฐฉ์‹๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, Composable์—์„œ state๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

@Composable
fun MyPageScreen(...) {
    val uiState by viewModel.collectAsState()
    
    MyPageScreenContent(
        uiState = uiState,
        ...
    )
}

๋‹ค์Œ์œผ๋กœ, MyPageScreenContent์—์„œ๋Š” ๋„˜๊ฒจ๋ฐ›์€ uiState๋ฅผ ๋ถ„๊ธฐํ•˜์—ฌ ๊ฐ ์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” UI๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

@Composable
fun MyPageScreenContent(
    uiState: MyPageUiState,
    modifier: Modifier = Modifier
) {

    ...
    when(uiState) {
        is MyPageUiState.Success -> {
            // ์ด ์•ˆ์—์„œ๋Š” userInfo ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
            ...
        }
        MyPageUiState.Loading -> {
            // ๋กœ๋”ฉ ๋ทฐ
        }
        MyPageUiState.LoadFailed -> {
            // ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์‹คํŒจ ๋ทฐ (์—๋Ÿฌ)
        }
    }
}