현재 운영 중인 있는 앱에 SAA(Single Activity Architecture) 패턴을 적용하여, MainActivity 을 제외한 모든 화면을 프래그먼트로 관리하고 있다.
이를 효과적으로 구현하기 위한 도구가 Jetpack 의 Navigation Component 이다.
다만 백스택 관리에 주의가 필요 하고, 기존의 뷰모델의 데이터를 공유하기 위해 ActivityViewModel 을 사용했다면 이제는 navGraphViewModel, Hilt 를 사용한다면 hiltNavGraphViewModel 을 사용하는 것이 좋다. Activity는 그저 앱의 진입 포인트(entry point) 역할을 하는것이 권장 사항이기 때문이다.
이번 글에서는 백스택 관리시 유의해야할 점을 간략하게 적어보도록 하겠다.
ex) 회원가입, (게시글등의) 등록 폼
이럴 경우 C->A 로 가는 action 에서 popUpTo와 popUpToInclusive 옵션을 설정해주어야 한다. (중간 화면들에서는 뒤로가기, 다음으로 이동 등을 통해 이전에 작성한 입력들을 수정할 수 있어야 하기 때문이다)
<action
android:id="@+id/action_c_to_a"
app:destination="@id/a"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim"
app:popUpTo="@id/a"
app:popUpToInclusive="true" />
위의 예시 코드를 확인해보면 popUpTo 옵션에는 a 프래그먼트를 popUpToInclusive 옵션으로는 true 를 지정한 것을 확인할 수 있다.
이렇게 설정해준 이유는 기본적으로 navigate 함수로 다음화면으로 이동할 경우 백스택에 top 에 계속해서 화면이 쌓이는 구조이기 때문에
A -> B -> C -> A 순으로 화면이 쌓이게 된다.
따라서 B까지만 백스택을 지워주게 될 경우
결과적으로 A -> A 가 되고, 화면에서 시스템 백버튼을 한번 눌를 경우 다시 A 화면이 보이게 된다.
따라서 A화면까지 지정하여(popUpTo) A를 지워지는 화면에 포함되도록(popUpToInclusive = true) 설정해줘야한다.
action 수행시 popUpTo 로 지정한 화면까지를 지워야하는데 해당 화면이 백스택에 존재히지 않기 때문에 action 수행시, 설정 pop() 을 수행하지 않고(백스택을 지우지 않고), 다음 화면으로 이동하게 된다. 따라서 시스템 백버튼을 눌러보면 보이지 않아야 할 화면이 출력되어 문제가 발생할 수 도 있다.
ex) 로그아웃을 했는데 시스템 백 버튼을 누르니 그 이전의 화면인 설정 화면으로 돌아가버리는 경우..
global 한 action 일 경우(ex 로그아웃, 토큰이 만료되어 로그인화면으로 돌아가는 경우) 2번과 같은 상황이 나올수있기 때문에 이를 유의해야 한다.