화면이 쌓이는 스택. 태스크(task) 단위로 관리된다.
태스크 = 사용자가 인식하는 '하나의 작업 흐름'
-
최근 앱 목록의 카드 하나가 태스크 하나다
-
[A] → [A,B] → [A,B,C]
-
뒤로가기 → [A,B] → [A] → 홈
launchMode — 쌓이는 방식을 바꾼다
-
standard — 기본. 매번 새 인스턴스를 쌓는다
- [A,B,B,B] 처럼 같은 화면이 중복될 수 있다
-
singleTop — 맨 위에 이미 있으면 새로 만들지 않고 onNewIntent 를 부른다
- 알림을 연달아 눌러도 화면이 겹겹이 쌓이지 않는다
-
singleTask — 태스크에 하나만. 위에 쌓인 것들을 전부 걷어낸다
- 앱의 진입 화면(런처)에 흔히 쓴다
-
singleInstance 자기 혼자만의 태스크를 갖는다. 거의 쓰지 않는다
// singleTop 을 코드로도 지정할 수 있다
val intent = Intent(this, DetailActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
startActivity(intent)
// singleTop 인 화면은 재사용되므로 새 데이터를 여기서 받는다
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent) // ★ 안 하면 getIntent() 가 옛 것을 준다
render(intent.getLongExtra("id", -1))
}
알림에서 들어올 때 — TaskStackBuilder
val pending = TaskStackBuilder.create(this)
.addNextIntentWithParentStack(Intent(this, DetailActivity::class.java))
.getPendingIntent(0, PendingIntent.FLAG_IMMUTABLE)
알림으로 상세 화면에 바로 들어가면 백스택이 비어 있다
- 뒤로가기를 누르면 앱이 그냥 종료된다 (사용자는 목록을 기대한다)
addNextIntentWithParentStack 이 부모 화면들을 함께 쌓아 준다
면접 함정
- ❌ "백스택은 Activity에만 있다" → Navigation Component도 자체 백스택을 관리한다. 층이 두 개가 된다.
- ❌ "singleTask를 쓰면 안전하다" → 위에 쌓인 화면을 전부 파괴하므로, 사용자가 진행 중이던 작업이 사라질 수 있다.
뒤로가기 vs 위로(Up)
- 뒤로가기 — '시간순' — 방금 온 곳으로 돌아간다
- 위로 — '계층순' — 부모 화면으로 올라간다
앱 안에서 목록 → 상세로 왔다면 둘이 같다 알림으로 상세에 바로 들어왔다면 다르다
- 뒤로가기 → 앱 종료 (온 곳이 없다)
- 위로 → 목록 화면 (계층상의 부모)
태스크 간 이동
내 앱에서 카메라 앱을 인텐트로 부르면
- 카메라 Activity 가 '내 태스크 위에' 올라온다 (기본)
- 최근 앱에서는 여전히 카드 하나로 보인다
FLAG_ACTIVITY_NEW_TASK 를 주면 별도 태스크가 된다
- 최근 앱에 카드가 두 개 생긴다
FLAG_ACTIVITY_CLEAR_TOP
Intent(this, HomeActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
스택에 이미 있으면 그 위를 전부 걷어내고 그것을 맨 위로 만든다 로그아웃 시 "모든 화면을 닫고 로그인 화면으로" 에 쓴다
- Navigation Component 를 쓴다면 popUpTo 로 같은 일을 한다
- 두 층(Activity 스택 · Navigation 스택) 을 섞어 쓰면 추적이 어려워진다