> **사용자 경험을 유지하고 앱의 성능을 최적하하기 위해 앱의 상태(e.g. foreground, background) 변화에 따라 수행할 작업을 이해하고 처리하자.**
<br>
## 개요
iOS 앱의 상태(state) 변화에 따라 앱이 수행할 수 있는 작업과 할 수 없는 작업이 나뉜다.
예시
- **foreground** 상태: 화면에 표시되고 있는 상태로, CPU와 같은 리소스를 사용할 때 우선권을 가진다.
- **background** 상태: 화면에서 벗어난 상태로, 최소한의 작업을 수행하거나 아예 아무 작업도 하지 않아야 한다. (리소스를 최소한으로 사용하는 것이 중요함)
<br>
앱의 상태가 변할 때마다, UIKit은 적절한 delegate 객체의 메서드를 호출하여 해당 상태 변화에 대응할 수 있도록 한다.
- **iOS 13 이후, scene-based 앱에서는 [[Scene과 UISceneDelegate|UISceneDelegate]] 객체를 사용하여 라이프사이클 이벤트에 대응한다.**
- **iOS 12와 그 이전에는 [[AppDelegate와 UIApplicationDelegate|UIApplicationDelegate]] 객체를 사용하여 라이프사이클 이벤트에 대응한다.**
<br>
>만약 앱에서 scene support를 활성화했다면 iOS 13 이후에는 항상 scene delegates가 사용되며, iOS 12와 그 전에는 app delegate가 사용된다.
<br><br>
## scene-based 라이프사이클에 대응하기
iOS 앱이 [[Scene과 UISceneDelegate|scene]]을 지원할 경우, **각 scene에 대한 별도의 라이프사이클 이벤트가 제공된다.**
<span style="color:gray;">여기서 scene은 디바이스에서 실행 중인 앱의 UI의 하나의 인스턴스를 나타낸다. </span>
사용자는 각 앱에 대해 **여러 개의 scene**을 생성하고 따로따로 표시하거나 숨길 수 있다.
각 scene은 고유의 라이프사이클을 갖기 때문에 서로 다른 실행 상태에 있을 수 있다.
예를 들어, 한 scene이 foreground에 있을 때, 다른 scene들은 background에 있거나 일시 중지된 상태에 있을 수 있다.
<br>
>scene support는 앱에게 선택적인 기능(opt-in feature)이다. 이를 활성화하려면 앱의 `Info.plist` 에 `UIApplicationSceneManifest` 키를 추가해야 한다.
<br><br>
#### scene을 통한 상태 전환
![[scene_based_life_cycle.png|center|400]]
<br>
- 새로운 scene이 앱에 대한 사용자 또는 시스템의 요청으로 생성되면, UIKit은 이를 **"unattached"** 상태로 만든다.
- 사용자 요청에 의한 scene은 빠르게 foreground로 이동하여 화면에 나타난다.
반면 시스템 요청에 의한 scene은 일반적으로 이벤트를 처리하기 위해 background로 이동한다.
<span style="color:gray;">예를 들어, 시스템은 위치와 관련된 이벤트를 처리하기 위해 background에서 scene을 시작할 수 있다.</span>
- 사용자가 앱 UI를 닫으면 UIKit은 관련된 scene을 background 상태로 이동시키고, 나중에는 중단된(suspended) 상태로 전환한다.
> **UIKit은 언제든지 background에 있거나 중단된 scene을 연결 해제하여 리소스를 회수할 수 있으며, 이렇게 되면 해당 scene은 "unattached" 상태로 돌아간다.**
<br><br>
#### scene 전환 때 수행할 작업 ✨
- **scene이 앱에 연결될 때** 초기 UI를 구성하고 scene이 필요로 하는 데이터를 로드한다.
- **foreground-active 상태로 전환될 때** UI를 구성하고 사용자와 상호작용하기 위해 준비한다.
- **foreground-active 상태에서 빠져나갈 때** 데이터를 저장하고 앱의 활동을 최소화한다.
- **background 상태로 전환될 때** 중요한 작업을 완료하고 최대한의 메모리를 해제하며 app snapshot을 준비한다.
- **scene이 연결 해제될 때**, scene과 관련된 공유 리소스를 정리한다.
- scene과 관련된 이벤트뿐만 아니라, **앱이 시작될 때** `UIApplicationDelegate` 객체를 사용하여 앱의 실행에 응답해야 한다.
- [Responding to the launch of your app](https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app) 참조하기
<br>
> **app snapshot**
> 사용자가 앱을 종료하거나 다른 앱으로 전환할 때 앱의 현재 상태와 UI의 이미지를 저장하는 개념.
> 이를 통해 사용자가 다시 앱을 열 때 앱이 마지막으로 종료되었을 때와 같은 상태로 빠르게 복원될 수 있다.
<br><br>
## app-based 라이프사이클에 대응하기
**iOS 12 및 그 이전 버전, 그리고 scene을 지원하지 않은 앱에서는 모든 라이프사이클 이벤트가 UIKit에 의해 `UIApplicationDelegate` 객체로 전달된다.**
app delegate는 앱의 모든 window를 관리하며, 여기에는 별도의 화면에 표시되는 window도 포함된다.
따라서 앱 상태 전환은 앱의 전체 UI에 영향을 미치며, 외부 디스플레이에 표시된 내용도 포함된다.
<br><br>
#### app delegate를 통한 상태 전환
![[app_based_life_cycle.png|center|400]]
<br>
- 시스템은 앱을 실행한 후, UI가 화면에 나타나기 전에 앱을 inactive 또는 background 상태로 둔다.
- foreground로 실행되면 시스템은 자동으로 앱을 active 상태로 전환한다. 그 이후에는 앱이 종료될 때까지 active와 background 상태 간을 오가게 된다.
<br><br>
#### app 전환 때 수행할 작업
- **앱 런치 시,** 앱의 데이터 구조 및 UI를 초기화한다.
- **active 상태로 전환될 때**, UI를 설정하고 사용자와 상호작용하기 위해 준비한다.
- **inactive 상태로 전환될 때**, 데이터를 저장하고 앱의 활동을 최소화한다.
- **background 상태로 전환될 때**, 중요한 작업을 완료하고 최대한의 메모리를 해제하며 app snapshot을 준비한다.
- **앱 종료 시**, 즉시 모든 작업을 중단하고 모든 공유 리소스를 해제한다.
- [[AppDelegate와 UIApplicationDelegate#^036e79|applicationWillTerminate(_:)]] 참조하기
<br>
<br>
## 라이프사이클 이벤트 이외의 중요한 이벤트
iOS 앱은 라이프사이클 이벤트 이외에도 다양한 중요한 이벤트에 대응할 수 있어야 한다.
이러한 이벤트들은 `UIApplicationDelegate` 객체를 통해 처리될 수 있으며, 때로는 알림(notifications)을 사용하여 앱의 다른 부분에서도 처리할 수 있다.
1. **Memory warnings:**
- 앱의 메모리 사용량이 너무 높을 때 발생하는 이벤트. 메모리 사용을 줄이는 등의 조치를 취해야 한다.
- [[AppDelegate와 UIApplicationDelegate#^89e449|applicationDidReceiveMemoryWarning(_:)]] 메서드 사용
- [Responding to memory warnings](https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle/responding_to_memory_warnings) 참조하기
2. **Protected data becomes available/unavailable:**
- 사용자가 디바이스를 잠금 또는 잠금 해제할 때 발생하는 이벤트
- `applicationProtectedDataDidBecomeAvailable(_:)` 및 `applicationProtectedDataWillBecomeUnavailable(_:)` 메서드 사용
3. **Handoff tasks:**
- `NSUserActivity` 객체를 처리해야 할 때 발생하는 이벤트.
- `application(_:didUpdate:)` 메서드 사용
4. **Time changes:**
- 전화 통신사가 시간 업데이트를 보낼 때와 같은 여러 시간 변경 이벤트에 대한 처리.
- `applicationSignificantTimeChange(_:)` 메서드 사용
5. **Open URLs:**
- 앱이 리소스를 열어야 할 때 발생하는 이벤트.
- `application(_:open:options:)` 메서드 사용
<br>
<br>
<br>
---
**참고 문서**
https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
**추천 링크**
[Preparing your UI to run in the foreground](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_foreground)
[ Preparing your UI to run in the background](https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background)
<br>
<br>
<br>
<br>