[iOS] iOS 앱과 View Controller의 생명주기 (Lifecycle)

문다연·2022년 10월 20일
0

ios.moon

목록 보기
18/26
post-thumbnail

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

C언어에 뿌리를 둔 모든 애플리케이션은 main() 함수로부터 시작되며, 이를 엔트리 포인트(Entry Point)라고 한다. OS가 애플리케이션 내부에 정의된 main() 함수를 찾아 호출하면 이곳에 작성된 코드들이 연쇄적으로 실행되면서 커스텀 코드까지 도달하게 되는 방식이다.

Objective-C 역시 C언어에 기반하고 있기 때문에, Obejective-C로 만들어진 iOS앱도 main() 함수로부터 시작된다. 하지만 iOS 앱에서는 main() 함수가 자동으로 만들어지기 때문에 직접 건드릴 필요가 없다. 이 main() 함수는 실행시 UIApplicationMain() 함수를 호출하고, 그 결과로 UIApplication 객체를 반환한다. 여기서 생성된UIApplication 객체는 UIKit 프레임워크에 속해 있으므로 이후의 앱 제어권은 UIKit 프레임워크로 이관된다. UIApplication 객체는 Info.plist 파일을 바탕으로 앱에 필요한 데이터와 객체를 로드한다.

UIApplication은 앱의 본체라고 할 수 있다. 내가 작성한 커스텀 코드나 객체들, 그리고 앱의 기능이라고 생각하는 모든 것들은 다 UIApplication에 포함되어 있는 하위객체이다.

이런 UIApplication 객체의 역할은 매우 다양하다.

  1. 이벤트 루프나 다른 높은 수준의 앱 동작을 관리한다.
  2. 푸시 알림과 같은 특수한 이벤트를 내가 정의한 커스텀 객체인 Delegate에게 알려준다.

이 클래스는 특별하지 않으면 서브 클래싱 없이 그대로 사용한다. 하지만 의도와 목적에 맞게 특별히 처리해야 할 것도 있을 수 있어 그대로 사용하는 것에는 한계가 있다. 그래서 UIApplication 객체는 AppDelegate라는 대리 객체를 내세우고 커스텀 코드를 처리할 수 있도록 약간의 권한을 부여한다.

UIApplication과 AppDelegate 객체의 관계는 기업의 회장과 비서실의 관계와 유사하다. 회장 역할의 UIApplication 객체는 앱이 해야 할 아주 중요하고 핵심적인 일(앱의 생명 주기 관리나 이벤트 처리 등)을 담당하고, AppDelegate는 커스텀 코드를 처리하는 비서의 성격을 띤다.

AppDelegate 객체는 커스텀 코드와 연결되는 만큼, 대부분 커스터마이징이나 서브 클래싱하여 사용할 수 있도록 오픈되어 있다. AppDelegate 객체는 iOS 애플리케이션 내에서 오진 하나의 인스턴스만 생성되도록 시스템적으로 보장받는다. 게다가 앱 전체의 생명 주기와 함께하기 때문에 AppDelegate 객체에 데이터를 저장하면 앱이 종료될 때까지 계속 데이터를 유지할 수 있다.

반면 스위프트는 C 기반의 언어가 아니다. 따라서 스위프트 기반 프로젝트에는 main.m 파일이 존재하지 않으며 엔트리 포인트 역시 존재하지 않는다. 이 때문에 스위프트에서는 위 과정을 @UIApplicationMain 어노테이션 표기로 대체해 시스템에 델리게이트 클래스 정보를 전달한다. 이후 과정으로는 동일하게 진행된다. 이벤트 루프를 만드는 등 실행에 필요한 준비를 진행한다. → 실행 완료 직전, 앱 델리게이트의 application(_:didFinishLaunchingWithOptions:) 메소드를 호출한다.

iOS 앱의 Life Cycle (좌 iOS 시스템 프레임워크, 우 커스텀 코드)

iOS 앱의 상태 변화와 생명 주기

앱은 실행하는 동안 다양한 상태로 변화한다. 앱이 가질 수 있는 상태는 다음과 같다.

상태설명
Not Running앱이 시작되지 않았거나 실행되었지만 시스템에 의해 종료된 상태
Inactive앱이 전면에서 실행 중이나, 아무런 이벤트를 받지 않고 있는 상태
Active앱이 전면에서 실행 중이며, 이벤트를 받고 있는 상태
Backgroud앱이 백그라운드에 있지만 여전히 코드가 실행되고 있는 상태
대부분의 앱은 Suspended 상태로 이행하는 도중에 일시적으로 이 상태에 진입하지만,
여분의 실행 시간이 필요한 경우 특정 시간동안 이 상태로 남아있음
Suspended앱이 메모리에 유지되지만 실행되는 코드가 없는 상태
메모리가 부족한 상황이 오면 iOS 시스템은 foreground에 있는 앱의
여유 메모리 공간 확보를 위해 이 상태에 있는 앱들을 특별한 알림없이 정리함

