이번 시간에는 key 에 관하여 알아보려고 한다.
우선 key 에 대해 알아보기 앞서, 코드를 작성해보자.
class MainActivity() : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
enableEdgeToEdge()
MaterialTheme {
Scaffold {
var count by remember { mutableIntStateOf(1) }
val isEven = remember { count % 2 == 0 }
Column(modifier = Modifier
.fillMaxSize()
.padding(it)
) {
Text(text = count.toString())
Button(
onClick = {
count++
Timber.d("${count}으로 변경 완료")
}
) { Text(text = "숫자 올리기")}
Text(text = "짝수인가? - $isEven")
}
}
}
}
}
}
위의 코드에서는 아래 3가지 컴포저블이 존재한다.
당연히 처음에는 초기화값대로 설정되어있을 것이다.
이제 버튼을 눌러 count 를 홀수로 만들어주고 텍스트를 살펴보자.

최초 false 였던 것이 여전히 false 로 유지되고 있다.
이전에 remember 는 내부 계산을 저장한다고 알려준 적이 있다.
다시 한 번 remember 함수를 살펴보자.
@Composable
inline fun <T> remember(crossinline calculation: @DisallowComposableCalls () -> T): T =
currentComposer.cache(false, calculation)
@ComposeCompilerApi
inline fun <T> Composer.cache(invalid: Boolean, block: @DisallowComposableCalls () -> T): T {
@Suppress("UNCHECKED_CAST")
return rememberedValue().let {
if (invalid || it === Composer.Empty) {
val value = block()
updateRememberedValue(value)
value
} else it
} as T
}
remember 함수는 key 를 지정해주지 않으면, invalid 가 false 로 지정되기 때문에 최초의 컴포지션이 아니면 재계산을 진행하지 않는다.
그렇기에 state 를 변경시켜주려면 currentComposer.cache() 의 invalid 를 true 로 만들거나, 값을 직접 조정해주어야한다.
여기서 invalid 가 현재 말하는 key 이다.
즉, key 를 넣어주고, 리컴포지션 시 key 가 이전과 다르다면 계산식이 다시 실행되어 변수값이 변화할 수 있게 되는 것이다.
이제 이를 알았으므로, isEven 의 remember 에 key 를 지정해주자.
val isEven = remember(count) { count % 2 == 0 }.

순으로 이어진다.
다만 위처럼 key 지정을 해주면 key 가 변경될때마다 계산식이 매번 이루어지므로 이를 참고하자.
이전 값과 같은지 판단을 하기 위해 존재하므로, State 나 State.value 일 필요는 없다.
class MainActivity() : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
enableEdgeToEdge()
MaterialTheme {
var count by remember { mutableIntStateOf(1) }
val test = Random.nextInt()
val isEven = remember(test) { count % 2 == 0 }
Scaffold {
Column(modifier = Modifier
.fillMaxSize()
.padding(it)
) {
Text(text = count.toString())
Button(
onClick = {
count++
Timber.d("${count}으로 변경 완료")
}
) { Text(text = "숫자 올리기")}
Text(text = "짝수인가? - $isEven")
}
}
}
}
}
}
위 코드를 실행하면 버튼을 눌러 발생시키는 리컴포지션마다 isEven 이 바뀌는 것을 알 수 있다.
단, key 가 변경되었는지 판단은 리컴포지션 때 발생하므로 이것또한 참고하자.
Tistory 글을 옮기고 있는데, 예전 글 및 내 지식이 몇 가지 이상한 부분이 있었다는 것을 지금 알았다... 글들을 옮기면서 다시 공부하지 않았으면 큰일났을 것 같다.