iOS의 viewDidLoad: 개념, 목적 및 코드 예제

저자: IT Sectr 게시일: 2026-03-05 읽는 시간: 8 분

viewDidLoad는 UIKit이 UIViewController의 View를 메모리에 로드한 후 호출하는 첫 번째 메서드입니다. Apple Developer Documentation에 따르면 이 메서드는 컨트롤러의 전체 수명 동안 정확히 한 번 호출됩니다. viewDidLoad는 인터페이스 초기 설정, 셀 등록 및 데이터 초기화를 위한 주요 위치입니다.

핵심 요점

  • viewDidLoad는 View가 메모리에 로드된 후 한 번 호출됩니다
  • super.viewDidLoad는 필수 — 없으면 Lifecycle이 깨집니다
  • 이 메서드에서 UI를 구성하고, 셀을 등록하고, data source를 만듭니다
  • 화면으로 돌아갈 때 다시 호출되지 않음 — viewWillAppear 사용
  • 일회성 작업 및 영구 알림 구독에 적합

viewDidLoad란

viewDidLoad는 UIKit이 컨트롤러의 View를 메모리에 로드한 직후에 호출하는 UIViewController의 인스턴스 메서드입니다. 이 시점에서 모든 IBOutlet 속성은 이미 인터페이스 요소에 연결되어 있지만, View는 아직 창 계층 구조에 추가되지 않았고 사용자에게 표시되지 않습니다. 개발자는 이 메서드를 재정의하여 초기 화면 구성을 수행합니다.

이 메서드는 ViewController Lifecycle의 일부이며, View가 프로그래밍 방식으로 생성된 경우 loadView 직후 또는 Storyboard에서 로드한 후에 호출됩니다. 일반적인 프로젝트에서 viewDidLoad는 UIViewController에서 가장 자주 재정의되는 메서드로, 이미 존재하고 구성 준비가 된 서브뷰로 작업할 수 있는 안전한 지점을 제공합니다.

중요한 세부 사항: viewDidLoad가 호출될 때 View의 크기는 아직 최종 크기와 일치하지 않습니다 — Auto Layout이 패스를 완료하지 않았으며 프레임이 예상과 다를 수 있습니다. 크기에 의존하는 계산에는 viewDidLayoutSubviews를 사용하세요.

viewDidLoad가 호출되는 시기

viewDidLoad 호출의 시점은 컨트롤러가 어떻게 초기화되는지에 따라 달라집니다. 대부분의 경우 UIKit은 컨트롤러의 view 속성에 처음 액세스할 때 이 메서드를 자동으로 호출합니다 — 이를 UIViewController의 지연 로딩(lazy-loading) 메커니즘이라고 합니다.

첫 화면 표시 시

NavigationController 또는 TabBarController가 처음으로 화면을 표시할 때 UIKit은 View가 로드되었는지 확인합니다. 로드되지 않은 경우 — loadView가 호출되거나(또는 Storyboard에서 로드) viewDidLoad가 즉시 트리거됩니다. 이것이 표준 시나리오이며 각 컨트롤러 인스턴스에 대해 한 번 발생합니다.

swift
override func viewDidLoad() {
    super.viewDidLoad()
    print("View가 로드되었습니다 — 인터페이스를 구성할 수 있습니다")
    setupUI()
    configureTableView()
}

기존 화면으로 돌아갈 때

뒤로 가기 버튼이나 dismiss를 통해 화면으로 돌아갈 때 viewDidLoad가 다시 호출되지 않습니다. 로직이 화면이 다시 나타나는 것에 의존하는 경우 — viewWillAppear에 배치하세요. 이것은 가장 일반적인 개념적 오류 중 하나입니다: 개발자는 viewDidLoad가 모든 표시에서 실행될 것으로 기대하지만 UIKit은 한 번만 호출합니다.

forcedViewLoad 시

개발자는 미리 로드를 트리거하기 위해 컨트롤러의 view에 강제로 액세스하는 경우가 있습니다: let _ = controller.view. 이렇게 하면 컨트롤러가 화면에 나타나기 전에 loadView와 viewDidLoad가 강제로 호출됩니다. 이 기술은 부드러운 전환을 위해 View를 미리 준비해야 할 때 사용됩니다.

viewDidLoad에서 해야 할 일

viewDidLoad는 화면이 표시되는지 여부에 의존하지 않는 일회성 설정 작업을 위한 것입니다. 이 메서드의 올바른 사용은 깔끔한 아키텍처와 예측 가능한 컨트롤러 동작의 핵심입니다.

