Jetpack Compose에서 상태 기반(State-Based) 텍스트 필드와 값 기반(Value-Based) 텍스트 필드 비교
Jetpack Compose에서 상태 기반(State-Based) 텍스트 필드와 값 기반(Value-Based) 텍스트 필드 비교
Jetpack Compose는 텍스트 입력을 처리하기 위해 값 기반(value-based) 텍스트 필드와 상태 기반(state-based) 텍스트 필드, 두 가지 접근 방식을 제공합니다. 이 두 방식은 입력 상태 관리, 텍스트 변환 처리, 줄 수 제한 설정, 보안 입력 지원 등에서 서로 다른 동작 방식을 갖습니다. 공식 문서에서는 상태 기반 텍스트 필드를 권장하는데, 텍스트 입력 상태의 전체 생명주기를 캡슐화하고 변환 및 설정 처리를 단순화하기 때문입니다. 이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.
- 값 기반 텍스트 필드가
onValueChange콜백을 통해 상태를 관리하는 방식 - 상태 기반 텍스트 필드가
TextFieldState를 사용하여 모든 입력 상태를 캡슐화하는 원리 VisualTransformation과InputTransformation/OutputTransformation분리 모델의 차이점TextFieldLineLimits가 기존의singleLine,maxLines,minLines매개변수를 어떻게 단순화하는지- 보안 입력 시나리오를 위한
SecureTextField컴포저블의 활용 방법
값 기반 상태 관리(Value-Based State Management)
값 기반 텍스트 필드는 외부 메커니즘을 통해 상태를 관리합니다. 개발자가 현재 텍스트 값과 onValueChange 콜백을 직접 제공해야 하며, 사용자가 텍스트를 입력하면 새로운 값과 함께 콜백이 호출됩니다. 이후 개발자가 mutableStateOf나 ViewModel을 활용하여 상태를 수동으로 갱신해야 합니다.
@Composable
fun ValueBasedInput() {
var text by remember { mutableStateOf("") }
TextField(
value = text,
onValueChange = { text = it },
label = { Text("Enter text") }
)
}
이러한 수동 동기화 방식은 복잡성을 유발할 수 있습니다. 리컴포지션(Recomposition)이나 구성 변경(configuration changes) 상황에서 일관성을 유지하는 책임이 개발자에게 있기 때문입니다. 비동기 상태 갱신이 올바른 순서로 적용되지 않으면, 화면에 표시되는 텍스트와 백킹 상태가 서로 달라질 수 있습니다. 가령, onValueChange 콜백이 ViewModel 업데이트를 트리거하고, ViewModel이 다른 텍스트 값을 가진 새로운 상태를 방출하면, 텍스트 필드가 깜빡이거나 커서 위치를 잃어버리는 현상이 발생할 수 있습니다. 면접에서 이 부분에 대해 질문을 받을 때는 단순히 "수동 동기화가 어렵습니다"라고 답변하기보다, 구체적인 버그 시나리오를 예시로 들어 설명하시면 더 높은 점수를 받으실 수 있습니다.
상태 기반 상태 관리(State-Based State Management)
상태 기반 텍스트 필드는 TextFieldState 객체를 사용하여 텍스트 입력과 관련된 모든 상태, 즉 콘텐츠, 커서 위치, 선택 범위, 컴포지션 정보를 캡슐화합니다. 컴포저블이 이 상태를 내부적으로 소유하고, 사용자 입력에 따라 자동으로 갱신하므로 개발자가 별도의 콜백을 연결할 필요가 없습니다.
@Composable
fun StateBasedInput() {
val textFieldState = rememberTextFieldState()
BasicTextField(
state = textFieldState,
decorator = { innerTextField ->
Box(Modifier.padding(16.dp)) {
innerTextField()
}
}
)
}
TextFieldState는 리컴포지션과 구성 변경에도 상태가 유지됩니다. rememberSaveable과 함께 사용하면 프로세스 종료(process death) 상황에서도 상태를 복원할 수 있습니다. 수동 상태 동기화로 인해 발생하던 버그가 근본적으로 제거되며, 개발자는 단순히 상태 객체만 제공하면 됩니다. 현재 텍스트는 textFieldState.text를 통해 읽기만 하면 되고, 콜백을 통해 값을 설정할 필요가 전혀 없습니다.