안녕하세요, iOS 개발하는 루피입니다!
오늘은 애플 공식문서를 바탕으로 App의 Life cycle에 대해 공부하고 정리해 보는 시간을 갖도록 하겠습니다.
자 그러면 바로 들어가 보도록 하겠습니다!
개요
앱의 현재 상태는 앱의 특정 시점에서 수행할 수 있는 작업과 수행할 수 없는 작업을 결정합니다.
예를 들어
Foreground 에 있는 앱은 사용자의 주의를 받고 있으며, CPU와 같은 시스템 자원에서 우선순위를 가집니다.
반면, Background 에 있는 앱은 화면 밖에 있으므로, 가능한 한 적은 작업만 수행하거나 아예 작업을 하지 않은 것을 권장됩니다.
이처럼 앱의 상태가 변경될 때마다, 해당 상태에 맞게 앱의 동작을 조정해야 합니다. UIKit은 앱의 상태가 변경될 때 적절한 Delegate 객체의 메서드를 호출하여 이를 알려줍니다.
- iOS 13 이상: Scene 기반 앱에서는 "UISceneDelegate" 객체를 사용하여 생명 주기 이벤트에 응답합니다.
- iOS 12 이하: "UIApplicationDelegate" 객체를 사용하여 생명 주기 이벤트에 응답합니다.
Note
iOS 13 이상에서 Scene 지원을 활성화하면, iOS는 항상 Scene Delegate를 사용합니다.
iOS 12 이하에서는 AppDelegate가 생명 주기 이벤트를 처리합니다.
여기서 잠깐, 저는 몇가지 의문이 들었는데요? 그 의무들을 정리해 보도록 하겠습니다.
Q ) 그렇다면 왜 "UISceneDelegate"로 바꾼거지?
A ) iOS 12 이하에서는 Scene 개념이 없었기에 AppDelegate는 단일 window만 가질 수 있지만, iOS 13에서는 멀티 window 지원을 위해 Scene 기반 생명 주기 관리가 도입되었습니다. 이로써 이제 앱은 여러 개의 Scene을 가질 수 있으며, 각 Scene은 독립적으로 상태를 관리합니다.
Q ) 그렇다면 이제 AppDelegate는 필요가 없는 거네?
A ) 아뇨. 앱 전체에 대한 이벤트는 여전히 “UIAppplicationDelegate”가 처리하지만, 각 Scene에 대한 이벤트는 UISceneDelegate가 처리하게 된 것입니다.
Q ) 그렇다면, 앱 전체에 대한 이벤트와 각 Scene 관련 이벤트는 무엇인가?
A ) 예를 들어 앱 전체 관련 이벤트로는 푸시 알림 등록이나 앱 시작 시 초기 설정 같은 것이 있으며, Scene 관련 이벤트는 특정 화면의 활성화/ 비활성화 상태 관리가 있습니다.
Q ) 아 근데 UIKit은 앱의 상태가 변경될 때 적절한 델리게이트 객체의 메서드를 호출하여 이를 알려준다는 말이 무슨 말이지? 와닿지가 않는데...
A ) iOS앱은 실행 중에 여러 상태로 전환됩니다. 예를 들어 활성화, 비활성화, 백그라운드 등이 있는데요 이러한 상태 변화가 발생할 때, 유킷은 개발자에게 이를 알려주기 위해 적절한 델리게이트 객체의 메서드를 호출합니다. 좀 더 자세히 보도록 하겠습니다.
예를 들어
앱이 활성화되면 `applicationDidBecomeActive(_:)` 또는 `sceneDidBecomeActive(_:)` 메서드를 호출합니다.
앱이 백그라운드로 전환되면 `applicationDidEnterBackground(_:)` 또는 `sceneDidEnterBackground(_:)` 메서드를 호출합니다.
문장이 이해되시나요? 이해가 됐다면 오케이입니다.
Scene 기반 생명 주기 이벤트에 응답하기
Scene을 지원하는 앱에서는 UIKit이 각 Scene에 대해 개별적인 생명 주기 이벤트를 전달합니다. Scene은 기기에서 실행 중인 앱 UI의 하나의 인스턴스를 나타냅니다. 사용자는 하나의 앱에서 여러 Scene을 생성할 수 있으며, 각 Scene을 개별적으로 표시하거나 숨길 수 있습니다. 각 Scene은 독립적인 생명 주기를 가지며, 서로 다른 실행 상태를 가질 수 있습니다.
예를 들어
- 한 Scene은 Foreground에 있을 수 있고,
- 다른 Scene은 Background에 있거나 Suspended 상태일 수 있습니다.
Important
Scene 지원은 선택적으로 활성화할 수 있는 기능입니다. Scene 지원을 활성화하려면, 앱의 Info.plist 파일에 UIApplicationSceneManifest 키를 추가해야 합니다.
(Specifying the scenes your app supports 문서에서 자세히 설명되어 있다고 합니다!)
Scene 상태 전환
- 새로운 Scene 요청할 때
- 사용자가 새로운 Scene을 요청하거나 시스템이 특정 작업을 위해 Scene을 요청하면, UIKit은 해당 Scene을 생성하고 초기 상태인 Unattached 상태로 둡니다.
- Foreground로 전환
- 사용자가 요청한 Scene은 화면에 표시되며, 빠르게 Foreground 상태로 이동합니다.
- 이 상태에서 Scene은 사용자와 상호작용할 준비가 됩니다.
- Background로 전환
- 시스템이 특정 이벤트를 처리하기 위해 Scene을 요청하면, 해당 Scene은 주로 Background 상태로 이동합니다.
- 예를 들어 시스템이 위치 이벤트를 처리하기 위해 Background에서 Scene을 실행.
- 사용자가 UI를 닫음
- 사용자가 앱의 UI를 닫으면 UIKit은 해당 Scene을 Background 상태로 이동시키고, 이후에는 Suspended 상태로 전환합니다.
- Unattached로 복귀
- UIKit은 필요하지 않은 리소스를 회수하기 위해 백그라운드 또는 Suspended 된 Scene을 언제든 Unattached 상태로 전환할 수 있습니다.

