JUN0.DEV
JUN0.DEV

Android Fragment 생명주기와 savedInstanceState 문제 해결 기록

Published on
  • avatarJunyoung Yang

학교 편의 앱을 만들던 중, Bottom Navigation으로 전환하던 Fragment 화면이 앱 복귀 후 잘못 표시되는 문제가 있었다. 시간표, 급식, 공지사항처럼 여러 화면을 Fragment로 나눠 보여주는 구조였고, 사용자가 잠깐 다른 앱을 열었다가 돌아오면 의도하지 않은 화면이 함께 보이는 경우가 있었다.

당시에는 Android 생명주기를 충분히 이해하지 못한 상태였다. 코드상으로는 Fragment를 showhide로 잘 전환하고 있다고 생각했지만, 실제 기기에서는 앱이 백그라운드에 갔다 돌아오는 상황에서 상태가 깨졌다. 이 글은 그 문제를 추적하면서 savedInstanceState를 이해하게 된 초기 프로젝트 기록이다.

처음 보인 문제

화면 구성은 아래와 같았다.

  • 하나의 FrameLayout 위에 여러 Fragment를 올린다.
  • Bottom Navigation을 누르면 선택한 Fragment만 show한다.
  • 나머지 Fragment는 hide한다.

일반적인 사용 흐름에서는 문제가 없어 보였다. 하지만 앱을 잠깐 벗어났다가 다시 돌아오면, 숨겨져 있어야 할 Fragment가 다시 보이거나 선택 상태와 실제 화면이 어긋나는 문제가 발생했다.

단순 UI 버그처럼 보였지만, 재현 조건이 일정하지 않아 원인을 찾기 어려웠다.

원인을 확인한 과정

처음에는 Fragment 전환 코드의 문제라고 생각했다.

  • showhide 호출 순서가 잘못됐는지 봤다.
  • Bottom Navigation 선택 상태가 어긋나는지 확인했다.
  • FragmentManager 트랜잭션이 비동기로 처리되는 문제인지 의심했다.
  • 여러 언어의 검색 결과를 찾아보며 비슷한 사례를 확인했다.

하지만 코드 한 줄만 고쳐서 해결되는 문제가 아니었다. 실제 원인은 Android가 백그라운드 앱을 복원하는 방식과 관련돼 있었다.

savedInstanceState를 확인했다

Android는 메모리 상황에 따라 백그라운드에 있는 앱 프로세스를 종료할 수 있었다. 사용자가 다시 앱으로 돌아오면 시스템은 이전 상태를 복원하려고 한다. 이때 Activity와 Fragment 상태가 savedInstanceState를 통해 복원된다.

문제는 제가 Fragment 표시 상태를 직접 관리하고 있었지만, 현재 선택된 Fragment 정보를 제대로 저장하고 복원하지 않았다는 점이었다.

그래서 프로세스가 재생성되는 흐름에서는 제가 생각한 초기 상태와 시스템이 복원한 Fragment 상태가 어긋날 수 있었다.

해결 방안

현재 선택된 Fragment 인덱스를 onSaveInstanceState에 저장하고, Activity가 다시 생성될 때 그 값을 복원하도록 정리했다.

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("currentFragment", currentFragmentIndex);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (savedInstanceState != null) {
        currentFragmentIndex = savedInstanceState.getInt("currentFragment", 0);
    }

    showOnlyCurrentFragment(currentFragmentIndex);
}

핵심은 화면 전환 로직만 맞추는 것이 아니라, 앱이 다시 만들어질 때도 같은 화면 상태를 재현할 수 있게 만드는 것이었다.

적용 후 달라진 점

이 문제는 오래 추적했던 기억이 있다. 당시에는 코드가 실행되는 순서만 보면 맞는 것처럼 보였기 때문이다.

하지만 모바일 앱에서는 사용자가 화면을 보는 동안에도 운영체제가 앱 프로세스와 상태를 관리한다. 그래서 앱 내부 코드만 보는 것이 아니라, 플랫폼이 언제 Activity와 Fragment를 다시 만드는지도 함께 확인해야 했다.

이후 Android 문제를 볼 때는 아래 순서를 먼저 확인한다.

  • 단순 클릭 흐름에서만 재현되는 문제인지
  • 백그라운드 복귀나 회전 같은 생명주기 이벤트에서 재현되는지
  • 상태를 직접 들고 있다면 저장과 복원을 함께 처리했는지
  • 공식 문서에서 플랫폼 동작을 먼저 확인했는지

마무리

이 글은 현재 주력 백엔드 작업이라기보다, 초기에 디버깅 방식을 배웠던 기록이다.

정리한 기준은 단순했다.

  • 화면 상태는 코드 안의 변수만으로 유지된다고 가정하지 않는다.
  • 플랫폼이 객체를 다시 만들 수 있는 상황을 고려한다.
  • UI 버그처럼 보여도 생명주기 문제일 수 있다.
  • 검색 결과보다 공식 문서의 생명주기 설명을 먼저 확인한다.

당시에는 작은 앱의 Fragment 문제였지만, 이 경험 이후로 "내 코드가 맞아 보인다"와 "실행 환경까지 고려했을 때 맞다"는 다르다는 점을 더 의식했다.