[UIKit] View Controller의 역할

2025. 1. 14. 00:38·iOS/UIKit
728x90
반응형

안녕하세요, iOS 개발하는 루피입니다.

 

오늘은 공식문서를 바탕으로 View Controller의 역할에 대해 정리해보려고 합니다.

바로 시작해 보겠습니다. ( 편의상 ViewController는 VC라고 하겠습니다 ㅎㅎ )


VC는 앱 내부 구조의 핵심을 이루는 요소이며, 모든 앱은 최소 하나 이상의 VC를 가지고 있습니다.

VC가 하는 일을 간단하게 정리해 보면..

  • 앱 UI의 특정 부분(View)을 관리합니다.
  • 해당 UI와 이를 뒷받침하는 데이터 간의 상호작용을 담당합니다.
  • 앱 내에서 서로 다른 UI 간의 전환을 처리하는 역할을 합니다.

VC는 두 가지 유형으로 나뉩니다.

  • Content View Controller
    • 앱의 특정 콘텐츠를 관리하는 VC로, 개발자가 주로 생성하는 기본적인 VC
  • Container View Controller
    • 다른 VC의 정보를 모아 이를 탐색하기 쉽게 하거나, 자식 VC의 콘텐츠를 새로운 방식으로 표시하는 역할을 하는 VC

대부분의 앱은 이 2가지 유형의 VC를 조합하여 사용합니다.


1. 뷰 관리 (View Management)

VC의 가장 중요한 역할은 View 계층 구조를 관리하는 것입니다.

 

모든 VC는 하나의 Root View를 가지고 있으며, 이는 해당 VC의 모든 콘텐츠를 감싸는 역할을 합니다. Root View에 필요한 하위 View들을 추가하여 콘텐츠를 화면에 표시합니다.

위처럼 VC는 항상 자신의 Root View에 대한 참조를 가지고 있으며, Root View는 각 Subview들을 강한 참조로 관리합니다.

 

Content VC는 자신이 가진 모든 뷰를 직접 관리합니다.

Container VC는 자신의 View 뿐만 아니라 하나 이상의 자식 VC의 Root View도 함께 관리합니다.

하지만 Container는 자식 VC의 콘텐츠를 직접 관리하지 않습니다. 대신 자식 뷰의 Root View만 관리하며, 이를 Container의 디자인에 따라 크기를 조정하고 배치합니다.

 

예를 들어 보겠습니다.

Content VC 예시

class ContentViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 자신의 루트 뷰에 직접 콘텐츠 추가
        view.backgroundColor = .white
        
        let label = UILabel()
        label.text = "This is a Content View Controller"
        label.textAlignment = .center
        label.frame = view.bounds
        view.addSubview(label)
    }
}

Container VC 예시

import UIKit

// Master (왼쪽 화면)
class MasterViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .lightGray
        
        let label = UILabel()
        label.text = "Master View"
        label.textAlignment = .center
        label.frame = view.bounds
        view.addSubview(label)
    }
}

// Detail (오른쪽 화면)
class DetailViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        let label = UILabel()
        label.text = "Detail View"
        label.textAlignment = .center
        label.frame = view.bounds
        view.addSubview(label)
    }
}

// Split View Controller (컨테이너)
class SplitViewExample: UISplitViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Master와 Detail을 자식으로 추가
        let masterVC = MasterViewController()
        let detailVC = DetailViewController()
        
        self.viewControllers = [masterVC, detailVC]
    }
}


2. 데이터 중계(Data Marshaling)

VC는 자신이 관리하는 View와 앱의 데이터를 연결하는 중간 역할을 합니다.

VC와 데이터 객체 간에든 항상 명확한 책임 분리를 유지해야 합니다. 데이터 구조의 무결성을 보장하는 대부분의 로직은 데이터 객체에 속해야 하며, VC는 주로 입력값을 검증하고, 이를 데이터 객체가 요구하는 형식으로 변환하는 역할을 맡습니다.