Scene 전환을 활용하여 다음 작업을 수행하세요
- Scene 연결 시 초기 UI 구성 및 데이터 로드
- UIKit이 Scene을 앱에 연결할 때, 해당 Scene의 초기 UI를 설정하고 필요한 데이터를 로드합니다.
- Foreground-Active 상태로 전환 시 사용자와 상호작용 준비
- Scene이 Foreground-Active 상태로 전환될 때, UI를 구성하고 사용자와 상호작용할 준비를 합니다.
- 관련 내용은 Preparing your UI to run in the foreground를 참고하면 좋을 거 같습니다!
- Foreground-Active 상태를 떠날 때 데이터 저장 및 앱 동작 조정
- Scene이 Foreground-Active 상태를 떠날 때, 데이터를 저장하고 앱의 동작을 조용히 유지하도록 조정합니다.
- 관련 내용은 Preparing your UI to run in the background를 참고하면 좋을거 같습니다!
- Background 상태로 진입 시 중요한 작업 완료 및 메모리 확보
- Scene이 Background 상태로 전환될 때, 중요한 작업을 완료하고 가능한 많은 메모리를 해제하며, 앱 스냅샷 준비를 완료합니다.
- 관련 내용은 Preparing your UI to run in the background를 참고하면 좋을 거 같습니다!
- Scene 연결 해제 시 공유 리소스 정리
- Scene이 연결 해제될 때, 해당 Scene과 관련된 모든 공유 리소스를 정리합니다.
- 추가 사항
- Scene과 관련된 이벤트 외에도, 앱이 실행될 때 UIApplicationDelegate 객체를 사용하여 응답해야 합니다.
- 앱 실행 시 수행해야 할 작업에 대한 자세한 내용은 Responding to the launch of your app를 참고하면 좋을거 같습니다!
앱 기반 생명 주기 이벤트에 응답하기
iOS 12 이하와 Scene을 지원하지 않는 앱에서는 UIKit이 모든 생명 주기 이벤트를 UIApplicationDelegate 객체에 전달합니다.
App Delegate는 앱의 모든 Window을 관리하며, 외부 디스플레이에 표시된 콘텐츠를 포함한 앱 전체 UI에 영향을 미치는 상태 전환을 처리합니다.
App Delegate 객체와 관련된 상태 전환
- 앱 실행 후 초기 상태
- 앱이 실행된 후, 시스템은 UI가 화면에 표시될지 여부에 따라 앱을 Inactive 또는 Background 상태로 둡니다.
- Foreground로 전환
- 앱이 Foreground로 이동하면, 시스템은 자동으로 앱을 Active 상태로 전환합니다.
- Active ↔ Background 상태 변화
- 앱이 종료될 때까지 Active와 Background 상태를 반복적으로 오가며 동작합니다. 상태 변화에서 수행해야 할 작업

