해당 포스트는 엄재웅 - Compose 성능 최적화를 위한 Stability 마스터하기(https://www.youtube.com/watch?v=bDyhdJk3uZM) 를 보고 간략하게 정리한 내용 & 간단한 개인 의견을 주저리 적어두었습니다.
원본 영상은 좋은 내용이 많으니, 보시길 추천드립니다.
Stable 로 간주되는 유형
- 원시 타입
- 파라미터가 없는 모든 람다 (파라미터를 넘기는 경우 해당 파라미터가 Stable 인 경우만)
- (data) class 의 public property 가 불변(val) 이거나 Stable 인 경우
- (data) class 에 @Stable 이나 @Immutable 을 명시적으로 표기하는 경우
Unstable 로 간주되는 유형(아래 모든 유형은 equals 와 별개로 동작하기 때문에 값이 같아도 Recomposition 발생)
- 모든 interface 는 unstable
- Any, abstract class 등 컴파일 레벨에서 구현체를 예측할 수 없는 것들은 모두 unstable
- (data) class 의 public 프로퍼티 중 하나 이상 가변(var) 혹은 unstable 한 경우
Composable 함수
- 파라미터가 모두 stable 하다면 recomposition 및 불필요한 작업 생략
- 파라미터가 하나라도 unstable 하면 recomposition 이 항상 발생
- compose metric 으로 확인하자
Smart Recomposition
- Recomposition 이 발생했을 떄, 하위에 Composable 에 Recomposition 이 모두 전이될 수 있는데, 이때 각각 하위 Composable 에서 파라미터의 equals 를 이용하여 true 라면 recomposition 을 생략할 수 있는 것을 의미하고 Recomposition 의 기본 동작
Composable 함수 유형 추론
- Composable 이 붙으면 컴포즈 컴파일러는 해당 Composable 함수에 Restartable, Skippable, Movable 과 같은 유형을 추가해둠
- Restartable (재실행가능)
- 일반적인 함수는 한번만 호출되지만, Restartable 을 전달 받는 파라미터가 변경되면 이를 감지하여 재실행 되어 다시 그려질 수 있도록 함
- 거의 모든 Composable 함수가 가지는 기본 특성
- Skippable
- Composable 파라미터가 모두 stable 하고 && equals 가 true 라면 Skippable 특성을 가지게 됨
- Restartable, Skippable 2가지 유형을 달고 있는 Composable 함수를 많이 만드는 것이 성능 향상의 핵심
Compose Annotation(@Immutable, @Stable)
- 컴포즈 컴파일러의 추론상 Unstable 할 것이라 예상되지만, 개발자의 판단하에 특정 클래스나 인터페이스를 Stable 하게 사용하고 싶은 경우 활용할 수 있음
- 라이브러리에서 잔달되는 unstable class 을 직접 수정하기 어려운 경우 Wrapper class 를 만들어 Stable 하게 만들 때 이용할 수 있음
- @Immutable
- (data) Class 의 모든 public 프로퍼티와 필드가 초기화된 이유 절대 변경이 없다고 컴포즈 컴파일러와 약속 하는 것
- 이를 위한 두 가지 규칙을 가짐
- public 프로퍼티는 항상 val 여야 함
- public 프로퍼티를 가변성으로 만들 수 있는 커스텀 setter 를 지양해야함
- ex ) get() = {...}, set(value) {...}
- @Stable
- @Immutable 보다는 조금 느슨한 약속
- "안정적" 이라는 것은 개발자가 mutableState 등을 이용해 해당 값을 임의로 변경할 가능성이 있다는 것 하지만 이때 동일한 입력 값에 동일한 결과를 반환할 것이라는 것을 보장한다는 의미.
- (data) class 의 프로퍼티가 불변(val) 인 경우 혹은 인터페이스에 가장 적합하게 사용 가능.
- ex) 모든 interface 는 위에서 unstable 하다고 이야기했지만, 동일한 입력에 동일한 결과가 나온다면 해당 상황에서 사용 가능.(equals true 가 성립해야함)
- @NonRestartableComposable
- Restartable 속성을 보여하지 않고, Recomposition 을 항상 생략
- 그말인즉 Recomposition 에 영향을 받지 않는 것들을 표현할 때 용이
- 예시
- LaunchedEffect : key 가 변경될 때만 영향 받고, Recomposition 는 상관 없음
- 혹은 딱 1회면 호출되어야 하는 일반 함수 처리시 용이
- 예시
- 그말인즉 Recomposition 에 영향을 받지 않는 것들을 표현할 때 용이
- Restartable 속성을 보여하지 않고, Recomposition 을 항상 생략
Stable 로 처리하는 클래스들이 궁금하다면 ?
- KnownStableConstructs.kt 파일 찾아보기
'Android > Development Tips' 카테고리의 다른 글
간단 Tips. Retrofit2 을 사용할 때 언제 WorkerThread 에서 동작할까 ? (2) | 2023.11.27 |
---|---|
Compose. StateFlow + List 를 활용하여 Recomposition 할 때 Tips (0) | 2023.06.06 |
Summary MVI 직접 작성 해야/하지 않아야 하는 이유 (0) | 2023.01.05 |
확대, 축소, 이동, 회전 가능한 컴포즈 뷰 (0) | 2022.12.30 |
간단 Tips. FrameLayout 위에 Fragment 를 올리는 것보다 FragmentContainerView 에 Fragment 를 올리는 것이 안전한 이유 (0) | 2022.11.30 |