์ค๋์ ๊ฐ๋ฒผ์ด ์ฃผ์ ๋ก ๋ธ๋ก๊ทธ๋ฅผ ๋์ ์ฌ๋ณด๊ฒ ์ต๋๋ค.
(์ถ์ ์ฐํด ๊ธฐ๋
๐ฅณ)
AppDelegate์์๋ง ์ฒ๋ฆฌํ๋ฉด ๋๋ ์ค ์์๋๋ฐ..
SceneDelegate์์๋?
์ฑ์ด ์คํ๋ ๋, ์ฐ๋ฆฌ๋ ํํ AppDelegate์ didFinishLaunchingWithOptions์์ ๋ชจ๋ ์ด๊ธฐํ๋ฅผ
์ฒ๋ฆฌ๋ฅผ ํ๋ฉด ๋๋ค๊ณ ์๊ฐํ๋ค.
ํ์ง๋ง ์ค์ ๋ก iOS 13 ์ดํ ๋์
๋ SceneDelegate ๊ตฌ์กฐ์์๋ ์ด ์๊ฐ์ด ํ๋ฆด ์ ์๋ค.
์ด๋ฒ ๊ธ์์๋ ์ฑ์ด ์คํ๋ ๋ ๋ฐ๋์ ๊ฑฐ์ณ์ผ ํ๋ ์ด๊ธฐํ ๋จ๊ณ์
AppDelegate/SceneDelegate ๊ฐ๊ฐ์ ์ญํ ์ ์ ๋ฆฌํด๋ณด๋ ค ํ๋ค.
๐๐ปโ๏ธ ์ญํ ์ ์ฐจ์ด
AppDelegate | SceneDelegate | |
ํธ์ถ ์์ | ์ฑ ํ๋ก์ธ์ค ์์ ์ | ๊ฐ ์ฌ ์์ฑ ์ |
์ญํ | ์ ์ญ์ ์ธ ์ฑ ์ด๊ธฐํ(SDK, Logger, DB ๋ฑ) | ํ๋ฉด(UI)์ด๊ธฐํ, ์๋์ฐ ์ค์ |
์๋ช ์ฃผ๊ธฐ | ์ฑ ๋จ์ | UI ์ธ์ ๋จ์ |
๋ํ ๋ฉ์๋ | application(_:didFinishLaunchingWithOptions:) | scene(_:willConnectTo:options:) |
์ฆ, AppDelegate๋ ์ฑ ์ ์ฒด์ ์ธ ํ๊ฒฝ์ ์ค๋นํ๊ณ , SceneDelegate๋ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง UI ์ง์ ์ง์ ์ ๊ตฌ์ฑํ๋ ๊ณณ์ด๋ค.
iOS 13์์ UIScene(๋ฉํฐ ์๋์ฐ) ๊ฐ๋
์ด ๋์
๋๋ฉด์, ํ ์ฑ์ด ์ฌ๋ฌ UI ์ธ์
์ ๋์์ ๊ฐ์ง ์ ์๊ฒ ๋์๋ค.
๊ทธ๋์ ํ๋ก์ธ์ค ๋จ์ ์ด๋ฒคํธ(์ฑ ์ ์ญ ์ด๊ธฐํ, SDK ๊ตฌ์ฑ)๋ AppDelegate๊ฐ ๋งก๋๋ก ์ฑ
์์ด ๋ถ๋ฆฌ๋์๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก '์ฑ์ ์คํ ์์ (AppDelegate)'๊ณผ 'ํ๋ฉด์ด ๋ณด์ด๊ธฐ ์์ํ๋ ์์ (SceneDelegate)'์ด ์์ฐ์ค๋ฝ๊ฒ ๋ถ๋ฆฌ๋์๋ค.
๋ฉํฐ ์ฌ(iPad Split View, Stage Manager) ํ๊ฒฝ์์ 'ํ๋ก์ธ์ค ๋จ์(AppDelegate)'์ 'UI ์ธ์
๋จ์(SceneDelegate)' ์ด๋ฒคํธ๋ฅผ ๋ถ๋ฆฌํ๊ธฐ ์ํ ๊ตฌ์กฐ์ ๋ณํ์๋ค.
๐๐ปโ๏ธ ์ฑ ์ฒซ ์คํ ์์ ์ ์ผ๋ฐ์ ์ธ ์ด๊ธฐํ ์์
1. ํ๊ฒฝ ๋ณ์ ๋ฐ ์ค์ ๊ฐ ๋ก๋ฉ
- UserDefaultsManager๋ฅผ ํตํด ๊ธฐ๋ณธ ์ค์ ์ธํ
- ์๋ฒ ํ๊ฒฝ, API Host, ์ฑ ๋ฒ์ ์ ๋ณด ๋ก๋
- ์ฒซ ์คํ ์ฌ๋ถ(isFirstLaunch) ํ์ธ
2. ํ์ SDK ์ด๊ธฐํ
- ์: Firebase, Crashlytics, Analytics, Logger ๋ฑ
- ๋๋ถ๋ถ AppDelegate์์ ์ฒ๋ฆฌ
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
Logger.setup()
return true
}
3. ๊ถํ ํ์ธ ๋ฐ ๋น๋๊ธฐ ์์ฒญ
- HealthKit, Notification, BLE, ์นด๋ฉ๋ผ, ์์น ๋ฑ
- UI๊ฐ ๋จ๊ธฐ ์ ๋ฏธ๋ฆฌ ์ํ๋ฅผ ํ์
ํด๋๋ฉด UX ์์ ํ์ ๋์์ด ๋จ
HealthPermissionManager.shared.checkAuthorization()
// ๊ถํ ํ์
์ ์ค์ ๊ธฐ๋ฅ ์ฌ์ฉ ์์ ์ ๋
ธ์ถํ๋ ๊ฒ์ด HIG ๊ถ์ฅ์ฌํญ์
// (์ฆ, ์ต์ด ์คํ์์๋ ์ํ ํ์ธ๋ง ํ๊ณ , ์์ฒญ์ ์ฌ์ฉ์ ์ก์
์งํ๋ก ๋ฏธ๋ฃจ๋ ๊ฒ์ด ์ข์)
4. SplashView ์ด๊ธฐํ(SceneDelegate)
- ์ฑ์ ์ฒซ UI๋ฅผ ๋ด๋น(์ด์ ๊ธ์์ ๋ค๋ฃฌ ์คํ๋์ ๋ทฐ)
- ์บ์๋ ์ด๋ฏธ์ง ํ์, ๋ค๋น๊ฒ์ด์
์ง์
๊ฒฐ์ ๋ฑ
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = SplashViewController()
window.makeKeyAndVisible()
self.window = window
}
// Universal Link์ NSUserActivity(Handoff ํฌํจ)๋ ์ฌ๊ธฐ๋ก๋ ์ ๋ฌ๋จ
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
DeepLinkManager.shared.handle(userActivity: userActivity)
}
5. ์ด๊ธฐ ๋ฐ์ดํฐ ํ๋ฆฌํ์น
- ์๋ฒ์์ AppConfig, Notice, SplashImage ๋ฑ์ ๊ฐ์ ธ์ ์บ์
- ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ์ฌ ํ๋ฉด ํ์๋ฅผ ์ง์ฐ์ํค์ง ์๋๋ก ํ๊ธฐ
๐๐ปโ๏ธ ๋น๋๊ธฐ ์ด๊ธฐํ ์์ ๊ด๋ฆฌ
์ฑ ์คํ ์ ์ฌ๋ฌ ์ด๊ธฐํ ๋ก์ง์ด ๋์์ ๋์๊ฐ๋ฉด ํ์ด๋ฐ ์ถฉ๋์ด ์๊ธธ ์ ์๋ค.
(ex. ํนํ Splash ํ๋ฉด์ด ๋จผ์ ๋๋ฌ๋๋ฐ SDK ์ด๊ธฐํ๊ฐ ์์ง ์๋๋ ๊ฒฝ์ฐ)
์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด swift์ async let์ ํ์ฉํด ๋ณ๋ ฌ ์คํ ํ ๋๊ธฐํํ ์ ์๋ค.
final class AppInitializer {
static let shared = AppInitializer()
func runAll() async {
async let loggerInit = Logger.setupAsync()
async let firebaseInit = FirebaseManager.initializeAsync()
async let healthPermission = HealthPermissionManager.shared.checkAuthorizationAsync()
_ = await [loggerInit, firebaseInit, healthPermission]
}
}
์์ ๊ฐ์ด ๊ตฌ์ฑํ๋ฉด ์ด๊ธฐํ ์์
์ ๋ณ๋ ฌ๋ก ์ํํ๋ฉด์๋, ๋ชจ๋ ์์
์ด ๋๋๊ธฐ ์ ๊น์ง ๊ธฐ๋ค๋ฆด ์ ์๋ค.
๐๐ปโ๏ธ SceneDelegate → SplashViewController ํ๋ฆ์ ์ ๋ฆฌํด๋ณด๋ฉด?
App Launch
↓
AppDelegate.didFinishLaunching() // SDK, Logger, Permission, ...
↓
SceneDelegate.willConnectTo() // UIWindow, RootViewController ๊ตฌ์ฑ
↓
SplashViewController.viewDidLoad() // ์บ์ ์ด๋ฏธ์ง ํ์
↓
SplashViewController.viewDidAppear() // ์ผ์ ์๊ฐ ํ MainViewController ์ ํ
๐๐ปโ๏ธ ๋ฅ๋งํฌ(Deep Link) ์ฒ๋ฆฌ
- ๋ฅ๋งํฌ: ์ฑ ์ธ๋ถ์์ ํน์ ํ๋ฉด์ผ๋ก ์ง์
ํ ์ ์๋ ๊ธฐ๋ฅ
- iOS 13 ์ดํ๋ถํฐ๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ SceneDelegate์์ ์ฒ๋ฆฌ
- ๊ทธ ์ด์ ๋ iOS๊ฐ UI ์ธ์
(Scene) ๋จ์๋ก ๋ฅ๋งํฌ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ๊ธฐ ๋๋ฌธ
ex. ์ฑ์ด ์์ ํ ์ข
๋ฃ๋ ์ํ์์ ๋งํฌ๋ฅผ ํตํด ์ง์
ํ๋ ๊ฒฝ์ฐ
→ AppDelegate์ scene(_:willConnectTo:)ํธ์ถ ํ
→ SceneDelegate.scene(_:openURLContexts:)๊ฐ ์ด์ด์ ํธ์ถ๋จ
์ด์ ๋ฐ๋ฅธ ์ค์ ๋ผ์ฐํ ์ฒ๋ฆฌ๋ SceneDelegate์์!
// SceneDelegate.swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
DeepLinkManager.shared.handle(url: url)
}
์ฆ, ์ ์ญ์ ์ธ URL ์คํด ๋ฑ๋ก ๋ฐ Universal Link ์ค์ ์ AppDelegate, ์ค์ URL์ ๋ถ์ํ์ฌ ํ๋ฉด ์ด๋์ ์ฒ๋ฆฌํ๋๊ฑด SceneDelegate์์ ๋ด๋น!
๋ง์ฝ ์ฑ์ด ์ด๋ฏธ ์คํ ์ํ๋ผ๋ฉด, SceneDelegate์์ ์ง์ ๋ฃจํธ ๋ทฐ์ปจ์ ์ฐพ์ ์ ์ ํ ํ๋ฉด์ผ๋ก ๋ผ์ฐํ
์งํ
๊ฐ๋ฐ ๊ณต๋ถ ์ด๊ธฐ์๋ ๊ณผ๊ฑฐ์๋ 'AppDelegate์์ผ๋ iOS 13 ์ดํ SceneDelegate๊ฐ ๋ฑ์ฅํ๋ฉฐ ๋์ฒด๋์๋ค?' ์ ๋๋ก๋ง ์๊ณ ์์๋ค.
๋จ์ํ ์ด๋์ ๋ค์ ๋ด์ฉ์ ๊ทธ๋๋ก ๋ฐ์๋ค์์ ๋ฟ, ์ ๊ทธ๋ฐ ๊ตฌ์กฐ๊ฐ ์๊ธด ๊ฑด์ง๋ ๊น๊ฒ ์๊ฐํ์ง ์์๋ ๊ฒ ๊ฐ๋ค.
์ด๋ฒ ๊ธ์ ์ ๋ฆฌํ๋ฉด์, AppDelegate์ SceneDelegate๊ฐ ๋จ์ํ ์ญํ ๋ง ๋ค๋ฅธ ๊ฒ ์๋๋ผ
์ฑ์ ์คํ ์์ ๊ณผ UI ์ง์
์์ ์ ๊ตฌ๋ถํ๊ธฐ ์ํ ๊ตฌ์กฐ์ ์ฅ์น๋ผ๋ ๊ฒ์ ์๊ฒ ๋์๋ค.
๊ณผ๊ฑฐ ์คํ๋์ ํ๋ฉด๊ณผ ๋ฅ๋งํฌ๋ฅผ ๊ตฌํํ๋ฉด์ '๊ทธ๋ฅ AppDelegate์ ๋ฃ์ผ๋ฉด ๋๊ฒ ์ง'๋ผ๊ณ ์๊ฐํ๋ ๋ถ๋ถ๋ค์ด
์ค์ ๋ก๋ SceneDelegate ๋จ์์ ์ฒ๋ฆฌ๋์ด์ผ ํ๋ ์ด์ ๊ฐ ๋ช
ํํด์ก๋ค :)
'๐' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] SplashView - ์คํ๋์ ํ๋ฉด (0) | 2025.09.28 |
---|---|
[Swift] KeychainManager (0) | 2025.09.21 |
[Swift] Keychain (0) | 2025.09.14 |