티스토리 뷰

반응형

 

Android 앱 개발을 시작한 초보자부터 다양한 경험을 가진 시니어 개발자까지, Android Task에 대한 이해는 모두에게 중요한 부분입니다. 이번 시간에는 Android의 Task에 대한 개념을 함께 살펴보도록 하겠습니다.

 

 

TASK 란?

Task는 사용자가 앱 내 무언가를 수행하려고 할 때 상호 작용하는 Activity의 집합 입니다. 이러한 Activity은 백스택(Back Stack)에 열린 순서대로 정렬됩니다.

예를들어 문자 앱은 문자를 보여주는 Activity을 가질 수 있습니다. 사용자가 메시지를 선택하면 해당 메시지를 보기위한 새로운 Activity가 열립니다. 이 때 새로운 Activity는 Back Stack 에 추가됩니다. 사용자가 뒤로가기를 탭하거나 제스처를 수행하면 현재 Activity인 사용자가 선택한 메시지 Activity 가 Back Stack 에서 Pop 되어 활동이 제거되고 이전 Activity 인 문자 목록 Activity가 활성화 됩니다.

 

 

TASK 는 Unit으로 구성되어 사용자가 새로운 TASK 을 시작 하던가 홈 버튼 을 통해 홈 화면으로 이동할 때 Background 로 전환 될 수 있습니다. TASK 의 모든 활동은 Background에 있는 동안 중지되지만 백스택 BackStack 은 그대로 유지됩니다.

 

 

예를 들어 현재 ‘Task A’의 백스택(Back Stack)에 두 개의 Activity 가 있다고 가정합니다. 사용자가 홈 버튼을 누러서 앱을 나가고 앱 런처에서 다른 앱을 실행합니다. 그러면 'Task A'는 백그라운드(Background)로 들어가고, 동시에 새로운 'Task B'라는 앱이 시작됩니다. 'Task B'의 화면 중 가장 위에 있는`Activity`이 열리게 됩니다. 사용자가 앱과 상호작용한 후 다시 으로 돌아가서 TASK A를 시작한 앱을 선택합니다. 이때 TASK A가 foreground로 나옵니다. TASK A 의 백스택(Back Stack) 맨 위에 있는 Activity가 다시 시작되며, TASK A 백스택(Back Stack)에 존재한 두 Activity은 모두 그대로 유지됩니다. 또한 이 시점에서 사용자는 TASK B로 다시 전환할 수도 있습니다.

 

 

실행모드 (Launcher Mode) 정의

Launcher Mode 활동의 새로운 인스턴스(Instance)의 현재 작업과 연결되는 방식을 정의할 수 있습니다. 연결되는 방식은 두 가지 방법으로 서로 다른 실행 모드(Launcher Mode) 를 정의할 수 있습니다.

  • manifest 파일 사용manifest 파일에서 Activity을 선언하면 Activity가 시작될 때 Task과 연결되어야 하는 방식을 지정할 수 있습니다.
  • 인텐트(Intent) 플래그 사용startActivity()를 호출할 때 새로운 Actiivity가 현재 Task 과 연결되어야 하는 방식(또는 연결되어야 하는지 여부)을 선언하는 Flag 를 Intent에 포함할 수 있습니다.

manifest 와 intent 동시에 실행모드(Launcher Mode) 정의 시 인텐트(Intent) 에 정의가 manifest에 정의보다 우선합니다.

 

 

Manifest 파일을 활용한 Launcher Mode

manifest 파일에서 활동을 선언할 때 <activity> 요소의 launchMode 속성을 사용하여 활동이 작업과 연결되어야 하는 방식을 지정할 수 있습니다.

launchMode 은 네 가지 실행 모드를 정의할 수 있습니다.

 

❑ Standard

"standard" 은 기본값입니다. 시스템은 활동이 시작된 Task의 새로운 Inastance 생성하고 Intent 을 생성된 Inastance로 라우팅합니다.

 

❑ SingleTop

"singleTop" 은 Activity가 이미 현재 Task의 맨 위에 있으면 시스템은 활동의 새로운 Instance 생성하지 않고 onNewIntent() 메서드를 호출하여 Intent를 기존 instance 로 라우팅합니다.

예를 들어 작업의 백 스택이 루트 활동 A와 활동 B 및 C 그리고 맨 위의 활동 D로 구성되어 있다고 가정합니다. 이때 D 유형 활동의 Intent가 도착합니다. D에 기본 "standard" 실행 모드(Launcher Mode)가 있으면 클래스의 새로운 Instance가 실행되고 스택이 A-B-C-D-D가 됩니다. 하지만 D의 실행 모드(Launcher Mode)가 "singleTop"이면 D의 기존 인스턴스는 onNewIntent()를 통해 도착한 인텐트를 받습니다. 따라서 스택은 계속 A-B-C-D로 유지됩니다. 만약, A-B-C-D로 구성된 백스택에 B 유형 Activity의 Intent가 도착하면 B의 새로운 Instance가 스택에 추가됩니다. B의 실행모드(Launcher Mode)가 "singleTop"이더라도 동일하게 새로운 Instance 가 스택에 추가됩니다.

 

 

❑ SingleTask