앱 전환을 사용하여 다음 테스크를 수행하세요.
- 앱 실행 시 (Launch)
- 앱의 데이터 구조와 UI를 초기화합니다.
- 자세한 내용은 Responding to the launch of your app를 참고하세요!!
- Active 상태로 전환 시 (Activation)
- UI 구성을 완료하고 사용자와 상호작용할 준비를 합니다.
- 자세한 내용은 Preparing your UI to run in the foreground를 참고하세요!!
- Active 상태에서 벗어날 때 (Deactivation)
- 데이터를 저장하고 앱의 동작을 조용히 유지하도록 조정합니다.
- 자세한 내용은 Preparing your UI to run in the background를 참고하세요!!
- Background 상태로 전환 시
- 중요한 작업을 완료하고 가능한 많은 메모리를 해제하며, 앱 스냅샷 준비를 완료합니다.
- 자세한 내용은 Preparing your UI to run in the background를 참고하세요!!
- 앱 종료 시 (Termination)
- 모든 작업을 즉시 중단하고 공유 리소스를 해제합니다.
- 자세한 내용은 applicationWillTerminate(_:) 메서드를 참고하세요!!
기타 중요한 이벤트에 응답하기
앱 생명 주기 이벤트 외에도, 앱은 다음 표에 나열된 중요한 이벤트에 대응할 준비가 되어 있어야 합니다. 대부분의 경우, 이러한 이벤트는 UIApplicationDelegate 객체를 사용하여 처리합니다. 또한, 일부 이벤트는 알림을 통해 처리할 수도 있어 앱의 다른 부분에서도 응답할 수 있습니다.
이벤트 별 대응 방법
- 메모리 경고 (Memory Warnings)
- 발생 상황: 앱의 메모리 사용량이 너무 높을 때 시스템에서 경고를 보냅니다.
- 대응 방법: 앱이 사용하는 메모리를 줄입니다.
- 자세한 내용은 Responding to memory warnings를 참고하세요!!
- 보호된 데이터 접근 가능/불가능 (Protected Data Becomes Available/Unavailable)
- 발생 상황: 사용자가 기기를 잠그거나 잠금 해제할 때 발생합니다.
- 대응 방법: applicationProtectedDataDidBecomeAvailable(_:)와 applicationProtectedDataWillBecomeUnavailable(_:) 메서드를 사용하여 데이터를 처리합니다.
- Handoff 작업 (Handoff Tasks)
- 발생 상황: NSUserActivity 객체를 처리해야 할 때 발생합니다.
- 대응 방법: application(_:didUpdate:) 메서드를 사용하여 Handoff 작업을 처리합니다.
- 시간 변경 (Time Changes)
- 발생 상황: 전화 통신사로부터 시간 업데이트를 받거나, 시스템 시간이 변경될 때 발생합니다.
- 대응 방법: applicationSignificantTimeChange(_:) 메서드를 사용하여 시간 변경에 대응합니다.
- URL 열기 (Open URLs)
- 발생 상황: 앱이 특정 리소스를 열어야 할 때 발생합니다.
- 대응 방법: application(_:open:options:) 메서드를 사용하여 URL을 처리합니다.
이렇게 공식문서를 바탕으로 App의 LifeCycle 관리에 대한 정리를 해보았습니다! 의역하여 내용에 문제가 있거나 피드백이 있다면 언제든지 댓글 남겨 주세요!!
'iOS > UIKit' 카테고리의 다른 글
| [UIKit] ViewController의 생명주기 (0) | 2025.01.11 |
|---|---|
| [UIKit] Preparing your UI to run in the foreground (0) | 2025.01.10 |
| [UIKit] MVC패턴을 이용해 TableView를 만들어 보자 (0) | 2024.12.18 |
| [UIKit] 코드베이스 세팅하는 방법 (0) | 2024.12.16 |
| [UIKit] UIKit이란? (0) | 2024.12.16 |