App LifeCycle

Eli·2021년 2월 7일
2

iOS

목록 보기
1/11

iOS의 LifeCycle에 대해선 딱히 별도의 공부나 봐야겠다는 생각은 못했는데, 이번 iOS 공부를 시작하면서 어떤 과정으로 실행되고 종료되는지를 정리 해보면 나름 가치 있는 시간이지 않을까 생각했다.

그리고 최근 iOS 13부터 이상한 Scene이라는 놈이 태어나서 좀 족보가 복잡해졌다랄까나.

아무튼 그 내용도 조금 다뤄보도록 한다.

크게 집중해서 봤던 포스팅들

Apple Developer Documentation

[Apple Dev Reference] 앱 라이프사이클 The App Life Cycle

App State

일단 앱의 생명주기는 크게 5단계를 거친다.

  1. Not Running: iOS앱의 아이콘을 눌렀을 때, 런칭 이미지가 뜨고 처음 실행되는 것 처럼 느꼈다면 이전의 상태는 Not Running 상태였다. 정의를 해보면 아직 실행되지 않았거나 완전희 종료된 상태.
  2. Inactive: 앱이 실행중이지만 어떤 이벤트를 받지 않는 상태. 아래와 같은 경우이다.
    1. 앱을 실행하기 시작할 때.
    2. 전화가 오는등 최상단에 다른 화면으로 보일 때
    3. 백그라운드에서 다시 진입 할 때
  3. Active: 여러분들이 앱을 보고있다면 그 앱은 Active 상태입니다.
  4. Background: 다른 앱으로 전환하거나 홈화면으로 앱을 보고있지 않는 상태이며, 백그라운드 기능을 사용하고 있을 때, Background 상태입니다.
  5. Suspended: Background기능을 사용하지 않은 채로 앱을 보고있지 않은 상태. 만약 일정시간 앱을 보지 않거나 백그라운드 기능을 수행하지 않는다면 이 앱은 메모리에서 해체 되어 완전히 종료될 것이다.

AppDelegate

iOS 프로젝트를 파면 위의 AppDelegate.swift 파일이 생기는데 크게 하는 일은 2가지가 있다.

  1. 앱의 상태변화에 따라 응답할 수 있도록 한다. (아래 예시)
    1. 앱이 시작 됨
    2. 앱이 푸시를 받음
    3. 앱이 꺼짐
    4. ... 많음
  2. 앱의 Entry point, 앱의 이벤트를 받아 전달하는 run loop

전체적으로 앱의 Process Lifecycle과 Session Lifecycle(아래 나올 Scene)들을 관리한다.

상당수 App의 state 변화에 따른 메소드들이 Scene으로 이동이 되었다.

앱의 실행 종료, Scene의 관리가 주된 책임이라고 생각을 하면 된다.

상태 변화에 따른 호출 메소드들을 아래에서 볼 수 있다.

///AppDelegate
//앱의 주요 객체를 생성 및 run loop를 만드는 과정들이 끝나기 직전에 호출
func application(
	_ application: UIApplication, 
	willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) 
-> Bool

//앱의 모든 준비가 마무리 되고 실행직전에 보여준다.
func application(
	_ application: UIApplication, 
	didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) 
-> Bool

///iOS13이상 SceneDelegate
///iOS12이하 AppDelegate

//유저가 앱을 조작할 수 있게 되었을 때 호출.
//메세지/시스템알림/전화 등이 왔다 없어질 때 호출이 될 수 있으므로 초기화 코드들은 배제하는 것이 좋다.
//멈추어져 있던 타이머/메모리를 많이 먹는 작업 등을 다시 시작하는 코드들을 호출하기에 좋다.
func applicationDidBecomeActive(_ application: UIApplication)
func sceneDidBecomeActive(_ scene: UIScene)

//앱이 Active(앱을 잠시 조작할 수 없게됨/백그라운드로 이동함)등의 상황을 거칠때 호출.
//이 역시 한 주기에서 여러차례 호출 될 수 있으며, 타이머등 리소스를 많이 먹는 작업들을 중지시키거나 메모리에서
//해제 시키는 등의 작업에 적합하다.
func applicationWillResignActive(_ application: UIApplication)
func sceneWillResignActive(_ scene: UIScene)

//앱이 inActive 상태로 진입하게 될 때를 가르킨다.
//다른앱에서 전환해 오거나 앱을 처음 실행하게 되거나 같은 경우들이 있다.
func applicationWillEnterForeground(_ application: UIApplication)
func sceneWillEnterForeground(_ scene: UIScene)

//앱이 Background 상태로 들어갔을 때 호출하게 된다.
//주로 백그라운드 업데이트 등 작업이 필요하게 될 때 호출한다. ex) GPS업데이트 등...
func applicationDidEnterBackground(_ application: UIApplication)
func sceneDidEnterBackground(_ scene: UIScene) 

// 몇가지 간혹 볼 수 있는 Delegation