그러나 VC가 실제 데이터를 직접 관리하는 역할은 최소화해야 합니다.


3. 사용자 상호작용(User Interactions)

VC는 Responder Object로, Responder Chain을 통해 전달되는 이벤트를 처리할 수 있습니다.

  • Responder Object 
    • iOS에서 이벤트를 처리할 수 있는 객체를 말합니다.
    • UIViewController, UIView, UIWindow 등은 모두 Responder Object입니다.
    • 이벤트가 발생하면 iOS는 이를 적절한 응답자 객체로 전달하여 처리합니다.
  • Responder Chain
    • 이벤트가 발생했을 때, 이를 처리할 적절한 객체를 찾기 위해 iOS가 사용하는 체계입니다.
    • 터치 이벤트가 View에서 발생하면, 해당 View가 먼저 이벤트를 처리하려고 시도합니다.
    • View가 이벤트를 처리하지 못하면, 이벤트는 해당 View의 상위 View나 VC로 전달됩니다.
    • 최종적으로 UIApplication이나 UIWindow까지 전달될 수 있습니다.

하지만, VC가 직접 터치 이벤트를 처리하는 경우는 드뭅니다. 대신, 일반적으로 뷰가 자신의 터치 이벤트를 처리한 후, 그 결과를 관련된 Delegate 메서드나 Target 객체의 메서드로 전달합니다. 이 Target 객체는 보통 VC입니다.

따라서 VC에서 대부분의 이벤트는 Delegate 메서드나 Action 메서드를 통해 처리됩니다.

참고

  • VC에서 액션 메서드를 구현하는 방법에 대한 자세한 내용은 Handling User Interactions를 참조하세요.
  • 기타 이벤트 처리 방법에 대한 내용은 Event Handling Guide for iOS를 참고하세요.

4. 리소스 관리(Resource Management)

VC는 자신이 생성한 View와 객체들에 대한 모든 책임을 집니다.

 

UIViewController 클래스는 대부분의 View 관리 작업을 자동으로 처리합니다.

예를 들어, UIKit은 더 이상 필요하지 않은 View 관련 리소스를 자동으로 해제합니다.

 

그러나 UIViewController를 서브클래싱하여 개발자가 명시적으로 생성한 객체는 직접 관리해야 합니다.

직접 관리해야 하는 경우...

class MyViewController: UIViewController {
    var imageCache: [String: UIImage] = [:] // 캐시 데이터
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 이미지 캐시 초기화
        imageCache["example"] = UIImage(named: "exampleImage")
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // 메모리가 부족할 때 캐시 데이터 정리
        imageCache.removeAll()
        print("Image cache cleared!")
    }
}

 

UIKit은 사용 가능한 메모리가 부족할 경우, 앱에게 더 이상 필요하지 않은 리소스를 해제하도록 요청합니다. 이를 위해 UIKit은 VC의 didReceiveMemoryWarning 메서드를 호출합니다. 이 메서드에서 다음과 같은 작업을 수행할 수 있습니다

  • 더 이상 필요하지 않은 객체에 대한 참조를 제거합니다.
  • 나중에 쉽게 다시 생성할 수 있는 캐시 데이터를 삭제합니다.

저메모리 상황에서는 가능한 많은 메모리를 해제하는 것이 중요합니다. 메모리를 과도하게 사용하는 앱은 시스템에 의해 강제로 종료될 수 있기 때문입니다.


4. 적응성(Adaptivity)

VC는 자신의 View를 화면에 표시하고, 환경 변화에 맞게 그 표시 방식을 조정하는 역할을 합니다.

 

iOS 앱은 iPad와 다양한 크기의 iPhone에서 실행될 수 있어야 합니다. 각 기기마다 별도의 VC와 View 계층 구조를 제공하는 대신, 하나의 VC를 사용하여 화면 공간 요구 사항에 맞게 View를 적응시키는 것이 더 간단하고 효율적입니다.

 

