[iOS] 앱의 생명주기(App Life Cycle)와 앱의 구조(App Structure)

728x90
반응형


앱 생명주기(App Life Cyle)와 앱의 구조(App Structure)에 대해 알아 보겠습니다.

앱의 실행과정

  1. main 함수가 실행
  2. main 함수는 UIApplicationMain함수를 호출
  3. UIApplicationMain함수는 앱의 본체에 해당하는 객체인 UIApplication 객체를 생성한다.
  4. nib파일을 사용하는 경우나, Info.plist 파일을 읽어들여 파일에 기록된 정보를 참고하여 그외에 필요한 데이터를 로드한다.
  5. 앱 델리게이트 객체를 만들고 앱 객체와 연결하고 런루프를 만드는 등 실행에 필요한 준비를 한다.
  6. 실행 완료를 앞두고 앱 객체가 앱 델리게이트에게 application:didFinishLaunchingWithOptions: 메시지를 보낸다.

The Main Function

Objective-C는 C언어의 기반 프로그램으로써 시작점은 main 함수이지만, Swift는 C기반 언어가 아니라 main파일이 존재하지 않으며 시작 포인트 역시 존재 하지 않습니다. 하지만 시작 진입점이 없으면 안되기 때문에 스위프트는 어노테이션 표기로 대체합니다.

import UIKit

@UIApplicationMain // 어노테이션으로 표기

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    func application(_ application: UIApplication, 
    				didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    }
}

iOS앱에서는 UIKit framework가 main함수를 관리하여 앱 개발자들이 직접 main함수를 작성하지 않는다는 것입니다. 그렇다고 앱의 실행에 앱 개발자가 관여할 수 없는 것은 아닙니다.(밑에 설명드리겠습니다.)

UIKit은 main함수를 다루를 과정에서 UIApplication객체가 생성되는데, 이 객체를 통해 앱 개발자는 앱의 실행에 부분적으로 관여할 수 있습니다.

UIApplicationMain Function

UIApplicationMain함수는 코코아 터치 프레임워크에서 앱의 라이프 사이클을 시작하는 함수입니다.
UIApplication 객체의 인스턴스를 만들고, 해당 객체의 앱으로서 기능하기 위한 기반을 마련하는데 이 과정을 앱 로딩 프로세스라고 불립니다.

Objective-C와 Swift에 조금 차이가 있습니다.
Objective-C언어로 개발하면 main.m이 자동으로 만들어져있는걸 볼 수있고, 스위프트로 시작하면 AppDelegate.swift 파일 맨 위에
@UIApplicationMain이 붙은 것을 볼 수있습니다. Swift에서는 main을 다루기 위해선 main.swift를 직접 만들어서 사용할 수 있습니다.

 

Objective-C의 경우 main.m 파일이 기본적으로 생성되어져 있다.
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
 
