[iOS] App 기본 구조를 알아보자 - 1

Fezravien·2021년 9월 27일
0

App-Basic-Struct

목록 보기
1/2
post-thumbnail

엔트리 포인트와 초기화 과정

엔트리 포인트

C 언어에 뿌리를 둔 모든 애플리케이션은 main() 함수로부터 시작되며,
이를 엔트리 포인트(Entry Point, 시작 진입점) 이라 한다.

운영체제가 애플리케이션 내부에 정의된 main() 함수를 찾아 호출하면
여기에 작성된 코드들이 연쇄적으로 실행되면서 우리가 작성해 둔 커스텀 코드까지 도달하게 된다.

Obj-C 역시 C 언어에 기반하고 있기 때문에, 이를 이용하여 만든 iOS 앱도 main() 함수로부터 시작되며,
C 기반의 다른 애플리케이션과 차이점이라면 iOS 앱에서는 main() 함수를 우리가 직접 작성하지 않는다는 것 이다.

대신 Xcode 프로젝트를 생성하면 main() 함수가 자동으로 만들어지는데,
여기에는 iOS 앱이 실행될 때 처리해야 할 내용이 작성되어있기 때문에 main() 함수를 건드릴 필요가 없다.


Main 함수는 뭐해?

main() 함수가 하는 일은 단순한데,
실행 시 시스템으로부터 전달받은 두 개의 인자값과 AppDelegate 클래스를 이용하여
UIApplicationMain() 함수를 호출하고 그 결과로 UIApplication 객체를 반환한다.

생성된 UIApplication 객체는 UIKit 프레임워크에 속해 있으므로 이후의 앱 제어권은 UIKit 프레임워크로 이관된다.


UIApplicationMain

공식문서의 설명을 살펴보면,

"애플리케이션 객체와 대리자를 만들고 이벤트 주기를 설정합니다."

여기서 말하는 대리자(Delegate)는 AppDelegate를 말하며,
이벤트 주기는 사용자와 상호작용을 할 수 있게 해주는 이벤트 루프 생성을 말하는 것 같다.


UIApplicationMain() 함수는 iOS 앱의 엔트리 포인트라고 할 수 있다.

  • 앱의 핵심 객체를 생성하는 프로세스 핸들링
  • 스토리보드 파일로부터 앱의 유저 인터페이스 읽기
  • 작성한 커스텀 코드를 호출해 줌으로써 앱 생성 초기에 필요한 설정을 구현
  • 이벤트를 입력받기 위한 이벤트 루프 실행

이 과정에서 직접 구현해야 하는 부분은 스토리보드 파일이나 초기화를 위한 커스텀 코드이다.


UIApplictaion

공식문서의 설명을 살펴보면,

"iOS에서 실행되는 애플리케이션을 위한 중앙 집중식 제어 및 조정 지점입니다."

모든 iOS앱에는 UIApplication 인스턴스는 하나만 존재한다.
(또는 매우 드물게 UIApplication의 하위클래스)

앱이 시작되면, 시스템은 UIApplicaionMain() 함수를 호출하며,
이 함수는 다른 task들 중에서 싱글톤 UIApplicaion 객체를 만든다.

UIApplication 클래스가 UIResponder를 상속받는데,
이 부분은 다른 포스팅에서 다루겠습니다 🙃

Application 객체의 주요 역할은 들어오는 사용자 이벤트의 초기 라우팅을 처리하는 것이다.

컨트롤 객체(UIControl)가 적절한 target 객체에 전달한 action 메세지를 전달하며,
Application 객체는 open window(UIWindow)의 목록을 유지관리하고,
이를 통해 앱의 UIView 객체를 검색할 수 있다.

UIApplication 클래스는 UIApplicaionDelegate 프로토콜을 준수하고,
일부 프로토콜 메소드를 구현해야하는 delegate를 정의한다.

Application 객체는 delegate에게 중요한 런타임 이벤트를 알리고, 적절히 응답 할 기회를 제공한다.

  • 앱 시작, 종료
  • 메모리 부족 경고

