0Pricing
Android Academy · 강의

양식 상태 관리

상태로 필드 값을 보관하고 업데이트합니다.

양식 상태 관리은(는) CoddyKit의 무료 Android Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Android Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Android Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

한 필드에서 양식으로

텍스트 필드 하나는 간단합니다. 실제 양식에는 이름, 이메일, 비밀번호, 체크박스 등 여러 필드가 있습니다. 이 과정에서는 Jetpack Compose에서 전체 양식의 상태를 보관하고 업데이트하는 깔끔한 방법을 배웁니다.

이 방법을 제대로 익히면 유효성 검사, 제출, 미리 보기를 모두 간단하게 처리할 수 있습니다.

여러 개의 독립적인 상태

가장 간단한 방법은 필드마다 mutableStateOf를 하나씩 사용하는 것입니다. 각 필드가 자신의 상태를 읽고 업데이트합니다.

필드가 두세 개인 작은 양식에는 이 방법이 충분히 적합합니다.

@Composable
fun LoginForm() {
    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }

    Column {
        OutlinedTextField(email, { email = it }, label = { Text("Email") })
        OutlinedTextField(password, { password = it }, label = { Text("Password") })
    }
}

데이터 클래스로 상태 묶기

양식이 커지면 흩어진 변수가 많아져 복잡해집니다. 더 깔끔한 방법은 전체 양식을 하나의 변경 불가능한 data class로 모델링하는 것입니다.

해당 객체를 담은 단일 상태를 유지하고 copy()로 업데이트합니다.

data class SignUpState(
    val name: String = "",
    val email: String = "",
    val agreedToTerms: Boolean = false
)

copy()로 업데이트하기

상태 객체는 변경할 수 없으므로 제자리에서 수정하지 않습니다. 대신 한 필드만 변경한 새 복사본을 만들어 다시 할당합니다.

이렇게 하면 Compose의 상태 모델을 예측 가능하게 유지할 수 있습니다. 새 객체는 새 스냅샷을 의미하고, 재구성을 촉발합니다.

var form by remember { mutableStateOf(SignUpState()) }

OutlinedTextField(
    value = form.name,
    onValueChange = { form = form.copy(name = it) },
    label = { Text("Name") }
)

전체 데이터 클래스 폼

여기서는 전체 폼이 하나의 SignUpState에 의해 관리됩니다. 각 필드는 copy()를 사용해 하나의 속성만 업데이트합니다.

언제든지 전체 폼의 값을 얼마나 쉽게 읽을 수 있는지 확인해 보세요. 단순히 form을 읽으면 됩니다.

var form by remember { mutableStateOf(SignUpState()) }

Column {
    OutlinedTextField(
        value = form.name,
        onValueChange = { form = form.copy(name = it) },
        label = { Text("Name") }
    )
    OutlinedTextField(
        value = form.email,
        onValueChange = { form = form.copy(email = it) },
        label = { Text("Email") }
    )
}

체크박스와 스위치

모든 입력이 텍스트인 것은 아닙니다. Checkbox나 Switch도 불리언 값과 onCheckedChange 콜백을 사용하는 같은 방식으로 작동합니다.

문자열과 마찬가지로 불리언을 폼 상태에 저장하면 됩니다.

var form by remember { mutableStateOf(SignUpState()) }

Row(verticalAlignment = Alignment.CenterVertically) {
    Checkbox(
        checked = form.agreedToTerms,
        onCheckedChange = { form = form.copy(agreedToTerms = it) }
    )
    Text("I agree to the terms")
}

상태에서 값 도출하기

상태를 단일 출처로 관리할 때의 큰 장점 중 하나는 추가 변수를 저장하지 않고도 상태에서 값을 계산할 수 있다는 것입니다. 예를 들어 폼을 제출할 준비가 되었는지 계산할 수 있습니다.

derivedStateOf 또는 간단한 표현식을 사용하면 폼이 변경될 때 결과가 자동으로 업데이트됩니다.