int main(int argc, char * argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
swift에선 Appdelegate의 @UIApplicationMain 어노테이션을 지우고 main.swift를 직접만들어 main함수를 다룰수 있습니다.
import UIKit

UIApplicationMain(
    CommandLine.argc,
    UnsafeMutableRawPointer(CommandLine.unsafeArgv)
        .bindMemory(
            to: UnsafeMutablePointer<Int8>.self,
            capacity: Int(CommandLine.argc)),
    nil,
    NSStringFromClass(AppDelegate.self)
)

UIApplicationMain의 인자를 자세히 살펴보겠습니다.

public func UIApplicationMain(_ argc: Int32,
				_ argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>!,
				_ principalClassName: String?,
				_ delegateClassName: String?) -> Int32

보시다시피 UIApplicationMain함수는 4가지의 인자를 받습니다.

첫번째, 두번째 인자는 argc, argv는 main함수로 받는 것으로 쉘에서 프로그램을 실행 할때 프로그램 실행 명령어와 함께 인자로 들어오는 값을 넣어준 것입니다. argc : argv의 개수argv : argument의 변수 목록

세번째 인자 principalClassName : UIApplication 클래스를 서브클래싱한 경우 해당 클래스 이름을 전달한다. nil을 쓰는 경우 이 값은 UIApplication으로 고정된다.

네번째 인자 delegateClassName : 앱 델리게이트 클래스 이름. 만약 nib 파일 내에 앱 델리게이트 객체가 정의되어 있다면 nil을 전달해야 한다.

결론적으로 main함수 안에서 실행되는 UIApplicationMain함수는 앱에 몇가지 중요한 객체를 생성하고 스토리보드에서 UI를 로딩하고 앱의 초기 셋팅값(info.plist)을 불러오고 앱을 Run loop에 올려 놓으며 함수를 진행시킵니다.


The Structure of an App

앱이 시작되면서 UIApplicationMain함수는 몇가지 중요한 객체를 생성하고 앱을 실행시킨다고 했습니다.
모든 iOS앱의 중심에는 시스템과 앱의 여러 객체들간의 대화를 가능하게 해주는 UIApplication객체가 있습니다.
아래 그림은 대부분의 앱에서 공통으로 사용되는 객체의 역할에 대해서 설명 하고 있습니다.

iOS앱은 기본적으로 MVC(Model-View-Controller)구조를 사용합니다. 이 디자인 패턴의 중요점은 앱의 Data와 비지니스 로직을 UI요소로부터 분리를 시켜줍니다. 이 패턴 덕분에 서로 다른 디바이스에서도 같은 동작이 가능한 것입니다.

출처: App Programming Guide for iOS - The App Life Cycle

The Main Run Loop

Main Run Loop는 사용자 관련 이벤트들을 받은 순서대로 처리합니다. UIApplication객체는 앱이 실행될 때, Main Run Loop를 실행하고, 이 Run Loop로 이벤트를 처리 합니다. 이름에서 알 수 있듯이, Main Run Loop는 앱의 메인 스레드에서 동작합니다.

출처: App Programming Guide for iOS - The App Life Cycle

Main Run Loop가 사용자의 이벤트에 대해 어떻게 동작하는지에 대한 구조입니다.
사용자가 디바이스에서 특정 액션은 취하면, 그 액션에 해당하는 이벤트가 시스템에 의해 생성되어 UIKit에서 생성한 port를 통해 앱에 전달 됩니다. 전달된 이벤트들은 queue에 보관되고 하나씩 Main Run Loop로 전달되어 처리됩니다.

 

앱의 상태 변화

App State

  1. Not Running : 실행되지 않았거나, 시스템에 의해 종료된 상태
  2. Inactive : 실행 중이지만 이벤트를 받고있지 않은 상태. 예를들어, 앱 실행 중 미리알림 또는 일정 얼럿이 화면에 덮여서 앱이 실질적으로 이벤트는 받지 못하는 상태등을 뜻합니다.
  3. Active : 어플리케이션이 실질적으로 활동하고 있는 상태.
  4. Background : 백그라운드 상태에서 실질적인 동작을 하고 있는 상태. 예를 들어 백그라운드에서 음악을 실행하거나, 걸어온 길을 트래킹 하는 등의 동 뜻합니다.
  5. suspended : 백그라운드 상태에서 활동을 멈춘 상태. 빠른 재실행을 위하여 메모리에 적재된 상태지만 실질적으로 동작하고 있지는 않습니다. 메모리가 부족할때 비로소 시스템이 강제종료하게 됩니다.

대부분의 상태 전환은 AppDelegate객체의 메소드 호출을 거칩니다. AppDelegate 객체는 UIResponder, UIApplicationDelegate를 상속 및 델리게이트 참조하고 있습니다.
UIApplicationDelegate은 UIApplication 객체의 작업에 개발자가 접근할 수 있도록 하는 메소드들을 담고 있습니다.

 

AppDelegate

  • application:willFinishLaunchingWithOptions: 어플리케이션이 최초 실행될 때 호출되는 메소드
  • application:didFinishLaunchingWithOptions: 어플리케이션이 실행된 직후 사용자의 화면에 보여지기 직전에 호출
  • applicationDidBecomeActive: 어플리케이션이 Active 상태로 전환된 직후 호출
  • applicationWillResignActive: 어플리케이션이 Inactive 상태로 전환되기 직전에 호출
  • applicationDidEnterBackground: 어플리케이션이 백그라운드 상태로 전환된 직후 호출
  • applicationWillEnterForeground: 어플리케이션이 Active 상태가 되기 직전에, 화면에 보여지기 직전의 시점에 호출.
  • applicationWillTerminate: 어플리케이션이 종료되기 직전에 호출

앱을 전면으로 실행하기

앱이 시작되는 부분에서 시스템은 프로세스와 앱의 Main Thread, 그리고 Main Thread에서 main함수를 생성합니다.
main함수에서 UIKit 프레임워크를 즉시 다룰 수 있고, UIKit 프레임 워크는 앱의 초기화와 실행준비를 합니다.

앱을 background로 실행하기

반응형

'iOS' 카테고리의 다른 글

[iOS] 싱글턴(Singleton) in Swift  (0) 2019.07.23
[iOS] Code Snippet  (0) 2019.07.23
[iOS] UIViewController개념과 생명주기(Life Cycle)  (0) 2019.07.23
[iOS] iOS UI Guide 개념  (0) 2019.07.23
[iOS] Hello Xcode  (0) 2019.07.22