클래스의 API를 따르면 디바이스의 구체적인 행동을 관리할 수 있다.

Subclassing Notes

대부분의 앱은 UIApplication을 서브클래싱 할 필요가 없다.
대신 앱 델리게이트를 통해 시스템과 앱 사이의 상호작용을 관리하면 된다.

만약 아주 드문 경우에서 앱이 시스템보다 먼저 들어오는 이벤트를 다뤄야 한다면,
커스텀 이벤트를 구현하거나 작업 전달 메커니즘을 구현할 수 있다.
이렇게 하려면 UIApplication 과 sendEvent:, sendAction:to:from:forEvent: 메소드를 오버라이드 해야한다.
그리고 가로채는 모든 이벤트에 대해 처리한 후, 다시 시스템에 전달해야 한다.
이벤트를 가로채는 건 거의 필요하지 않고 가능한 피해야 한다.

여기까지 공식문서의 내용이었습니다.

UIApplicationMain() 함수가 생성하는 UIApplication은 앱의 본체라고 할 수 있는 객체로 사실상 앱 그 자체를 의미한다.
이 클래스를 특별한 일이 있거나 중대한 목적이 있는 경우가 아니라면 서브 클래싱 없이 그대로 사용하는데,
굳이 서브 클래싱할 필요도 없고, 하기도 어렵기 때문이다.

그런데 달리 생각해보면 UIApplication 객체를 서브 클래싱하지 않고 그대로 사용하는 것에는 한계가 존재하는데,
의도와 목적에 맞게 특별히 처리해야 할 것도 있을 수 있기 때문이다.

UIApplication 객체는 AppDelegate라는 대리 객체를 내세우고 커스텀 코드를 처리할 수 있도록 약간의 권한을 부여한다.


AppDelegate

AppDelegateUIApplication으로 부터 위임받은 일부 권한을 이용하여
커스텀 코드와 상호작용하는 역할을 담당하고 이를 통해 필요한 코드를 구현할 수 있도록 돕는다.

AppDelegate 객체는 iOS 애플리케이션 내에서 오직 하나의 인스턴스만 생성되도록 시스템적으로 보장받는다.
앱이 처음 만들어질 때 객체가 생성되고, 앱이 실행되는 동안 계속 유지되다가 앱이 종료되면 그때 함께 소멸하는 등

"앱 전체의 생명 주기와 함께 한다."

AppDelegate에 대한 자세한 내용은 다음 포스팅에서 하겠습니다 🙃



초기화

UIApplication 객체와 AppDelegate 객체가 연관되어 앱이 실행되는 전체 과정

  1. main() 함수가 실행된다.
  2. main() 함수는 다시 UIApplicationMain() 함수를 호출한다.
  3. UIApplicationMain() 함수는 앱의 본체에 해당하는 UIApplication 객체를 생성한다.
  4. UIApplication 객체는 Info.plist 파일을 바탕으로 앱에 필요한 데이터와 객체를 로드한다.
  5. AppDelegate 객체를 생성하고 UIApplication 객체와 연결한다.
  6. 이벤트 루프를 만드는 등 실행에 필요한 준비를 진행한다.
  7. 실행 완료 직전, 앱 델리게이트의 application(_:didFinishLaunchingWithOptions:) 메소드를 호출한다.


Swift에서 Main은 어떻게 불리지 🤔

스위프트에는 직접 UIApplicatioMain()을 호출하여 델리게이트 클래스를 인자값으로 전달할 수 없다.

그래서 앱 델리게이트 역할을 할 클래스에 @main 또는 @UIApplicationMain 어노테이션(@)을 걸어 컴파일러에게 알려주는 방식으로
시스템에 델리게이트 클래스 정보를 전달한다.


📄 참고
Apple - UIApplictationMain
Apple - UIApplictaion
[도서] 꼼꼼한 재은씨의 Swift 기본편

profile
꺼진 뷰도 다시보자.

0개의 댓글