본문 바로가기
iOS/Swift

IOS Application Lifecycle

by Jiseong 2021. 9. 9.

IOS에서 앱을 실행하면 어떤 과정을 통해 실행될까?

C언어에 뿌리를 둔 모든 애플리케이션은 main() 함수로부터 시작된다. 이를 Entry Point라고 한다.

OS가 애플리케이션 내부에 정의된 main() 함수를 찾아 호출하면 함수에 작성된 코드가 실행되며, 작성해둔 Custom Code에 까지 도달하게 되는 식이다.

 

IOS 앱 또한 Object-C 기반으로 돌아가기 때문에 앱은 main() 함수에서 시작된다.

다만, 다른 C 기반의 앱과 달리, IOS 앱은 핵심 라이브러리인 UIKit Framework가 main() 함수를 관리하여 사용자가 직접 작성하지 않는 차이가 있다.

 

다음은 실제로 Object-C 기반의 XCode 프로젝트를 생성하였을 때, main.m 파일 안에 생성되는 main() 함수이다.

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
	@autoreleasepool {
    	return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]))
    }
}

 

main() 함수가 하는 일은 단순하다. 실행시 시스템으로부터 전달받은 두 개의 인자값(argc, argv)과, AppDelegate 클래스를 이용하여 UIApplicationMain() 함수를 호출하고, 그 결과로 UIApplication 객체를 반환한다. 생성된 UIApplication 객체는 UIKit Framework에 속해 있으므로, 이후의 앱 제어권은 UIKit Framework로 이관된다.

 

UIApplicationMain() 함수가 호출하는 UIApplication은 앱의 본체라고 할 수 있는 객체로, 사실상 앱 자체를 의미한다.

우리가 작성한 Custom Code나 객체, 구현한 기능 등 모든 것들은 UIApplication에 포함되어있는 하위 객체이다.

이 객체를 통해 앱 개발자는 앱 실행에 부분적으로 관여할 수 있게된다.

이처럼, 앱 개발자가 앱을 실행할 때 접근할 수 있는 객체가 UIApplication 이기에 앱이 어떤 과정으로 실행되는지 디테일하게 들여다보려면 UIApplication에 대해 알아야한다.

 

UIApplication

The centralized point of control and coordination for apps running in iOS.

 

모든 IOS 앱은 UIApplicationMain 함수를 실행한다. 

이때 생성되는 것 중 하나가 UIApplication 객체이다. 이 객체는 Singleton 형태로 생성되어, UIApplication.shared의 형태로 앱 전역에서 사용 할 수 있다. 

UIApplication 객체의 중요한 역할은 사용자의 이벤트에 반응하여 앱의 초기 설정을 하는 것이다. (routing, handling)

 

 

IOS Application Lifecycle

 

 

왼쪽은 IOS 시스템 프레임워크이고, 오른쪽은 사용자가 작성하는 Custom Code이다. 

시스템 프레임워크는 사용자가 앱 아이콘을 탭했을 때, 이를 인식하고 앱을 구동한다.

Entry Point인 main() 함수가 실행되고, 함수 내부에서 UIApplicationMain()을 호출하면 앱이 구동된다.

정확히는.. main() 함수를 통해 UIApplicationMain()을 호출하는 대신 @UIApplicationMain 어노테이션을 찾아 해당하는 클래스를 실행한다.

이때 Custom Code에서 AppDelegate 클래스에 작성된 application(_:didFinishedLaunchingWithOptions:) 메소드가 시스템에 의해 자동으로 호출된다. 즉, AppDelegate 클래스의 application(_:didFinishedLaunchingWithOptions:) 메소드에 원하는 Custom Code를 작성해두면 앱이 처음 시작될 때 해당 코드를 실행한다.

이어서 시스템 프레임워크의 EventLoop가 실행되면서 사용자가 작성하는 Handle Event에 의해 Custom Code로 연결된다.

사용자가 원하는 이벤트를 제어할 수 있도록 Handle을 만들어 Custom Code에 연결해놓으면 EventLoop에서는 특정 이벤트가 발생했을때 사용자가 만든 Handle(@IBAction...etc)을 통하여 Custom Code에 구현한 것을 Callback 해준다.

 

앱이 실행 목적을 모두 완료한 후, 더이상 사용되지 않으면 시스템은 앱을 메모리에서 제거한다

이 과정에서 시스템은 AppDelegate 클래스의 applicationWillTerminate(_:) 메소드를 호출한다.

이는 "회사 불 끌거니깐 마무리할 것 있으면 얼른 마무리해라" 라는 시그널과 같다. 앱 종료시 반드시 처리해야 될 것이 있다면 이 메소드 내부에 Custom Code를 작성하면 된다.

 

 

<application(_:didFinishedLaunchingWithOptions:) 메소드>

//
//  AppDelegate.swift
//
//  Created by 임지성 on 2021/09/09.
//

import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

 

 

IOS Application Lifecycle 요약

 

1. main() 함수 실행

2. main() 함수가 UIApplicationMain() 호출

3. UIApplicationMain() 은 UIApplication 객체 생성

4. UIApplication 객체는 프로젝트 내부의 info.plist를 바탕으로 앱에 필요한 데이터, 객체 Load