UI 구성 요소 설정

viewDidLoad에서 UITableView 및 UICollectionView의 nib 파일과 클래스를 등록하고, 델리게이트를 구성하고, UI 요소 속성의 초기 값을 설정합니다. 이 시점에서 모든 IBOutlet이 이미 연결되어 있으므로 label.text, imageView.image 및 기타 서브뷰 속성에 안전하게 액세스할 수 있습니다.

swift
override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(
        CustomCell.self,
        forCellReuseIdentifier: CustomCell.identifier
    )
    title = "메인 화면"
}

데이터 초기화 및 구독

여기서 viewModel을 만들고, 배열로 data source를 초기화하고, 컨트롤러의 전체 수명 동안 활성 상태여야 하는 알림을 구독합니다. 예를 들어, 백그라운드에서 돌아올 때 데이터를 업데이트하기 위해 UIApplication.willEnterForegroundNotification을 구독하는 것은 viewDidLoad의 좋은 대상입니다. 현대 iOS 아키텍처에서 viewModel은 컨트롤러와 비즈니스 로직 사이의 브리지 역할을 하며, viewDidLoad에서 초기화하면 화면이 처음 나타날 때까지 데이터가 준비됩니다.

테이블과 컬렉션의 data source 구성에 특히 주의하세요. 테이블이 Core Data와 함께 UIFetchedResultsController 또는 NSFetchedResultsController를 사용하는 경우 viewDidLoad에서 fetch request와 델리게이트를 초기화하세요. 이렇게 하면 화면이 처음 나타날 때 추가 요청 없이 테이블이 이미 데이터로 채워져 있습니다.

탐색 설정

viewDidLoad에서 NavigationBar 버튼을 구성하고, large title을 설정하고, search controller를 추가하고, edit/done 버튼을 설정합니다. 이러한 요소는 화면이 다시 표시될 때 거의 변경되지 않으므로 여기서 초기화하는 것이 최적입니다.

viewDidLoad에서 피해야 할 일

모든 작업이 viewDidLoad에 적합한 것은 아닙니다. 이 메서드에 배치된 일부 작업은 과도한 메모리 소비, 잘못된 동작 또는 화면 재표시 시 버그를 유발합니다.

피하세요: 결과가 UI에만 영향을 미치는 네트워크 요청 시작. 요청이 화면 표시 전에 완료되면 사용자가 결과를 볼 수 없고, 이후에 완료되면 데이터가 오래되었을 수 있습니다. viewDidLoad에서 로드를 시작하지만 UI는 viewWillAppear에서 업데이트하세요.

하지 마세요: View의 크기와 위치에 의존하는 작업을 viewDidLoad에서 수행하는 것. 호출 시점에 Auto Layout이 패스를 완료하지 않았으며 프레임이 최종적이지 않을 수 있습니다. 계산에는 viewDidLayoutSubviews를 사용하거나 updateViewConstraints를 재정의하세요.

구독하지 마세요: 화면이 표시될 때만 관련이 있는 알림. 키보드 알림, 자식 컨트롤러의 콘텐츠 변경 알림 — viewWillAppear에서 구독하고 viewDidDisappear에서 구독 취소하여 불필요한 호출과 누수를 방지하세요.

호출하지 마세요: 표시 화면이 필요한 메서드. 예를 들어 viewDidLoad에서 UIAlertController를 표시하려고 하면 컨트롤러의 View가 아직 창 계층 구조에 추가되지 않았기 때문에 오류가 발생합니다. window 또는 presentedViewController에 의존하는 UI 작업은 화면이 표시된 후에만 수행해야 합니다.

초기화하지 마세요: 불필요하게 무거운 리소스. 화면이 거의 표시되지 않거나 데이터가 즉시 표시되지 않는 경우 리소스 집약적 객체의 생성을 실제로 필요할 때까지 지연시키세요. Swift의 지연 속성 초기화는 이 문제를 해결하기 위한 내장 메커니즘입니다: lazy 수식어가 있는 속성은 첫 번째 액세스 시에만 생성되어 메모리를 절약하고 화면 로딩을 가속화합니다.

사용하지 마세요: 화면이 표시될 때마다 실행되어야 하는 작업에 viewDidLoad를 사용하는 것. 이것이 가장 근본적인 실수입니다: 초보 개발자는 종종 데이터 업데이트 로직을 viewDidLoad에 배치하고 다른 화면에서 돌아올 때 테이블이 다시 로드되지 않는 것에 놀랍니다. 작업이 모든 표시에서 반복되어야 하는 경우 — viewWillAppear를 사용하세요. 수명 동안 한 번 실행되어야 하는 경우 — viewDidLoad를 사용하세요. UIViewController 생명 주기의 대부분의 문제를 피하기 위해 이 간단한 규칙을 기억하세요.

