iOS 앱의 시작점, 앱의 실행 과정

ellyheetov·2021년 3월 13일
0
post-thumbnail

C언어에 뿌리를 둔 모든 애플리게이션은 main()함수로 부터 시작된다. 이를 엔트리 포인트(entry point, 시작 진입점)이라고 한다.

MacOS Command Line Tool을 이용하여 프로젝트를 생성한 경우 자동으로 main.swift파일이 생긴다. 프로그램의 시작 지점이 main함수라는 것을 알 수 있다.

만약 main.swift 파일을 제거하면 어떻게 될까?🧐

main.swift파일을 제거하고 test.swift파일을 생성하고 실행시켜 보았다. 예상대로 Build Failed를 확인할 수 있었다. main.swift에서 프로그램을 시작해야하는데, main을 찾을 수 없기 때문이다. 하지만, iOS앱 프로젝트를 생성한 경우 시작 지점을 지정하지 않아도 정상 작동하는 것을 볼 수 있다.

Object-C 프로그램의 시작 진입점

Obejct-C 프로그램을 생성하면 main.m 파일이 나타난다. Object-C의 main함수를 살펴보자.

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

main함수의 인자인 argc, argv는 command-line 에서 입력한 인자를 넘겨준다. main함수가 하는 일을 다음과 같다.

  • autorelease pool을 생성한다.
  • UIApplicationMain() 함수를 호출한다.
  • autorelease pool을 drain한다(?).
  • UIApplicationMain() 함수의 리턴 값을 호출자에게 반환한다.

Object-C 프로그램은 main()에서 시작하고 main()에서 끝이 난다. 매우 간단하게 보이지만, iOS앱이 실행될 수 있는 비밀은 UIApplicationMain()에 있다.

코코아 앱의 시작 진입점

앱에서는 시작 진입점을 지정하기 위해 어노테이션을 사용한다. @main 또는 @UIApplicationMain 태그를 사용할 수 있다.

@main
//@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { }

만약 생성된 앱 프로젝트에서 @main 어노테이션을 지울 경우 빌드에 실패한다. 앱의 시작 진입점을 알 수 없기 때문이다.

그럼 이제 직접 시작 진입점을 지정해보자.@main을 지우고 main.swift파일을 생성한다. 이때 반드시 파일명은 main.swift가 되어야 한다. 해당 파일만이 유일하게 top-level code를 작성할 수 있는 파일이다. main.swift 파일에 아래 코드를 입력한다.

import UIKit

UIApplicationMain(
    CommandLine.argc,
    CommandLine.unsafeArgv,
    NSStringFromClass(UIApplication.self),
    NSStringFromClass(AppDelegate.self)
)

코드 작성 후 앱을 빌드하면 빌드가 성공한다.

UIApplicationMain

UIApplicationMain은 4개의 인자를 받는다.

func UIApplicationMain(_ argc: Int32, 
                     _ argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>, 
                     _ principalClassName: String?, 
                     _ delegateClassName: String?) -> Int32
  • argc : argv의 개수
  • argv : 앱을 실행할 때에 넘겨 줄 변수 목록
  • principalClassName : UIApplication 클래스를 서브클래싱 한 경우 클래스의 이름을 전달한다. nil을 작성한 경우 UIApplication으로 추정된다.
  • delegateClassName : 앱 델리게이트 클래스 이름. 만약 nib 파일 내에 앱 델리게이트 객체가 정의되어 있다면 nil을 전달해야 한다.

이제 앱의 시작지점을 지정할 수 있다.

앱의 실행 과정

간단히 말하면, UIApplicationMain 함수는 앱의 시작점이며, 앱의 실행을 위한 주요 객체들을 생성하는 함수이다. UIApplicationMain() 함수를 호출 했을 때 일어나는 일들을 알아보자.

  1. UIApplicationMain 메소드가 호출된다.
  2. UIApplication 객체를 생성한다.
  3. AppDelegate를 생성한다.
  4. 메인 스토리 보드와, nib 파일을 로드한다.
  5. SceneDelegate를 생성한다.
  6. window 객체를 생성한다.
    초기 ViewController의 인스턴스를 window의 RootViewController로 할당한다.
  7. ViewController의 view가 로드된다.

각 단계를 조금 자세히 알아보자!😃

1. UIApplicationMain 메소드를 호출한다.

UIKit은 UIapplication을 생성한다. 생성된 UIApplication은 UIApplicationMain 함수를 호출하게 된다. (아래 설명은 UIApplicationMain에 전달된 3,4번째 인자가 nil이라고 가정한다.)

2. UIApplication 객체를 생성한다.

3. AppDelegate를 생성한다.

AppDelegate 객체는 iOS 앱 내에서 오직 하나의 인스턴스만 생성됨을 보장받는다. 앱이 처음 만들어질 때 객체가 생성되고, 앱이 실행되는 동안 유지되다가 앱이 종료되면 그때 함께 소멸하는 등 앱 전체의 생명주기와 함께한다.

앱이 시작되면 AppDelegate에서는 application(_:willFinishLaunchingWithOptions:)application(_:didFinishLaunchingWithOptions:)를 호출한다.
해당 메소드 내에서 사용자 데이터 구조를 초기화 하게된다. 메소드 내에 작업들은 동기적으로 작동 되므로, 두 메소드 안에서 오랜 작업을 수행한다면 앱을 시작하는데에 오랜 시간이 소요된다. 값이 반환된 이후에 앱의 상태를 변경시킨다.

4. 메인 스토리 보드와, nib 파일을 로드한다.

앱은 스토리 보드의 초기 ViewController를 찾기 위해 시도한다. 초기 ViewController를 찾아 인스턴스를 생성한다.

5. SceneDelegate를 생성한다.

Scene은 디바이스에서 실행되고 있는 앱의 UI 인스턴스를 나타낸다. 사용자 스크린에 UI를 나타내기 위한 window, view, viewcontroller들을 관리하기 위해 scene 객체를 사용한다는 것이다. UI 인스턴스 생성은 제공받은 정보에 의존하는데, 이러한 정보를 가지고 있는 것이 Info.plist이다. 런타임 시간동안에 dynamic하게 관리 될 수도 있다.

6. Window 객체를 생성한다.

윈도우 인스턴스를 할당한다. 또한, 초기 View controller의 인스턴스를 window의 RootViewController로 할당한다.

7. ViewController의 view가 로드된다.

만약 storyboard나 xib로 부터 view를 생성했다면 이 객체는 초기화되고 초기 인터페이스의 객체가 된다. 이제 뷰는 윈도우에 올라가게 되고, 이것의 subview가 사용자에게 보여지게 된다. 이제 view controller의 viewDidLoad가 호출 될 수 있고, 앱이 실행될 준비가 갖춰진다.

정리

UIApplicationMain의 역할

  • iOS앱의 entry point(시작 진입점)
  • 핵심 객체를 생성하는 프로세스를 핸들링
  • 스토리보드 파일로부터 앱의 유저 인터페이스를 읽어들임
  • 커스텀 코드를 호출해 줌
  • 앱 생성 초기에 필요한 설정을 구현할 수 있게 해 줌

참고

https://oleb.net/blog/2011/06/app-launch-sequence-ios/

애플 개발 문서

profile
 iOS Developer 좋아하는 것만 해도 부족한 시간

0개의 댓글