5. AppDelegate 객체 생성 후 UIApplication 객체와 연결

6. EventLoop

7. 앱 실행 완료 직전, AppDelegate 클래스의 application(_:didFinishedLaunchingWithOptions:) 메소드 호출

8. 실행

 

 

App State Changed

 

앱은 실행되는 동안 상태가 변화된다. 여기서 말하는 상태(State)란 화면에 나타났거나, 화면으로부터 숨겨졌거나, 시작, 종료하는 등을 의미한다.

앱의 상태 변화는 OS가 처리하는 영역이다. IOS는 시스템에서 발생한 특정 컨디션에 맞게 앱의 상태를 변화시키고 제어한다.

예를들라고 그랬는데, 원래는 폰게임을 하고있다가 전화가 오면 실행되던 게임은 백그라운드로 넘어가든, 종료되든 했는데, 요즘은 그러질않아서.. 

 

여튼 뭐 전화로 예를 들면, IOS가 전화오거나, 전화가 종료되면 상황에 맞게 기존 앱의 상태를 변경시키는 것이다.

 

이처럼 IOS는 각각의 앱마다 모두 상태 변화를 제어하여 어떤 앱은 실행시키고, 어떤 앱은 백그라운드, 어떤 앱은 종료하는 등 다양한 처리를 한다. 

Apple에서 정의하는 앱의 상태(App State)는 크게 5가지로 구분된다.

 

  • Not Running: 앱이 시작되지 않았거나, 실행되었지만 시스템에 의해 종료된 상태
  • Inactive: 앱이 전면(Foreground)에서 실행중이지만, 아무런 이벤트를 받지 않는 상태, 앱의 상태 변화 과정에서 잠깐 머무는 단계
  • Active: 앱이 전면(Foreground)에서 실행중이며, 이벤트를 받고있는 상태
  • Background: 앱이 백그라운드에 있지만, 여전히 코드가 실행되고 있는 상태 
    • 대부분의 앱은 Suspended 상태로 이행하는 도중에 일시적으로 이 상태에 진입하지만, 파일의 다운로드나 업로드, 연산처리 등 여분의 실행 시간이 필요한 앱일 경우 특정 시간이나 상황동안 이 상태로 남아있게 된다. (게임 백그라운드 다운로드 같은 경우)
  • Suspended: 앱이 메모리에 유지되지만, 실행되는 코드가 없는 상태
    • 메모리가 부족한 상황이라면, IOS 시스템은 앱의 전면(Foreground)에 있는 앱의 여유 메모리 공간을 확보하기 위해Suspended 상태에 있는 앱들을 특별한 알림 없이 종료한다. (Suspended -> Not Running 상태로 진입하는 것은 알림을 받지않는다.) 또한, 앱이 Background 상태에서 Suspended 상태로 진입할 때 willTerminate 메소드가 실행되지만, 이 또한 기기를 재부팅하면 실행되지 않는다. 

앱의 실행 상태가 변화할 때마다 Application객체는 AppDelegate 클래스에 정의된 특정 메소드르 호출한다. 

사용자는 이 메소드 내부에 Custom Code를 작성함으로써 사용자가 원하는 작업이 실행되도록 할 수 있다. 

AppDelegate 클래스엔 다양한 메소드들이 있고. 각 메소드들은 그에 맞는 상태 변화에 따라 호출된다.

 

AppDelegate 주요 메소드

 

  • application(_:willFinishLaunchingWithOptions:): 앱이 구동되어 필요한 초기실행 과정이 완료되기 직전에 호출되는 메소드
  • application(_:didFinishLaunchingWithOptions:): 앱이 사용자에게 화면으로 표시되기 직전에 호출되는 메소드. 앱이 실행된 후에 진행할 수 있는 Customizing이나 init을 위한 코드를 작성한다.
  • applicationDidBecomeActive(_:): 실행되는 앱이 Foreground, 즉 화면 전면에 표시될 때 호출되는 메소드. 앱이 Inactive 상태에 들어가면서 일시중지된 작업이 있다면 이를 재시작하는 코드를 작성한다.
  • applicationDidEnterBackground(_:): 앱이 Background 상태에 진입했을 때 호출되는 메소드. 이 메소드가 호출된다는 것은 미래의 어느 순간에 앱이 종료된다는 것이고, 잃어서는 안되는 사용자 데이터를 미리 저장하거나, 공유 자원을 점유하고 있다면 이를 해제해 주어야 한다. 앱이 다시 실행될 때 현재의 상태를 복구할 수 있도록 필요한 상태 정보도 이 메소드에 저장 처리하는 것이 좋다.
  • applicationWillTerminate(_:): 앱 종료 직전에 호출되는 메소드. 사용자 데이터 등을 종료 전에 한번 더 저장해주는 것이 좋다.

 

 

역시 어렵다

 

'iOS > Swift' 카테고리의 다른 글

M1 error running pod install  (0) 2021.09.20
text property  (0) 2021.09.10
[Swift] Control Flow  (1) 2021.09.08
Design Pattern - MVC  (0) 2021.08.31
[Swift] String and Characters  (0) 2021.08.24

댓글