"singleTask"시스템이 새로운 Instance 를 생성하고 새로운 Task 루트에 있는 활동을 인스턴스화합니다. 만약, Activity의 인스턴스가 이미 별도의 Task 에 있다면 시스템은 새로운 Instance 를 생성하지 않고 onNewIntent() 메서드를 호출하여 인텐트를 기존 Instance로 라우팅합니다. Activity의 Instance가 한 번에 하나만 존재할 수 있습니다.

 

예를들어 <activity> 요소의 singleTask 실행 모드를 지정한 A 앱이 있다고 가정하겠습니다. 즉, 이 A 앱을 여는 Intent를 발행하면 이 활동은 앱과 동일한 TASK에 배치되지 않습니다. 대신 해당 A 앱에서 New Task 가 시작되거나, A 앱에 이미 백그라운드에서 실행 중인 작업이 있다면 그 작업이 포그라운드로 나와 New Intent를 처리합니다.

 

Activity 가 New Task 에서 시작되었든 또는 Activity 가 시작된 Task과 동일한 Task에서 시작되었든 관계없이 사용자는 뒤로 버튼을 통해 항상 이전 Activity 로 돌아갈 수 있습니다. 그러나 singleTask 로 실행 모드(Launcher Mode)를 지정한 Activity을 시작했는데 그때 Activity의 instance가 백그라운드 작업에 존재하면 해당 Task가 포그라운드로 이동합니다. 백스택(Back Stack)에는 앞으로 나온 Task의 모든 Activity가 스택의 맨 위에 포함되어 있습니다.

 

 

참고: 활동이 새 작업에서 시작되더라도 사용자는 여전히 뒤로 버튼을 통해 이전 활동으로 돌아갈 수 있습니다.

 

❑ SingleInstance

"singleInstance""singleTask"와 동일하지만 시스템이 Instance 보유한 Task으로는 어떤 다른 Activity도 실행하지 않는 점이 다릅니다. Activity는 Task에 하나만 존재합니다. singleInstance에서 startActivity 로 실행하는 모든 Activity은 별도의 작업으로 열립니다.

 

번외) Launcher Mode 를 SingleTask 로 선언 하지 않은 Activity을 타 앱에서 실행한다면 어떻게 될까?

일반적으로, 제휴 진입 시 호출하는 Activity실행 모드(Launcher Mode)는 주로 singleTask로 설정되어 새로운 작업(New Task)을 생성하거나 이미 백그라운드에 해당 Activity 인스턴스가 존재하는 경우 New Intent가 발생하도록 하는 경우가 많습니다. 그러나 특정 상황을 가정해볼 때, 제휴 진입하는 Activity의 실행 모드(Luancher Mode)manifest에서 standard 또는 singleTop으로 설정된 경우를 생각해보겠습니다. 이러한 경우에, 제휴 진입 시 호출되는 Activity의 작업(Task) 위치는 호출하는 앱의 실행 모드(Launcher Mode)에 따라 결과가 다를 수 있습니다.

 

호출부의 실행모드(Launcher Mode) 제휴 Activity Task 위치
standard singleTop singeTask 호출부의 Task
singleInstance New Task

 

호출하는 앱의 실행 모드 중 singleInstance 를 제외한 다른 모든 실행 모드(Launcher Mode)에서는 호출한 앱의 작업(Task)을 활용하는 것을 확인할 수 있습니다. 이러한 접근 방식은 개발자의 의도와는 달리 사용자는 호출하는 앱을 통해 제휴 앱을 사용하게 되며, 동시에 별도의 제휴 앱 실행 할 수 있게 됩니다. 이러한 점으로 인해 동일한 제휴 앱이 중복 생성되는 문제가 발생할 수 있습니다.

 

 

호출하는 앱에서 제휴 앱을 실행시키는 과정에서 앱의 독립성이 상실되며, 사용자 경험 측면에서는 혼란스러운 상황이 발생할 수 있습니다. 따라서 제휴 앱 진입 시에는 해당 Activity실행 모드(Launcher Mode)singleTask로 설정하여, 제휴 앱이 호출한 앱의 작업(Task) 내에서 실행되도록 조정하는 것이 바람직합니다.

 

 

이러한 접근 방식을 통해 사용자는 자연스럽게 제휴 앱을 이용할 수 있으며, 동시에 중복된 제휴 앱 생성으로 인한 문제도 방지할 수 있습니다.

 

 

마무리

시간을 내어 TASK에 대한 이해를 다시 해보는 것은 개발자들에게 중요한 일입니다.

이번 글에서는 다루지 않았지만, Taskaffinity를 활용한 Activity가 속하는 Task 설정 및 백스택(Back stack)을 클리어하는 처리 방법 등 다양한 Task 처리 방법이 있습니다. 자세한 내용은 Android Developer 사이트에서 확인하는 것을 추천합니다.

이번 글을 통해, 무심코 지나쳤던 Task에 대한 개념을 다시 한 번 살펴보고, 현재 진행 중인 프로젝트에서 이 개념을 얼마나 잘 활용하고 있는지 점검해 보는 것이 좋을 것입니다.

 

 

참고

https://ogyong.tistory.com/46

https://programmingfbf7290.tistory.com/entry/안드로이드-태스크-launchMode-Intent-플래그-총정리

https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko

반응형
댓글