iOS에서의 적응성 처리 VC는 대규모 변화와 세부적인 변화를 처리해야 합니다.

적응성을 처리하는 방법

  • 대규모 변화(Coarse-Grained Changes): 트레이트(Traits)와 크기 클래스를 기반으로 레이아웃 조정.
  • 세부적인 변화(Fine-Grained Changes): Auto Layout과 추가 메서드(`viewWillTransition`)를 사용해 처리.

대규모 변화 

  1. 이는 VC의 traits가 변경될 때 발생합니다.
  2. traits는 디스플레이 스케일과 같은 환경의 전반적인 속성을 나타냅니다.
  3. 가장 중요한  traits 중 두 가지는 가로와 세로 크기 클래스입니다.
  4. 크기 클래스는 VC가 해당 방향으로 사용할 수 있는 공간의 정도를 나타냅니다.

대규모 변화  예시

  1. 가로 크기 클래스가 regular(넓은 공간) 일 때는 추가적인 가로 공간을 활용해 콘텐츠를 배치합니다.
  2. 반면, 가로 크기 클래스가 compact(좁은 공간)일 때는 콘텐츠를 세로로 배치하여 공간을 효율적으로 활용합니다. 

그림은 이러한 크기 클래스의 변화를 기반으로 콘텐츠 레이아웃이 어떻게 조정되는지 보여줍니다.

특정 크기 클래스 내에서도, 더 세부적인 크기 변화가 언제든지 발생할 수 있습니다.

 

예를 들어...

 

사용자가 iPhone을 세로 모드에서 가로 모드로 회전할 경우, 크기 클래스 자체는 변경되지 않을 수 있지만, 화면의 실제 가로 및 세로 크기는 보통 변경됩니다.

 

이러한 경우, Auto Layout을 사용하면 UIKit이 자동으로 뷰의 크기와 위치를 새로운 화면 크기에 맞게 조정합니다. 그러나 필요에 따라 VC가 추가적인 조정을 수행할 수도 있습니다.

참고

  • 적응성에 대한 자세한 내용은 The Adaptive Model을 참고하세요.

오늘도 화이팅입니다!

728x90
반응형

'iOS > UIKit' 카테고리의 다른 글

[UIKit] The View Controller Hierarchy  (1) 2025.01.14
[UIKit] Container View Controller  (0) 2025.01.12
[UIKit] ViewController의 생명주기  (0) 2025.01.11
[UIKit] Preparing your UI to run in the foreground  (0) 2025.01.10
[UIKit] 공식문서로 App의 LifeCycle 관리에 대해 알아 보자구요  (0) 2025.01.10
'iOS/UIKit' 카테고리의 다른 글
  • [UIKit] The View Controller Hierarchy
  • [UIKit] Container View Controller
  • [UIKit] ViewController의 생명주기
  • [UIKit] Preparing your UI to run in the foreground
kimsangjunzzang
kimsangjunzzang
루피 님의 블로그 입니다.
  • kimsangjunzzang
    루피 님의 블로그
    kimsangjunzzang
  • 전체
    오늘
    어제
    • 분류 전체보기 (103) N
      • iOS (63) N
        • Swift (34) N
        • UIKit (9)
        • SwiftUI (8)
        • RxSwift (12)
      • FE (8)
        • 모던 자바스크립트 (3)
        • HTML (5)
      • Operating System (1)
      • 트러블 슈팅 (4)
      • 바로 안 나오면 모르는거다 (4)
      • Algorithm (20) N
      • 회고록 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    state
    Concurrency
    boj
    알고리즘
    HTML
    SwiftUI
    C++
    swift
    백준
    프로그래머스
    AppleDeveloperAcademy
    ios
    Algorithm
    디자인 패턴
    task
    ViewController
    arc
    rxswift
    web
    uikit
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
kimsangjunzzang
[UIKit] View Controller의 역할
상단으로

티스토리툴바