Contact는 변경할 수 없는 데이터 클래스이므로 Compose는 다음 중 어느 것도
ContactDetails의 인수가 변경되었습니다.
따라서 Compose는 ContactDetails를 건너뛰고 재구성하지 않습니다.
반면 ToggleButton의 인수는 변경되었습니다.
Compose는 이 구성요소를 재구성합니다.
변경 가능한 객체
앞의 예에서는 변경 불가능한 객체를 사용하지만,
변경할 수 있는 객체입니다. 다음 스니펫을 생각해 보세요.
dataclassContact(varname:String,varnumber:String)
이제 Contact의 각 매개변수가 var이므로 클래스는 더 이상 변경할 수 없습니다.
속성이 변경되면 Compose에서 인식하지 못합니다. 이는
Compose는 Compose 상태 객체의 변경사항만 추적합니다.
Compose는 이러한 클래스를 불안정하다고 간주합니다. Compose는
살펴보겠습니다. 따라서 Contact가 이런 방식으로 정의되었다면 ContactRow는
이전 예에서 selected가 변경될 때마다 재구성됩니다.
Compose에서의 구현
Compose가
리컴포지션 중에 건너뛸 함수를 결정합니다.
Compose 컴파일러가 코드에서 실행될 때 각 함수와 유형을 표시합니다.
여러 태그 중 하나로 대체합니다. 이러한 태그는 Compose가 함수를 처리하는 방법 또는
유형을 반환합니다.
함수
Compose는 함수를 skippable 또는 restartable로 표시할 수 있습니다. 참고:
함수를 다음 중 하나로 표시하거나 둘 다 표시하거나 둘 다 표시하지 않습니다.
건너뛸 수 있음: 컴파일러가 컴포저블을 건너뛸 수 있는 것으로 표시하면 Compose는
모든 인수가
이전 값입니다.
다시 시작 가능: 다시 시작할 수 있는 컴포저블이 '범위' 역할을 합니다. 각 항목의 의미는 다음과 같습니다.
재구성이 시작될 수 있습니다 즉, 함수가
Compose가 리컴포지션을 위한 코드 재실행을 시작할 수 있는 위치를 나타내는 항목
상태를 변경할 수 있습니다
유형
Compose는 유형을 변경할 수 없거나 안정적인 것으로 표시합니다. 각 유형은 하나 또는
기타:
변경 불가능: Compose는 다음 요소의 값이 변경 불가능하다고 표시합니다.
속성은 변경될 수 없으며 모든 메서드는 참조적으로 투명합니다.
모든 기본형은 변경 불가능으로 표시됩니다. 여기에는
String, Int, Float
안정적: 생성 후 속성이 변경될 수 있는 유형을 나타냅니다.
런타임 중에 이러한 속성이 변경되는 경우 Compose는
확인할 수 있습니다
를 통해 개인정보처리방침을 정의할 수 있습니다.
디버그 안정성
매개변수가 변경되지 않은 컴포저블을 앱에서 재구성하는 경우 먼저
명확하게 변경 가능한 매개변수에 대한 정의를 확인하세요. 편지쓰기는 항상
var 속성이 있는 유형 또는 val이 있는 유형을 전달하는 경우 구성요소를 재구성합니다.
속성을 사용할 수 있습니다.
안정성과 관련된 복잡한 문제를 진단하는 방법에 대한 자세한 내용은
Compose에 관한 자세한 내용은 디버그 안정성 가이드를 참고하세요.
안정성 문제 해결
Compose 구현의 안정성을 확보하는 방법에 관한 자세한 내용은 다음을 참고하세요.
안정성 문제 해결 가이드를 참고하세요.
요약
전반적으로 다음 사항에 유의해야 합니다.
매개변수: Compose가 각 매개변수의 안정성을 결정합니다.
구성 가능한 함수를 사용하여 그 중에 어떤 컴포저블을 건너뛰어야 하는지 결정합니다.
재구성할 수 있습니다
즉각적인 해결 방법: 컴포저블을 건너뛰지 않고 그리고
성능 문제를 일으킨다면
먼저 var 매개변수와 같은 불안정성을
살펴보겠습니다
컴파일러 보고서: 컴파일러 보고서를 사용하여 다음을 수행할 수 있습니다.
클래스에 관해 어떤 안정성이 추론되는지 결정합니다.
컬렉션: Compose는
List, Set 및 Map으로. 이는 잔여 노출수가 발생하지 않을 것이라고 보장할 수 없기 때문입니다.
변경할 수 없습니다 대신 Kotlinx 변경 불가능한 컬렉션을 사용할 수 있습니다.
클래스에 @Immutable 또는 @Stable로 주석을 답니다.
기타 모듈: Compose는 항상 출처가 불안정하다고 간주합니다.
Compose 컴파일러가 실행되지 않는 모듈 UI에서 클래스 래핑
사용할 수 있습니다
추가 자료
성능: Compose 성능에 관한 자세한 디버깅 도움말은
권장사항 가이드 및 I/O 강연을 참고하세요.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-26(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-26(UTC)"],[],[],null,["# Stability in Compose\n\nCompose considers types to be either stable or unstable. A type is stable if it\nis immutable, or if it is possible for Compose to know whether its value has\nchanged between recompositions. A type is unstable if Compose can't know whether\nits value has changed between recompositions.\n\nCompose uses the stability of a composable's parameters to determine whether it\ncan skip the composable during [recomposition](/develop/ui/compose/mental-model#recomposition):\n\n- **Stable parameters:** If a composable has stable parameters that have not changed, Compose skips it.\n- **Unstable parameters:** If a composable has unstable parameters, Compose always recomposes it when it recomposes the component's parent.\n\nIf your app includes many unnecessarily unstable components that Compose always\nrecomposes, you might observe performance issues and other problems.\n\nThis document details how you can increase the stability of your app to improve\nperformance and overall user experience.\n\nImmutable objects\n-----------------\n\nThe following snippets demonstrates the general principles behind stability and\nrecomposition.\n\nThe `Contact` class is an immutable data class. This is because all its\nparameters are primitives defined with the `val` keyword. Once you create an\ninstance of `Contact`, you cannot change the value of the object's properties.\nIf you attempted to do so, you would create a new object. \n\n data class Contact(val name: String, val number: String)\n\nThe `ContactRow` composable has a parameter of type `Contact`. \n\n @Composable\n fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {\n var selected by remember { mutableStateOf(false) }\n\n Row(modifier) {\n ContactDetails(contact)\n ToggleButton(selected, onToggled = { selected = !selected })\n }\n }\n\nConsider what happens when the user clicks the toggle button and the\n`selected` state changes:\n\n1. Compose evaluates if it should recompose the code inside `ContactRow`.\n2. It sees that the only argument for `ContactDetails` is of type `Contact`.\n3. Because `Contact` is an immutable data class, Compose is sure that none of the arguments for `ContactDetails` have changed.\n4. As such, Compose skips `ContactDetails` and does not recompose it.\n5. On the other hand, the arguments for `ToggleButton` have changed, and Compose recomposes that component.\n\n### Mutable objects\n\nWhile the preceding example uses an immutable object, it is possible to create a\nmutable object. Consider the following snippet: \n\n data class Contact(var name: String, var number: String)\n\nAs each parameter of `Contact` is now a `var`, the class is no longer immutable.\nIf its properties changed, Compose wouldn't become aware. This is because\nCompose only tracks changes to Compose [State objects](/reference/kotlin/androidx/compose/runtime/MutableState).\n\nCompose considers such a class unstable. Compose doesn't skip recomposition of\nunstable classes. As such, if `Contact` were defined in this way, `ContactRow`\nin the previous example would recompose any time `selected` changed.\n\nImplementation in Compose\n-------------------------\n\nIt can be helpful, though not crucial, to consider how exactly Compose\ndetermines which functions to skip during recomposition.\n\nWhen the Compose compiler runs on your code, it marks each function and type\nwith one of several tags. These tags reflect how Compose handles the function or\ntype during recomposition.\n| **Note:** These tags aren't strictly necessary to understand recomposition and stability as described in the preceding sections of this document. However, they are broadly useful when [debugging](/develop/ui/compose/performance/stability/diagnose) stability issues.\n\n### Functions\n\nCompose can mark functions as `skippable` or `restartable`. Note that it may\nmark a function as one, both, or neither of these:\n\n- **Skippable**: If the compiler marks a composable as skippable, Compose can skip it during recomposition if all its arguments are equal with their previous values.\n- **Restartable**: A composable that is restartable serves as a \"scope\" where recomposition can start. In other words, the function can be a point of entry for where Compose can start re-executing code for recomposition after state changes.\n\n### Types\n\nCompose marks types as either immutable or stable. Each type is one or the\nother:\n\n- **Immutable** : Compose marks a type as immutable if the value of its properties can never change and all methods are referentially transparent.\n - Note that all primitive types are marked as immutable. These include `String`, `Int`, and `Float`.\n- **Stable**: Indicates a type whose properties can change after construction. If and when those properties change during runtime, Compose becomes aware of those changes.\n\n| **Note:** A composable's parameters don't have to be immutable for Compose to consider it skippable. They can be mutable as long as the Compose runtime is notified of all changes. For most types this would be an impractical contract to uphold. However, Compose provides mutable classes that do uphold this contract for you, such as `MutableState`, `SnapshotStateMap`, and `SnapshotStateList`.\n\nDebug stability\n---------------\n\nIf your app is recomposing a composable whose parameters have not changed, first\ncheck its definition for parameters that are clearly mutable. Compose always\nrecomposes a component if you pass in a type with `var` properties, or a `val`\nproperty that use a known unstable type.\n\nFor detailed information about how to diagnose complex issues with stability in\nCompose, see the [Debug stability](/develop/ui/compose/performance/stability/diagnose) guide.\n\nFix stability issues\n--------------------\n\nFor information about how to bring stability to your Compose implementation, see\nthe [Fix stability issues](/develop/ui/compose/performance/stability/fix) guide.\n\nSummary\n-------\n\nOverall, you should note the following points:\n\n- **Parameters**: Compose determines the stability of each parameter of your composables to determine which composables it should skip during recomposition.\n- **Immediate fixes** : If you notice your composable isn't being skipped *and\n it is causing a performance issue* , you should check the obvious causes of instability like `var` parameters first.\n- **Compiler reports** : You can use the [compiler reports](/develop/ui/compose/performance/stability/diagnose) to determine what stability is being inferred about your classes.\n- **Collections** : Compose always considers collection classes unstable, such as `List, Set` and `Map`. This is because it cannot be guaranteed that they are immutable. You can use [Kotlinx immutable collections](/develop/ui/compose/performance/stability/fix#immutable-collections) instead or annotate your classes as `@Immutable` or `@Stable`.\n- **Other modules**: Compose always considers unstable where they are from modules in which the Compose compiler does not run. Wrap the classes in UI model classes if required.\n\nFurther reading\n---------------\n\n- **Performance** : For more debugging tips on Compose performance, check out our [best practices guide](http://goo.gle/compose-performance) and [I/O talk](https://www.youtube.com/watch?v=EOQB8PTLkpY)."]]