iOS 앱을 개발할 때 가장 먼저 만나게 되는 중요한 친구들이 있죠. 바로 **`AppDelegate`** 클래스와 이 친구가 채택하고 있는 프로토콜 **`UIApplicationDelegate`** 입니다. 이들은 앱의 전체적인 동작과 생명주기를 책임지는, 앱의 심장부 같은 존재예요.
하지만 iOS 13부터는 앱의 구조에 큰 변화가 생겼다는 사실, 알고 계셨나요? 이번 글에서는 `AppDelegate`의 기존 역할과 **iOS 13 이후 `SceneDelegate` 와 어떻게 협력하며 앱의 생명주기를 관리**하는지 쉽고 명확하게 알아보겠습니다.
<br>
<br>
# 1. `AppDelegate`의 역할 변화
![[WWDC_2019_Architecting_Your_App_for_Mulitiple_Windows_Session_Lifecycle.png|center|w80]]
<br>
원래 `AppDelegate` 클래스는 `UIApplicationDelegate` 프로토콜을 채택하여 앱 전체의 라이프사이클을 관리하고 동작을 제어하는 핵심 역할을 수행했습니다.
하지만 iOS 13 이후부터는 상황이 달라졌습니다. iPad의 멀티태스킹이나 다중 윈도우 지원이 중요해지면서, 앱의 라이프사이클을 관리하는 일부 역할이 `SceneDelegate`에게 넘어갔어요.
<br>
> [!question] **잠깐, Scene이 뭔가요?**
> 여기서 **Scene(씬)**이란, **앱의 UI가 화면에 표시되는 인스턴스**를 의미합니다. 예를 들어, 아이패드에서 하나의 앱을 두 개의 윈도우로 열거나, 아이폰에서 앱을 실행할 때 보이는 단일 UI가 각각 하나의 Scene 이라고 이해하시면 편해요.
<br>
현재 `AppDelegate` 와 `SceneDelegate` 는 서로 협력하여 앱의 전반적인 라이프사이클을 관리합니다.
- **`AppDelegate` 의 주요 역할**: **앱의 전반적인 라이프사이클**(앱 시작, 종료, 리소스 관리 등)과 **여러 Scene 간의 상호작용**을 관리합니다.
- **`SceneDelegate` 의 주요 역할:** 주로 **각 Scene에 특화된 라이프사이클 이벤트**를 다룹니다.
<br>
<br>
# 2. 핵심 메서드 살펴보기
`AppDelegate` 에 정의된 주요 메서드들은 앱의 상태 변화나 중요한 이벤트 발생 시 UIKit 에 의해 호출됩니다. 마치 [[ko/domains/iOS/architecture/app lifecycle/iOS 앱의 life cycle 관리하기 (app-based, scene-based)|앱의 생애 주기(Life Cycle)]]에 따라 정해진 시점에 호출되는 약속과 같아요.
## 1. 앱의 시작과 종료 관리
##### `application(_:willFinishLaunchingWithOptions:)`
```swift
optional func application(
_ application: UIApplication,
willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
) -> Bool
```
- **호출 시점**
- **앱 실행 직전**에 가장 먼저 호출됩니다.
- **주요 역할**
- 앱 초기 실행 과정에서 가장 먼저 설정해야 할 항목들(예: 핵심 프레임워크 초기화)이 있다면 여기서 수행할 수 있습니다.
<br>
##### `application(_:didFinishLaunchingWithOptions:)`
```swift
optional func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
) -> Bool
```
- **호출 시점**
- 앱이 **처음 실행될 때** 호출됩니다.
- **주요 역할**
- **초기 설정**과 관련된 코드는 주로 이 메서드에서 수행됩니다.
- **파라미터 설명**
- `launchOption`은 앱이 **외부 이벤트** (예시: 푸시 알림, URL 스키마) 에 의해 시작되었을 때 어떤 이유로 실행되었는지 알려줍니다.
<br>
##### `applicationWillTerminate(_:)`
```swift
optional func applicationWillTerminate(_ application: UIApplication)
```
- **호출 시점**
- 앱이 **종료되기 직전**에 호출됩니다.
- **주요 역할**
- 앱이 종료되기 전에 반드시 저장해야 하거나 정리해야 할 작업이 있다면 여기서 수행합니다.
<br>
<br>
## 2. 앱의 상태 변화 감지 및 대응
##### **`applicationDidBecomeActive(_:)`**
```swift
optional func applicationDidBecomeActive(_ application: UIApplication)
```
- **호출 시점**
- 앱이 **활성화될 때** (Foreground 상태에서 사용자와 상호작용할 수 있는 상태) 호출됩니다.
- **주요 역할**
- 앱이 비활성화 상태에서 돌아왔을 때, **일시 중지되었던 작업들을 다시 시작**합니다.
- 예시: 타이머를 다시 시작하거나, OpenGL 프레임 속도를 조절하는 작업
- 만약 앱이 백그라운드에 있다가 돌아왔다면, **UI를 새로 고치기 위한 코드**를 여기서 수행할 수 있습니다.
<br>
##### `applicationDidEnterBackground(_:)`
```swift
optional func applicationDidEnterBackground(_ application: UIApplication)
```
- **호출 시점**
- 앱이 **백그라운드로 전환될 때** 호출됩니다.
- **주요 역할**
- 여기서는 백그라운드에서 실행될 작업이나 리소스 저장과 같은 작업을 수행합니다.
- 나중에 앱이 완전히 종료되더라도 현재 상태로 복원할 수 있도록 앱의 상태 정보를 저장해야 합니다.
<br>
> [!warning] 잠깐! 백그라운드 작업 시 주의 사항
> `applicationDidEnterBackground(_:)` 메서드 내에서 시간이 많이 소요되는 작업을 할 때는 **주의가 필요합니다**.
>
> 시스템은 이 메서드에서 **최대한 빨리 반환**하는 것을 권장합니다. 보통 **약 5초** 정도의 시간이 주어지는데, 이 시간 내에 메서드를 반환하지 않으면 앱이 강제로 종료되고 메모리에서 제거될 수 있습니다.
>
> 만약 추가 시간이 필요하다면 `beginBackgroundTask(expirationHandler:)` 함수를 호출하여 시간을 요청해야 합니다. 다만, 이 요청 자체도 가능한 빨리 호출해야 합니다. 요청이 승인되기 전에 앱이 일시 중단될 수 있으니, 해당 함수를 호출하는 시점에 특히 유의해야 합니다.
<br>
<br>
## 3. 시스템 이벤트 및 오류 처리
##### `applicationDidReceiveMemoryWarning(_:)`
```swift
optional func applicationDidReceiveMemoryWarning(_ application: UIApplication)
```
- **호출 시점**
- 시스템이 **메모리 부족 상태**를 감지했을 때 호출되는 경고 메서드입니다.
- **주요 역할**
- 이 메서드가 호출되면, **불필요한 리소스를 해제**하거나 메모리 사용을 **최적화**하는 등 메모리 관리가 관련된 작업을 수행해야 합니다.
<br>
##### `application(_:didReceiveRemoteNotification:fetchCompletionHandler:)`
```swift
optional func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
)
```
- **호출 시점**
- **원격 푸시 알림(Remote Push Notification)**을 수신했을 때 호출됩니다.
- **주요 역할**
- 알림을 처리하고 필요한 작업을 수행하는 로직을 이곳에 구현할 수 있습니다.
<br><br><br>
## 3. 더 깊이 알아보기
우리는 `AppDelegate`가 iOS 13 이후 **앱 전반의 라이프사이클과 여러 Scene 간의 상호작용**을 관리하는 '총괄 관리자'로 변화했고, **각 Scene에 특화된 라이프사이클 이벤트**는 `SceneDelegate`가 담당하며 이 둘이 협력한다는 것을 확인했습니다.
하지만 실제 프로덕트 레벨에서 앱의 안정성을 확보하려면, 이 역할 분담의 세부적인 작동 원리를 완벽하게 이해해야 합니다. 특히 **멀티 윈도우 환경**을 지원하거나 **복잡한 백그라운드 작업**을 구현할 때, 두 델리게이트가 시스템과 상호작용하는 방식에 대한 명확한 이해가 필수적입니다.
<br>
이를 돕기 위한 학습 자료 두 가지를 소개합니다.
- [[ko/domains/iOS/architecture/app lifecycle/iOS 앱의 life cycle 관리하기 (app-based, scene-based)]]
- [WWDC 2019 Architecting Your App for Multiple Windows](https://developer.apple.com/videos/play/wwdc2019/258/)
<br>
이로써 `AppDelegate`와 `UIApplicationDelegate`, 그리고 라이프사이클 관리의 핵심 메서드에 대한 탐구를 마칩니다.
<br><br><br><br>