Activity 구성 변경 총정리

SSY·2025년 9월 14일
0

AndroidFramework

목록 보기
4/4
post-thumbnail

1. 시작하며

이전에 작성한 포스팅(Activity 재생성이 발생하는 경우와 그에 대한 권고 대비 사항)에선 Activity재생성이 발생하는 경우와 그에 대한 안드로이드에서 권장하는 대비법에 대해 알아봤있다. 개괄적으로 말해보자면, Activity재생성은 '구성 변경'과 '프로세스의 강제 종료'등의 사유로 발생하는데, 이는 onDestroy()까지 호출했다가, onCreate()를 호출하는, 즉 말 그대로 Activity를 다시 생성하는 작업을 의미한다. 또한 Activity생명주기 중간에 onSaveInstanceState()onRestoreInstanceState()을 호출했었다.

[Activity 재생성 생명주기]

  • onPause()
  • onStop()
  • onSaveInstanceState()
  • onDestroy()
  • onCreate()
  • onStart()
  • onRestoreInstanceState()
  • onResume()

하지만, '구성 변경'으로 인해 발생하는 Activity재생성은 Manifest.xmlandroid:configChanges설정을 통해 Activity재생성을 방지할 수 있다.

이번 포스팅에선 위 내용을 토대로, Android공식 홈페이지가 권고하는 '구성 변경'에 대한 내용을 정리한 글이다.

2. '구성'이란?

갤럭시 앱 기준, '설정'앱에 들어가면 앱의 여러 설정을 변경할 수 있다. 언어, 글자 크기, 글자 두께, 외부 키패드 연동, 테마 변경 등이 가능하다. Android Framework에선 이러한 설정 정보를 Configuration이란 객체에 담고있는데, 이를 '구성'이라고 한다. 이러한 구성 리스트는 Android공식 홈페이지에 android:configChanges설정 목록에서 볼 수 있다.

설명
colorMode화면의 색상 모드 기능(색상 범위 또는 동적 범위)이 변경되었을 때.
density화면 밀도 변경(예: 사용자가 디스플레이 크기를 조정하거나 다른 디스플레이가 활성화).
fontScale글꼴 배율 변경(예: 사용자가 새 전체 글꼴 크기를 선택).
fontWeightAdjustment글꼴 두께 증가/감소 값이 변경되었을 때.
grammaticalGender언어의 문법적 성이 변경되었을 때(GrammaticalInflectionManager 참고).
keyboard키보드 유형 변경(예: 사용자가 외부 키보드를 연결).
keyboardHidden키보드 접근성 변경(예: 사용자가 하드웨어 키보드를 표시/숨김).
layoutDirection레이아웃 방향 변경(좌→우 LTR ↔ 우→좌 RTL). (API 17+)
locale언어 변경(예: 사용자가 텍스트를 표시할 새 언어를 선택).
mccMCC(모바일 국가 코드) 변경.
mncMNC(모바일 네트워크 코드) 변경.
navigation탐색(물리/트랙볼 등) 구성 변경. 일반적으로는 발생하지 않음.
orientation화면 방향 변경(예: 사용자가 기기를 회전).
screenLayout화면 레이아웃 변경(예: 다른 디스플레이가 활성화되는 경우).
screenSize현재 사용 가능한 화면 크기 변경(전체 사용 가능 영역 기준으로 크기 변경).
smallestScreenSize실제 화면의 최소 너비가 변경(외부 디스플레이로 전환/분할 등). (API 13+)
touchscreen터치 스크린 모드 변경(예: 입력 주변기기를 연결/해제).
uiMode사용자 인터페이스 모드 변경(예: 야간/자동/자동차/TV 등; UiModeManager 참고).

3. 구성변경

말 그대로, 사용자가 '설정'앱에 들어가, 위의 말한 설정을 변경하므로써, Configuration객체 내부 상태가 변경되는걸 의미한다.

사용자는 구성변경 이후, 이러한 설정이 올바르게 적용되어, UI에 즉시 반영되길 기대한다. 예를 들어, 어르신이 글자가 너무 작아 크기를 키웠다거나, 외국인이 언어를 한국어에서 영어로 변경하는 경우가 있다. 이런한 설정 변경 작업이 일어났을 때, 앱은 그러한 설정을 반영해줘야 한다.

