SceneDelegate와 AppDelegate의 차이점: iOS 앱 개발의 핵심 이해
iOS 앱 개발에서는 AppDelegate와 SceneDelegate가 중요한 역할을 합니다. iOS 13부터는 멀티 윈도우 환경을 지원하기 위해 SceneDelegate가 도입되었습니다. 이 두 클래스는 각각 다른 책임을 가지며, 앱의 생명주기 및 상태 관리를 처리합니다. 이 글에서는 AppDelegate와 SceneDelegate의 차이점과 각각의 역할을 예제를 통해 설명하겠습니다.
AppDelegate
AppDelegate는 앱의 전반적인 생명주기를 관리합니다. 앱이 시작되고 종료되며, 백그라운드나 포그라운드로 전환되는 등의 전반적인 이벤트를 처리합니다. AppDelegate는 주로 다음과 같은 작업을 수행합니다.
- 앱 초기화: 앱이 시작될 때 초기 설정을 처리합니다.
- 푸시 알림 설정: 푸시 알림을 설정하고 처리합니다.
- 백그라운드 작업: 앱이 백그라운드로 전환될 때 필요한 작업을 수행합니다.
다음은 AppDelegate의 예제 코드입니다.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 앱 초기화 코드
print("앱이 시작되었습니다.")
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// 앱이 비활성화될 때 호출
print("앱이 비활성화 상태로 전환됩니다.")
}
func applicationDidEnterBackground(_ application: UIApplication) {
// 앱이 백그라운드로 전환될 때 호출
print("앱이 백그라운드로 전환되었습니다.")
}
func applicationWillEnterForeground(_ application: UIApplication) {
// 앱이 다시 포그라운드로 전환될 때 호출
print("앱이 포그라운드로 전환됩니다.")
}
func applicationDidBecomeActive(_ application: UIApplication) {
// 앱이 활성화 상태로 전환될 때 호출
print("앱이 활성화 상태로 전환되었습니다.")
}
func applicationWillTerminate(_ application: UIApplication) {
// 앱이 종료될 때 호출
print("앱이 종료됩니다.")
}
}
SceneDelegate
SceneDelegate는 iOS 13 이후로 도입된 클래스이며, 앱의 각 장면(Scene)에 대한 생명주기를 관리합니다. 멀티 윈도우 환경을 지원하기 위해 도입되었으며, 앱이 여러 UI 창을 가질 수 있는 경우 각 창의 상태를 독립적으로 관리합니다. SceneDelegate는 주로 다음과 같은 작업을 수행합니다.
- UI 상태 관리: 각 장면의 UI 상태를 관리합니다.
- 장면 생명주기 이벤트 처리: 장면이 활성화되거나 비활성화될 때 이벤트를 처리합니다.
다음은 SceneDelegate의 예제 코드입니다.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
// 장면이 연결될 때 호출
guard let _ = (scene as? UIWindowScene) else { return }
print("장면이 연결되었습니다.")
}
func sceneDidDisconnect(_ scene: UIScene) {
// 장면이 분리될 때 호출
print("장면이 분리되었습니다.")
}
func sceneDidBecomeActive(_ scene: UIScene) {
// 장면이 활성화될 때 호출
print("장면이 활성화되었습니다.")
}
func sceneWillResignActive(_ scene: UIScene) {
// 장면이 비활성화될 때 호출
print("장면이 비활성화됩니다.")
}
func sceneWillEnterForeground(_ scene: UIScene) {
// 장면이 포그라운드로 전환될 때 호출
print("장면이 포그라운드로 전환됩니다.")
}
func sceneDidEnterBackground(_ scene: UIScene) {
// 장면이 백그라운드로 전환될 때 호출
print("장면이 백그라운드로 전환되었습니다.")
}
}
guard let _ = (scene as? UIWindowScene) else { return } 이 코드는 Swift에서 사용되는 guard 구문을 활용한 옵셔널 바인딩입니다. 이 코드의 목적은 주어진 scene 객체를 UIWindowScene 타입으로 안전하게 캐스팅(casting)하고, 만약 캐스팅에 실패하면 함수의 실행을 중단시키는 것입니다.
코드 설명
guard let _ = (scene as? UIWindowScene) else { return }
이 코드는 다음과 같은 의미를 갖습니다:
- guard 구문: 조건이 만족되지 않으면 코드 블록을 빠져나가기 위해 사용됩니다. 여기서는 조건이 false일 경우 else 블록이 실행됩니다.
- 옵셔널 바인딩: scene as? UIWindowScene 표현식은 scene 객체를 UIWindowScene 타입으로 안전하게 캐스팅하려고 시도합니다. 이 캐스팅은 성공할 수도 있고 실패할 수도 있으며, 실패할 경우 nil을 반환합니다.
- let _: 캐스팅이 성공할 경우, 결과 값을 _에 바인딩합니다. _는 특별한 식별자(identifier)로, 실제로 사용하지 않겠다는 의미입니다. 따라서 바인딩한 값이 필요하지 않은 경우 사용됩니다.
- else { return }: 캐스팅이 실패하면 else 블록이 실행됩니다. 여기서는 return이 호출되어 현재 함수 또는 메서드의 실행을 중단합니다.
코드 흐름
이 코드는 주어진 scene이 UIWindowScene 타입인지 확인하고, 그렇지 않으면 함수를 종료합니다. UIWindowScene은 iOS 13에서 도입된 클래스로, 앱의 UI를 구성하는 창(window)을 나타냅니다. 이 코드는 일반적으로 SceneDelegate의 scene(_:willConnectTo:options:) 메서드 내에서 사용됩니다.
예제
다음은 SceneDelegate 내에서 이 코드를 사용하는 예제입니다:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// scene이 UIWindowScene으로 캐스팅되지 않으면 함수 종료
guard let windowScene = (scene as? UIWindowScene) else { return }
// window를 생성하고 UIWindowScene에 연결
let window = UIWindow(windowScene: windowScene)
let viewController = UIViewController()
viewController.view.backgroundColor = .white
window.rootViewController = viewController
self.window = window
window.makeKeyAndVisible()
}
}
이 예제에서:
- scene 객체가 UIWindowScene으로 캐스팅됩니다.
- 캐스팅에 성공하면 windowScene에 바인딩되고, 실패하면 함수가 종료됩니다.
- 성공한 경우 window를 생성하고 windowScene에 연결한 후, 루트 뷰 컨트롤러를 설정합니다.
이렇게 guard 구문을 사용함으로써 코드의 가독성을 높이고, 불필요한 중첩을 피할 수 있습니다. 또한, 예상치 못한 타입의 객체를 처리할 때 안전하게 대처할 수 있습니다.
주요 차이점 정리
- 역할:
- AppDelegate: 앱 전체의 생명주기를 관리.
- SceneDelegate: 각 장면의 생명주기를 관리.
- 도입 시기:
- AppDelegate: iOS 초기 버전부터 존재.
- SceneDelegate: iOS 13부터 도입.
- 사용 목적:
- AppDelegate: 전반적인 앱 상태 관리 (앱 시작, 종료, 백그라운드 진입 등).
- SceneDelegate: 멀티 윈도우 환경에서 각 장면의 상태 관리.
결론
iOS 앱 개발에서 AppDelegate와 SceneDelegate의 차이점을 이해하는 것은 중요합니다. AppDelegate는 여전히 앱의 전반적인 생명주기를 관리하지만, SceneDelegate는 멀티 윈도우 지원을 위해 각 장면의 생명주기를 관리합니다. 이를 통해 개발자는 더 유연하고 강력한 앱을 만들 수 있습니다. 이 두 클래스의 역할을 잘 이해하고 활용하면, 보다 안정적이고 사용자 친화적인 앱을 개발할 수 있을 것입니다.