공부하며 적는 글입니다. 정확하지 않을 수 있습니다.
@main
이건 어디에 사용하는 것이고, 그 뜻은 뭘까..
@main: Type-Based Program Entry Points
공식문서에 따르면 @main
은 타입 기반의 프로그램 진입점 이라고 설명한다.
프로그램 실행을 시작하기 위한 진입점으로 타입을 지정하는 Swift 언어 기능이라고 한다.
대충 프로그램이 시작할때를 지정해주는 키워드인듯 하다.
그럼 어디서 사용할까?
보통 우리가 @main
을 볼 수 있는 곳은 AppDelegate 클래스이다.
AppDelegate는 앱이 시작되는 진입점을 알려주고, 앱의 입력 이벤트를 전달하는 런루프를 생성하는 역할을 한다.
그리고 @main
은 Swift 5.3 버전 부터 사용하는 키워드이다.
그전에는 @UIApplicationMain
이라는 키워드로 사용하고 있었다.
소개를 조금 자세히 보면, 탑 레벨의 코드를 작성하는 대신 사용자는 싱글타입에 @main
속성을 사용할 수 있다고 설명한다. 또한 라이브러리와 프레임워크는 프로토콜과 클래스 상속을 통해 앱의 진입점을 커스터마이징할 수 있다고 한다.
이게 뭔말이냐;
일단 탑 레벨 코드가 뭔지부터 알아보자.
문서 얘기하는 탑 레벨 코드는 0개 이상의 선언이나 정의 그리고 표현식으로 구성된다고 한다. 기본적으로 소스파일의 탑 레벨에서 선언된 것들은 같은 모듈내의 모든 소스파일에서 접근이 가능하다는 것이다.
이 탑 레벨 코드에는 두 가지 종류가 존재한다고 한다.
탑 레벨 선언과 실행가능한 탑 레벨 코드 이다.
이 중에서 실행가능한 탑 레벨 코드는 오직 프로그램의 진입점으로서만 허용된다고 한다.
따라서 우리가 아까 소개에서 봤던 탑 레벨 코드의는 기존의 진입점을 알려주는 @UIApplicationMain
속성이었다라는 것을 알 수 있다.
그럼 @main
을 알기전엔 그 전에 사용했던 걸 알아야 하지 않겠는가?
Objective-C 기반의 프로젝트에서는 main.m
의 소스파일에 있는 main()
함수를 프로그램이 시작되고, Swift 기반의 Xcode 프로젝트에서 Mac 템플릿을 생성하면 기본적으로 main.swift
파일을 포함하여 main
함수를 쉽게 찾아볼 수 있다.
그런데, Xcode에서 새 iOS 프로젝트를 만들고 앱이 어디서부터 시작되는지 알기 위해 main
함수를 찾아보려고 하면, 뭐 잘 보이지도 않는다.
그 이유는 iOS 기본 템플릿에서는 Swift 파일에 @UIApplicationMain
을 포함함으로써 컴파일러가 iOS의 진입점을 합성하기 때문에 main.swift
파일이 필요하지 않았던 것이다!
그렇다고 main()
함수가 없는건 아니다. Swift 기반의 iOS 프로젝트에서는 UIKit 프레임워크가 이를 숨겨서 관리하고 있기 때문에 찾기가 힘들었던 것이다.
@UIApplicationMain
은 UIApplicationMain
함수를 호출하고 해당 클래스의 이름을 delegate Class의 이름으로 전달한다.
이 함수는 앱 실행에서 중요한 기능들을 수행하게 된다.
@UIApplicationMain
이 표시된 곳)에서 Delegate를 인스턴스화 하고 이를 앱의 객체에 할당한다.앱을 실행하기 위한 제일 중요한 부분들이 여기에서 실행되는 것이었다.
그럼 @UIApplicationMain
의 역할과 함수의 기능에 대해서 알아보았으니, 왜 @main
을 사용하게 됐는지 알아보자.
스위프트의 프로그램은 소스파일의 시작점 부터 시작해 특별한 구문 없이 잘 작동하게 된다.
근데, 사용자용 앱의 경우 종료될 때 까지 계속해서 실행되고, UIKit이나 AppKit과 같은 사용자 인터페이스 프레임워크는 앱 실행의 복잡성을 처리하여 앱 동작을 정의하기 위한 고급의 API 후크를 제공하게 된다.
이런 프레임워크를 사용하는 개발자는 앱 실행의 문자 그대로 시작점에 대해 신경 쓰거나 상호 작용하지 않는다.
이 두 모델의 문제를 해결하기 위해서, 앱은 프레임워크의 기본 실행 시작점을 시작하기 위해 소량의 "부팅 로딩" 코드가 필요로 하게 된다.
그래서 초반에 Swift가 나왔을 때는 @UIApplicationMain
이나 @NSApplicationMain
로 부팅로딩을 제공했었다.
근데 이렇게 조금 길고 직관적이지 않은 코드를 사용하기 보단 @main
과 같은 더 일반적이고 가벼운 메커니즘을 제공하는 것이 더 이상적이라고 생각해서 만들었다고 한다.
이는 스위프트의 타입 기반의 시스템을 사용하여 문제를 해결하는 패턴에 더 적합하다고 한다. 그리고 프레임워크가 표준 언어 기능을 사용하여 깔끔하고 간단한 진입점을 제공할 수 있게 한다.
@UIApplicationMain
대신 @main
속성을 사용함으로써 타입 기반의 스위프트 코드에서 이상적인 프로그램의 진입점을 알려줄 수 있고, main()
함수는 일반 정적 메서드 이므로 프로토콜에서 확장 또는 기본 클래스로 제공할 수 있다.