iOS에서 UIViewController의 라이프사이클(ViewController Life Cycle)은 화면이 사용자에게 보이기 전부터 사라진 이후까지의 일련의 과정,
각 단계마다 특정 메서드가 호출되며, 개발자는 이 메서드를 오버라이드해서 원하는 동작을 넣을 수 있습니다

| 호출 시점 | 메서드 | 설명 |
|---|---|---|
| 처음 메모리에 로드될 때 | viewDidLoad() | 뷰가 메모리에 올라간 직후 한 번만 호출됨. 초기 설정 (UI 구성, 데이터 로딩 등)에 사용 |
| 화면에 나타나기 직전 | viewWillAppear(_:) | 뷰가 곧 사용자에게 보이기 직전. UI 업데이트, 애니메이션 준비 |
| 뷰가 화면에 점점 나타나는 도중 호출 | viewIsAppearing(_:) | 화면 전환 애니메이션에 맞춰 특정 작업을 시작할 때, 뷰가 아직 완전히 보여지진 않았지만, 어느 정도 렌더링된 시점에 UI를 조정할 때 |
| 화면에 나타난 직후 | viewDidAppear(_:) | 뷰가 완전히 나타난 후. 애니메이션 시작, 네트워크 호출 등 가능 |
| 화면에서 사라지기 직전 | viewWillDisappear(_:) | 다른 뷰로 넘어가기 전에 호출됨. 타이머 정지, 상태 저장 |
| 완전히 사라진 후 | viewDidDisappear(_:) | 뷰가 완전히 사라진 후. 리소스 해제, 상태 초기화 등 |
실습
먼저 ViewController를 두개 만들어 LifeCycle이 어떤식으로 동작하는지 알아 보자
일단 SceneDelegate에 UIKit을 codebase로 구현할 것 이기 때문에 이렇게 작성한다. 그리고 UINavigationController를 이용해서 화면간의 설정을 할 수 있게 만들었다.
UINavigationController
UINavigationController는 iOS 애플리케이션에서 계층적인 네비게이션 구조를 관리하는 컨트롤러로, 화면 간의 이동과 스택 기반의 화면 관리를 담당합니다.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UINavigationController(rootViewController: ViewController())
window.makeKeyAndVisible()
self.window = window
}
그리고 ViewController에서 LifeCycle을 확인을 하려고 각 주기에 print문을 작성해보았다
import UIKit
import SnapKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad")
}
override func viewWillAppear(_ animated: Bool) {
print("ViewWillAppear")
}
override func viewIsAppearing(_ animated: Bool) {
print("ViewIsAppearing")
}
override func viewDidAppear(_ animated: Bool) {
print("ViewDidAppear")
}
override func viewWillDisappear(_ animated: Bool) {
print("ViewWillDisappear")
}
override func viewDidDisappear(_ animated: Bool) {
print("ViewDidDisappear")
}
}
이걸 빌드를 해보면

이런식으로 뜨는것을 볼 수 있는데 화면이 보여주기 까지의 LifeCycle을 확인 할 수 있었다.
그렇다면 이제 View가 사라지는 과정을 살펴보자면
import UIKit
import SnapKit
class ViewController: UIViewController {
private lazy var button: UIButton = {
let button = UIButton()
button.setTitle("다음 페이지로 이동", for: .normal)
button.backgroundColor = .red
button.setTitleColor(.white, for: .normal)
button.addTarget(self, action: #selector(buttonTapped), for: .touchDown)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
print("viewDidLoad")
}
override func viewWillAppear(_ animated: Bool) {
print("ViewWillAppear")
}
override func viewIsAppearing(_ animated: Bool) {
print("ViewIsAppearing")
}
override func viewDidAppear(_ animated: Bool) {
print("ViewDidAppear")
}
override func viewWillDisappear(_ animated: Bool) {
print("ViewWillDisappear")
}
override func viewDidDisappear(_ animated: Bool) {
print("ViewDidDisappear")
}
private func configureUI() {
[button].forEach { view.addSubview($0) }
view.backgroundColor = .white
button.snp.makeConstraints() {
$0.center.equalToSuperview()
$0.width.equalTo(300)
$0.height.equalTo(100)
}
}
@objc
private func buttonTapped() {
self.navigationController?.pushViewController(AdamViewController(), animated: true)
}
}
이런식으로 ViewController에 버튼을 만들고
import UIKit
class AdamViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("AdamViewController viewDidLoad")
view.backgroundColor = .orange
}
}
버튼을 누르면 AdamViewController로 화면이 전환이 되는 것을 설정하였다.
그래서 버튼을 누르면

AdamViewController가 메모리에 올라가고 ViewController가 Disappear 되는 것을 볼 수 있다.
ViewController LifeCycle 실습 고찰
iOS 앱을 개발하면서 ViewController의 LifeCycle을 이해하는 것은 매우 핵심적인 개념입니다.
각 메서드가 언제 호출되는지 정확히 이해하고 있어야 UI 구성, 데이터 처리, 애니메이션, 리소스 해제 등의 적절한 시점에 코드를 배치할 수 있습니다.
이번 실습에서는 코드를 기반으로 LifeCycle 메서드의 호출 순서를 직접 print()를 통해 확인해보며 이해도를 높일 수 있었고, 특히 화면 전환 전후의 LifeCycle 변화를 명확하게 확인할 수 있었습니다.
ViewDidLoad() → ViewWillAppear() → ViewIsAppearing() → ViewDidAppear()
ViewDidLoad(): 최초 1회만 호출되며, UI 초기화 및 설정에 적합한 시점
ViewWillAppear(): 뷰가 보이기 직전. 사용자에게 보이기 전에 준비해야 하는 UI 처리
ViewIsAppearing(): 뷰가 화면에 점점 나타나는 도중 호출됨 (iOS 17+)
ViewDidAppear(): 뷰가 완전히 나타난 후 호출되어 애니메이션 시작, 네트워크 요청 등을 하기에 적절
ViewWillDisappear() → ViewDidDisappear()
ViewWillDisappear(): 다른 화면으로 이동하기 직전 호출되어 상태 저장, 타이머 종료 등에 사용
ViewDidDisappear(): 완전히 사라진 후 호출되어 리소스 정리나 초기화 작업에 적절
UINavigationController를 통해 화면을 Stack 구조로 관리하며, push/pop을 통해 화면 전환 시 LifeCycle의 흐름을 자연스럽게 체험할 수 있었음
버튼 액션을 통해 AdamViewController로 전환되면서 기존 ViewController가 사라지고, 새로운 ViewController가 메모리에 올라오는 순서를 콘솔에서 직접 확인함
참고
https://developer.apple.com/documentation/uikit/uiviewcontroller