4. 구성 변경 처리법

Activity재생성 발생에 따라, 정보를 저장해야할 경우가 있다. 그럴 땐, 이전 포스팅(Activity 재생성이 발생하는 경우와 그에 대한 권고 대비 사항)에 써놨듯이 onSaveInstanceState()/onRestoreInstanceState() or rememberSaveable(), SaveStateHandle()을 활용한 상태 유지가 가능하다.

이에 대한 대비법으로 Manifest.xmlandroid:configChanges를 설정하고, Activity 재생성을 방지한다면, Activity의 정보는 유실되지 않는다. 따라서 이 방법이 더 보이기도 한다. 하지만 이게 꼭 좋은걸까?

결론부터 말하면, android:configChanges를 설정한다 해도, '구성 변경'에 따른 Activity의 재생성을 100% 방지할 수 없다. 왜냐하면 Android 12L때 도입 된 '동적 색상 변경'의 경우, Manifest.xml에 android:configChanged로도 이를 제어할 수 없기 때문이다.

또한 구성 변경의 의미를 되짚어 보면, 이는 구성 변경에 따른 UI 상태의 즉시 동기화가 이뤄져야만 한다. 예를 들어, 언어를 영어로 바꿨을 땐, 앱의 언어를 영어로 바꿔줘야하고, 테마를 다크모드로 바꿨을 땐, 다크모드로 바꿔줘야 하는것 처럼 말이다. 따라서 구성 변경에 따른 Activity의 재생성을 막아버리는 행위는, 개발자가 onConfigurationChanged() 또는 LocalConfiguration.current를 통해 UI 동기화 작업을 수동으로 진행해야 하는 만큼, 리소스 할당 작업의 수고로움이 더 들 수 있다. 따라서 구성 변경이 발생했을 땐, 오히려 Activity재생성을 유도해주고, 그에 따른 필요 리소스들을 UI에 자동 적용해주는 편이 더 편할수도 있다.

아래는 Android공식 홈페이지에서 구성 변경이 발생했을 때, Activity재생성을 권고하는 말을 문장을 바꿔가며 여러번 강조하고 있다.

더 나아가, Android 12L땐 동적 테마 변경에 따른 Activity구성 변경을 막을 수 없다.

[Android 12L 동적 색상 변경 시, 무조건적인 Activity재생성]

뿐만 아니라, 구성 변경에 따른 onConfigurationChanged()의 콜백 호출이 Android12, 12L 13 버전에선 적절히 호출되지 않는 버그 또한 보고된 바 있다. 따라서 해당 기기 버전의 하위 호환을 신경써야하는 앱이라면, 차라리 Activity재생성을 유도해주는 게 더 좋은 선택지일 수도 있다.

[Google Issue Tracker]
아래 이슈는 실제 올라온 이슈로, onConfigurationChanged()의 호출 이슈로, LocalConfiguration.current로의 상태값이 제대로 전달되지 않는 이슈이다.

참고 : Google Issue Tracker

5. 정리

  • 구성 변경 시, Activity재생성이 발생한다.
  • 이를 방지하는 방법은 android:configChanges선언이다.
  • 해당 플래그 선언으로 onConfigurationChanged() or ConfigurationLocal.current를 통한 Configuration상태값 수신이 가능하다.
  • 하지만 Activity재생성을 방지했을 경우, 구성 변경에 따른 리소스 재할당을 개발자가 직접 신경써야한다.
  • 따라서 Android에서도 구성 변경에 따른 Activity재생성을 유도하는걸 권고하고 있다.
  • 더 나아가, Android 12L, 13기기에선 onConfigurationChanged()의 호출 버그 또한 있어, 더욱 권장하지 않는다.
  • 따라서 구성 변경 시, Activity재생성을 유도하는 게 좋은 선택지일 수 있다.
profile
불가능보다 가능함에 몰입할 수 있는 개발자가 되기 위해 노력합니다.

0개의 댓글