[Android] popBackStack vs navigateUp

우발자·2025년 9월 12일
1

안드로이드 개발을 하면서 Jetpack Navigation을 이용하여 화면간에 이동을 많이 해보았다. 그러면서 종종 겪는 문제가 있다.

바로 이런 문제일 것이다. A에서 B로 이동 후 B에서 화면을 터치하면 popBackStack을 호출하는 앱이다.
B에서 A로 popBackStack이 호출되면 애니메이션이 발생하면서 최상위 스택이 제거가 되는데 애니메이션이 발생할 때 터치를 여러번하여 popBackStack이 2번 호출되어 NavHost까지 제거되기 때문이다.

popBackStack의 내부로직


(NavController.kt#executePopOperations) 에서 복잡한 내부 코드들 중 일부를 가져왔다.

여기서 popBackStackInternal이란 확장함수의 내부를 타고 가보면 이런 로직이 있다.

  1. popBackStack()을 실패했을 경우 (현재 백스택이 존재하지 않을 경우)
  2. popUpTo로 설정한 범위까지 순회했을 경우

이 두경우일 때 위에 콜백함수로 백스택 엔트리에서 제거해준다.

그래서 왜 이런일이 발생할까?


현재 로직을 보면 backQueue가 비어있지 않을 때 popBackStack을 동작한다.
backQueue가 비어있지 않을 때 동작하는게 맞지 않나? 라고 생각할 수 있지만
backQeueu에선 기본적으로 destination만 포함하고 있는게 아니다.
navGraph도 포함하고 있다. 그래서 destination이 없어도 navGraph만 존재하더라도 동작을 하기 때문에 navHost가 제거 될 수 있다.

navigateUp은 내부 구조가 조금 다르다.

destinationCountOnBackStack이라는 변수는 NavGraph가 아닌 진짜 destination으로만 카운트한 값이다.

이 값이 1일때 그니깐 최상단 스택만 남아있을 때는 딥링크로 들어왔는지에 대해 체크하는 로직을 하고 popBackStack() 함수를 호출 하진 않는다. 그래서 navigateUp에선 최상단 화면을 보장받을 수 있다.

그리고 딥링크 관련해서는 다른앱에서 딥링크로 앱을 들어왔을 시 navigateUp을 호출하면 호출했던 앱으로 이동하게 된다.


결론

navigateUp 과 popBackStack은 동작은 비슷해보이지만 가지고 있는 성질은 다른 것 같다.

navigateUp은 사용자의 진입점에 따라 돌아가기 위해 사용하면 될 것 같고
popBackStack은 말그대로 현재 백스택 뿐만 아니라 자기가 원하는 범위만큼 스택을 제거할 때 사용하면 될 것 같다.

profile
어제보다 나은 개발자가 되자

0개의 댓글