면접 질문실전 질문꼬리 질문

Jetpack Compose에서의 안정성(Stability)과 불안정성(Unstable) 타입

skydovesJaewoong Eum (skydoves)||8분 소요

Jetpack Compose에서의 안정성(Stability)과 불안정성(Unstable) 타입

Jetpack Compose는 컴포저블 함수의 매개변수가 가진 **안정성(stability)**을 기반으로, 부모 컴포저블이 리컴포지션(Recomposition)될 때 자식 컴포저블의 리컴포지션을 건너뛸 수 있는지 여부를 판단합니다. 안정적인(stable) 타입이란 Compose가 동등성(equality) 검사를 통해 값의 변경 여부를 신뢰성 있게 감지할 수 있는 타입을 의미합니다. 반대로 불안정한(unstable) 타입이란 값이 변경되지 않았다는 보장을 Compose가 할 수 없어서, 해당 컴포저블을 무조건 리컴포지션해야 하는 타입을 뜻합니다.

이러한 안정성과 불안정성의 구분을 정확히 이해하는 것은 불필요한 리컴포지션을 방지하고, 매끄러운 UI 성능을 유지하는 데 있어 매우 중요합니다. 특히 면접에서도 Compose의 성능 최적화와 관련하여 자주 출제되는 주제이므로, 개념을 확실히 정리해 두시는 것을 권장합니다.

이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.

  • Compose 타입 시스템에서 어떤 타입이 안정적(stable)이고 어떤 타입이 불안정(unstable)한지 정의할 수 있습니다.
  • 매개변수의 안정성이 리컴포지션 과정에서 컴포저블을 건너뛸 수 있는지 여부를 어떻게 결정하는지 설명할 수 있습니다.
  • var 프로퍼티와 표준 코틀린 컬렉션 등 대표적인 불안정 타입을 식별할 수 있습니다.
  • MutableState가 관찰 가능한 변경(observable mutation)을 통해 어떻게 안정적인 타입으로 분류되는지 설명할 수 있습니다.
  • 컴포저블 계층 구조에서 불필요한 리컴포지션을 줄이기 위한 안정성 원칙을 적용할 수 있습니다.

타입이 안정적(Stable)으로 분류되는 조건

Compose에서 타입이 안정적이라 함은, 두 인스턴스가 동일한 값을 나타내는지 동등성 비교를 통해 판단할 수 있다는 뜻입니다. 안정적인 타입은 크게 두 가지 범주로 나뉩니다.

불변(Immutable) 타입은 모든 프로퍼티가 val로 선언되어 있으며, 해당 프로퍼티 역시 안정적인 타입으로 구성된 경우를 의미합니다. 한번 생성되면 관찰 가능한 상태가 변경될 수 없습니다. 코틀린의 모든 원시 타입(primitive type), String, 그리고 안정적인 타입의 val 프로퍼티로만 이루어진 data class가 이 범주에 해당합니다.

관찰 가능한 가변(Observable Mutable) 타입은 값이 변경될 수 있지만, 변경 시 Compose에 이를 알릴 수 있는 타입입니다. MutableState<T>가 대표적인 예시로, Compose는 MutableState에 대한 읽기와 쓰기를 추적하고, 값이 변경되면 리컴포지션을 예약합니다. 가변성이 제어되고 관찰 가능하기 때문에, Compose는 여전히 건너뛰기(skip) 여부를 판단할 수 있습니다.

즉, "안정적"이란 단순히 "불변"만을 의미하는 것이 아니라, "변경 사항을 Compose가 감지할 수 있는가"를 기준으로 판단한다는 점을 기억하시면 됩니다.

타입이 불안정(Unstable)으로 분류되는 조건

타입이 불안정하다는 것은 리컴포지션 사이에 값이 변경되지 않았다는 것을 Compose가 보장할 수 없는 경우를 뜻합니다. 대표적인 원인은 다음과 같습니다.

  • Compose State로 뒷받침되지 않는 var 프로퍼티를 가진 data class의 경우, 외부에서 언제든 값을 변경할 수 있어 Compose가 변경 여부를 추적할 수 없습니다.
  • 프로퍼티 자체가 다른 불안정 타입인 경우, 해당 타입을 포함하는 클래스도 불안정하게 됩니다.
  • 표준 코틀린 컬렉션(List, Map, Set)은 Compose가 내부 요소의 불변성을 검증하거나 내부 변경을 추적할 수 없기 때문에 불안정으로 분류됩니다.

컴포저블이 불안정한 매개변수를 전달받으면, Compose는 해당 컴포저블을 안전하게 건너뛸 수 없습니다. 실제로 값이 변경되지 않았더라도 값이 동일하다는 것을 증명할 수 없기 때문에, Compose는 반드시 해당 함수를 리컴포지션합니다. 이 점이 바로 면접에서도 자주 물어보는 핵심 포인트이므로, 확실히 이해해 두시길 바랍니다.

건너뛰기(Skipping) 동작

부모 컴포저블이 리컴포지션될 때, Compose는 각 자식 컴포저블의 매개변수를 다음과 같이 평가합니다.

이 면접 질문은 구독자 전용입니다

Dove Letter를 구독하시면 안드로이드, 코틀린 개발 관련 독점 면접 질문의 전체 내용을 볼 수 있습니다.

구독하기