iOS 앱의 생명 주기 (Lifecycle), 실행 상태 변화
출처 [https://purple-log.tistory.com/27]

위 그림은 iOS 앱의 생명주기이다. 어떤 특정한 순간에 앱은 이 상태 중 하나일 수도 있고, 하나의 상태에서 다른 상태로 옮겨가는 중일 수도 있다. 특히 다른 상태에로 옮겨가는 중일 때 이를 상태 변화라고 한다.


상태 변화가 나타날 때마다 앱 객체는 앱 델리게이트에 정의된 특정 메소드를 호출한다. 상태에 따라 다양한 메소드들이 정의되어 있으며, 각 메소드들은 모두 그에 맞는 상태 변화에 따라 호출되므로 필요하다면 적절한 커스텀 코드를 작성하여 원하는 작업이 실행되도록 할 수 있다.

  • application(_:willFinishLaunchingWithOptions:)
    앱이 구동되어 필요한 초기 실행 과정이 완료되기 직전에 호출
  • application(_:didFinishLaunchingWithOptions:)
    앱이 사용자에게 화면으로 표시되기 직전에 호출
  • applicationDidBecomeActive(_:)
    앱이 화면 전면(foreground)에 표시될 때 호출
    앱이 Inactive 상테에 들어가면서 일시 중지된 작업이 있다면 이를 재시작하는 코드를 여기에 작성
  • applicationDidEnterBackground(_:)
    앱이 백그라운드 상태에 진입했을 때 호출
  • applicationWillTerminate(_:)
    앱이 종료되기 직전에 호출

더 자세한 메소드는 애플의 개발자 공식 문서를 참고한다.


뷰 컨트롤러의 상태 변화와 생명 주기

앱 자체의 상태 변화와 생명 주기가 있듯, 뷰 컨트롤러도 생명 주기와 상태 변화를 가진다. 뷰 컨트롤러의 생명 주기는 (Scene, 뷰 컨트롤러가 하나씩의 화면을 담당하여 컨텐츠를 표현하고 뷰를 관리하는 것)의 전환과 복귀에 밀접하게 연관되어 있다. 일반적으로 씬의 전환과 이전 화면으로 복귀하는 과정에서 VC(View Controller) 객체의 생성과 소멸이 발생하기 때문이다.
화면이 처음 메모리에 로드되고 스크린에 장면이 표시되었다가 장면의 목적을 달성하여 사라지는 일련의 과정 동안 VC는 계속해서 다른 VC와의 상호관계에 의해 동작하거나 HW, OS의 제어에 의해 움직이게 된다. 이때 화면 상태에 따라 메모리를 효율적으로 관리하기 위해서는 세부적인 제어가 필요한데, 일명 튜닝이라고 한다.

앱의 생명 주기에 따라 호출되는 앱 델리게이트의 메소드들이 정해져 있듯, VC가 특정 상태 변화를 일으킬 때에도 호출하는 메소드들이 VC에 정의되어 있다.

View Controller의 생명주기 (Lifecycle)

뷰 컨트롤러의 생명 주기에 따르면 다음과 같이 네 가지 상태로 나눌 수 있다.

상태설명
AppearingVC가 스크린에 등장하기 시작한 순간부터 등장을 완료하기 직전까지의 상태
퇴장 중인 다른 VC와 교차하기도 함
AppearedVC가 스크린 전체에 완전히 등장한 상태
DisappearingVC가 스크린에서 가려지기 시작해서 완전히 가려지기 직전까지의 상태,
또는 퇴장하기 시작해서 완전히 퇴장하기 직전까지의 상태
DisappearedVC가 스크린에서 완전히 가려졌거나 혹은 퇴장한 상태

특이한 것은 상태의 일부는 완료가 아니라 진행 중인 상태를 나타내기도 한다는 점이다.

  • View Controller의 상태에 따라 호출되는 UIViewController 클래스에 정의된 메소드와 호출 시점
    • viewWillAppear(_:) Appearing
    • viewDidAppear(_:) Appeared
    • viewWillDisappear(_:) Disappearing
    • viewDidDisappear(_:) Disappeared

평소에 앱의 생명주기에 대해 잘 모르는 상태로 개발을 계속해왔는데,
정확히 공부하고 보니 상태에 따라 앱에게 어떤 동작을 부여해줄지 결정하는 데에 중요한 개념이었다.
주로 SwiftUI를 이용해서 개발해와서 MVVM 패턴에 익숙하다보니 잘 몰랐지만,
앞으로 MVC 패턴에 대해 공부하고 개발하기 위해, 
앞서 살펴본 상태에 따라 호출되는 메소드들을 잘 인지하고 있어야할 것 같다.

Ref.

📓 꼼꼼한 재은씨의 스위프트 : 기본편
 애플 공식 문서

profile
ios-moon.tistory.com 이전했어요 🚛

0개의 댓글