viewDidLoad 코드 예제

실제 프로젝트에서 viewDidLoad의 올바른 사용을 보여주는 세 가지 실용적인 예제를 살펴보겠습니다. 각 예제는 특정 화면 구성 작업을 해결합니다.

예제 1: 사용자 정의 셀로 컬렉션 구성

swift
override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.register(
        PhotoCell.self,
        forCellWithReuseIdentifier: PhotoCell.reuseId
    )
    collectionView.register(
        HeaderView.self,
        forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
        withReuseIdentifier: HeaderView.reuseId
    )
    viewModel.delegate = self
    viewModel.fetchInitialPage()
}

예제 2: 프로그래밍 방식으로 제약 조건 설정

swift
override func viewDidLoad() {
    super.viewDidLoad()
    let label = UILabel()
    label.text = "안녕하세요, 세계!"
    label.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(label)

    NSLayoutConstraint.activate([
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    ])
}

예제 3: 빈 상태와 로더 구성

viewDidLoad에서는 데이터가 없을 때 표시되는 요소(빈 상태, 로더, 플레이스홀더)도 구성합니다. 이러한 구성 요소는 한 번 생성되고 화면이 표시될 때마다 재사용됩니다. 이러한 요소의 숨김/표시는 현재 데이터에 따라 viewWillAppear에서 관리됩니다.

swift
override func viewDidLoad() {
    super.viewDidLoad()
    emptyStateLabel = UILabel()
    emptyStateLabel.text = "데이터 없음"
    emptyStateLabel.textAlignment = .center
    emptyStateLabel.isHidden = true
    view.addSubview(emptyStateLabel)

    activityIndicator = UIActivityIndicatorView(style: .medium)
    activityIndicator.hidesWhenStopped = true
    view.addSubview(activityIndicator)
}

예제 4: 애플리케이션 알림 구독

swift
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handleEnterForeground),
        name: UIApplication.willEnterForegroundNotification,
        object: nil
    )
}

@objc private func handleEnterForeground() {
    refreshContent()
}

자주 묻는 질문

viewDidLoad가 두 번 이상 호출될 수 있나요?

정상적인 조건에서는 아닙니다 — UIKit은 View를 메모리에 로드한 후 viewDidLoad를 한 번 호출합니다. 컨트롤러가 소멸되고 다시 생성되면 새 인스턴스에 대해 viewDidLoad가 실행됩니다.

super.viewDidLoad를 호출해야 하나요?

네, 반드시. super.viewDidLoad를 호출하면 UIKit이 Lifecycle이 올바르게 작동하는 데 필요한 내부 설정을 수행합니다. 메서드 내에서 항상 super를 먼저 호출하세요.

viewDidLoad와 viewWillAppear의 차이점은?

viewDidLoad는 View가 로드될 때 한 번 호출됩니다. viewWillAppear는 화면이 나타나기 전에 매번 호출됩니다. 전자는 일회성 설정, 후자는 데이터와 상태 업데이트용입니다.

viewDidLoad에서 무거운 작업을 수행할 수 있나요?

viewDidLoad에서 무거운 동기 작업은 메인 스레드를 차단하고 화면 표시를 지연시킵니다. 비동기 로딩은 허용되지만 완료 시 UI를 업데이트할 때 화면이 이미 숨겨져 있을 가능성을 고려해야 합니다.

viewDidLoad를 강제로 호출하려면?

viewDidLoad를 직접 호출할 수 없습니다 — UIKit이 호출합니다. View 로드를 강제하려면 controller.view 속성에 액세스하세요. 그러면 loadView와 viewDidLoad가 자동으로 트리거됩니다.

요약

  • viewDidLoad는 View가 메모리에 로드된 후 호출되는 일회성 UIViewController 설정 메서드
  • View에 처음 액세스할 때 컨트롤러 수명 동안 한 번 호출됨
  • 셀 등록, 델리게이트 구성, viewModel 초기화에 적합
  • 올바른 Lifecycle 작동을 위해 항상 super.viewDidLoad 호출
  • View 크기에 의존하는 작업에 viewDidLoad 사용하지 않음
  • 매 표시 시 데이터 업데이트에는 viewWillAppear 사용
  • 영구 알림 구독은 적합, 임시 알림은 viewWillAppear에서

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기