//외부 앱 또는 링크를 열지말지를 리턴하는 함수
//보통 외부 sdk, social login등 구현할 때 자주쓰인다.
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool

//메모리 사용량에 대한 경고
//일반적인 앱을 작업을 할 때 크게 마주하진 않는다.
func applicationDidReceiveMemoryWarning(_ application: UIApplication)

//FCM 등 푸시 작업들을 할 때,
//APNs에서 받은 Token값을 Firebase등으로 넘겨줄 수 있는 함수
func application(_ application: UIApplication, 
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)

//FCM을 통해 푸시 노티를 받았을 경우 호출
//이 역시 Firebase로 넘겨주는 호출을 해주게 된다.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any])

willFinishLaunchingWithOptions 와 didFinishLaunchingWithOptions

해당 차이를 알기 위해선 앱의 상태 저장에 대한 기능을 먼저 알아야한다.

앱 상태 복원 (UIViewControllerRestoration)

Apple Developer Documentation

기본적으로 앱은 언젠가 중지가 되어 앱 라이프사이클의 수명을 다하게 되는데, 이때 최종 ViewController와 그 상태를 저장해 앱을 다시 시작했을 때, 마지막 ViewController와 Data를 그대로 보여주어 유저의 경험을 더 좋게 하고자하는 게 목표인 것 같다.

사실 이게 제대로 이루어지는 서비스를 그렇게 크게 보진 못하지만 애플은 이를 잘하도록 권장하는 것 같다(램을 늘려주면 될텐데...)

Will과 Did의 차이는 마지막에 앱의 상태가 복구가 이루어 졌는지 아직인지에 대한 포인트이다.

왜 Will과 Did중에 Did는 오랜된 것에서 구동이된다 쓰여있으며, Will을 권장하는지에 대한 포인트는 아직 찾지 못했다.

LaunchOptions안에 뭐가 있나?

Apple Developer Documentation

런치옵션에 대한 모든 내용들은 위의 공식문서에 내용이 있다.

해당 정보를 제공해주는 가장 큰 이유는 어떠한 사유로 앱을 시작하게 되었고 그 사유에 따른 런칭 액션들을 할 수 있게 도와주는 것이 목표인 것 같다.

기본적으로 블루투스 데이터 수신, 푸시, 퀵액션 등 다양한 실행할 만한 요소들이 있고 그 요소들의 데이터에 따라 시작 ViewController 들을 달리한다는 등의 기능들을 만들 수 있을 것 같다.

  1. 블루투스 연결 및 이벤트
  2. 위치 업데이트
  3. 유저의 푸시 클릭
  4. 퀵액션 탭
  5. url로 오픈
  6. ... etc

Return False

willFinishLaunchingWithOptions에서 return은 보통 true고 되어있고, 또 false로 처리를 하려는 생각은 할 수 없었다. 딱히 필요도 없고.

공식 문서상에는 URL과 몇몇 레퍼를 찾아보니 Launch Options로 들어온 URL들을 OS 에 알리려는 목적이 가장 큰 것 같다. 이 URL은 우리는 처리하지 않을 것이다. 정도의 목적인 것 같은데...

결국 return false를 하더라도 어떠한 영향도 없을 것 같다는 심심한 결론.

SceneDelegate

iOS 13 이전의 시절에는 없었던 녀석. 왜 필요가 없었나? iOS 앱은 꼭 한개의 세션/화면만 볼 수 있었다.

그러나 아래의 사진과 같은 Multi Window가 생겨나게 되었다.

같은 메모앱을 동시에 2개의 화면으로 실행할 수 있게 된 것이다.

그러므로 이를 대응하기 위해 태어난게 SceneDelegate이다.

여러개의 세션/화면들을 각각 볼 수 있도록 AppDelegate가 하던 일을 어느정도 위임을 받았다.

Scene에는 하나의 인스턴스를 나타내는 windows와 view controllers들이 있다.

Scene은 같은 메모리와 앱 공간을 동시에 실행하면서 즉 위의 아이패드와 같이 여러개의 Scene들이 활성화 될 수 있다.

아래는 기존 AppDelegate에서 하던 몇개의 기능들이 SceneDalegate로 대체되어 1:1 매칭이 되니, 위의 정리를 참고하면 된다.

Deployment Target이 13 이하일 때

12이하의 앱들은 무조건 1개의 window를 가지게 되므로 iOS 13에서 추가된 부분을 삭제하고 이전과 설정하면 동일하게 이용이 가능하다.

아마 추후에 지원버전을 높이는 시점에 SceneDelegate 부분을 좀 많이 건들이게 되지 않을까 싶다.

그러나 Deployment Target이 13이 되려면 앞으로 몇년은 더 걸릴 예정이기 때문에...
그냥 그렇구나 정도로만 생각하고 넘어가면 된다.

profile
애플을 좋아한다. 그래서 iOS 개발을 한다. @Kurly

0개의 댓글