var form by remember { mutableStateOf(SignUpState()) }

val canSubmit by remember {
    derivedStateOf {
        form.name.isNotBlank() &&
        form.email.isNotBlank() &&
        form.agreedToTerms
    }
}

Button(onClick = { /* submit */ }, enabled = canSubmit) {
    Text("Sign Up")
}

구성 변경에도 상태 유지하기

remember는 재구성 중에 상태를 유지하지만 화면 회전과 같은 구성 변경이 발생하면 상태가 사라집니다. 회전 후에도 간단한 값을 유지하려면 rememberSaveable을 사용하세요.

기본형과 Parcelable 형식은 별도의 설정 없이 사용할 수 있습니다.

var email by rememberSaveable { mutableStateOf("") }

OutlinedTextField(
    value = email,
    onValueChange = { email = it },
    label = { Text("Email") }
)

폼 상태를 ViewModel로 끌어올리기

간단한 폼을 넘어서는 경우에는 상태를 ViewModel에 보관하세요. 구성 변경 후에도 상태가 유지되고 UI 로직을 컴포저블에서 분리할 수 있습니다.

컴포저블은 상태를 읽고 이벤트를 전달하며, 실제 상태의 원본은 ViewModel이 관리합니다.

class SignUpViewModel : ViewModel() {
    var state by mutableStateOf(SignUpState())
        private set

    fun onNameChange(value: String) {
        state = state.copy(name = value)
    }
}

ViewModel 연결하기

컴포저블에서 ViewModel을 가져온 다음 각 필드를 해당 상태 및 처리기에 연결하세요. UI는 얇게 유지되어 테스트하기 쉬워집니다.

이 구조는 실제 서비스의 폼에 권장되는 방식입니다.

@Composable
fun SignUpScreen(vm: SignUpViewModel = viewModel()) {
    OutlinedTextField(
        value = vm.state.name,
        onValueChange = vm::onNameChange,
        label = { Text("Name") }
    )
}

순수 Kotlin: copy() 동작 확인하기

copy() 업데이트 패턴은 표준 Kotlin 데이터 클래스 동작일 뿐입니다. 여기서는 각 업데이트가 완전히 새로운 객체를 만드는 과정을 볼 수 있도록 독립적으로 실행합니다.

data class SignUpState(
    val name: String = "",
    val email: String = ""
)

fun main() {
    var state = SignUpState()
    state = state.copy(name = "Ada")
    state = state.copy(email = "ada@dev.io")
    println(state)
}

빠른 확인

상태에 저장된 변경 불가능한 data class로 폼을 모델링했습니다. 하나의 필드를 어떻게 업데이트해야 할까요?

복습

이제 전체 폼의 상태를 관리하는 방법을 배웠습니다.

  • 작은 폼: 필드마다 하나의 mutableStateOf를 사용합니다.
  • 큰 폼: 하나의 변경 불가능한 data class를 사용하고 copy()로 업데이트합니다.
  • 텍스트 필드를 텍스트로 관리하는 것처럼 불리언으로 Checkbox와 Switch를 관리합니다.
  • "제출 가능 여부"와 같은 값은 저장하지 말고 도출합니다.
  • 회전에는 rememberSaveable을 사용하고, 실제 화면에는 ViewModel을 사용합니다.

다음: 입력을 검증하고 유용한 오류를 표시하는 방법입니다.

자주 묻는 질문

“양식 상태 관리” 강의는 무료인가요?

네 — “양식 상태 관리” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Android Academy 강의 전체를 잠금 해제할 수 있습니다. Android Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“양식 상태 관리”에서 뭘 배우나요?

상태로 필드 값을 보관하고 업데이트합니다. 브라우저에서 직접 실행하는 실습 코드로 Android Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Android Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Android Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“양식 상태 관리” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Android Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Android Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. TextField와 사용자 입력
  2. 양식 상태 관리
  3. 입력값 검증
  4. 키보드 옵션과 동작
← Android Academy(으)로 돌아가기