먹고 기도하고 코딩하라

[SwiftUI] App과 Scene, View는 어떻게 다른가? 본문

앱/Swift

[SwiftUI] App과 Scene, View는 어떻게 다른가?

사과먹는사람 2022. 6. 22. 12:10
728x90
728x90

 

공식 문서로 살펴보자.

 

 

App

  • App 프로토콜을 따르는 구조체를 선언해 앱을 만들 수 있음
  • body 연산 프로퍼티를 구현해 앱 콘텐츠를 정의
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            Text("Hello, world!")
        }
    }
}
  • 이 경우, App 구조체 선언 윗줄에 들어가는 @main 어트리뷰트는 MyApp이 앱의 시작점(entry point)이 된다는 것을 가리킴
  • App 프로토콜은 기본적으로 앱을 실행할 수 있는 main() 메소드 구현을 제공하지만, 전체 앱 파일 중에서 딱 1개에만 entry point가 있어야 함
  • App의 body는 Scene 프로토콜을 따르는 객체들로 구성할 수 있으며, 각 scene은 뷰 계층(view hierarchy)의 루트 뷰를 포함하고, 시스템에 의해 관리되는 생명주기를 가짐
@main
struct Mail: App {
    var body: some Scene {
        WindowGroup {
            MailViewer()
        }
        Settings {
            SettingsView()
        }
    }
}

 

Scene

  • 프로토콜로서, 시스템에 의해 관리되는 앱의 생명주기와 앱의 UI의 부분을 구성하는 한 부분
  • Scene은 사용자들에게 보여주고 싶은 View hierarchy(뷰 계층)의 컨테이너 역할
  • 시스템은 플랫폼에 알맞게, 또 앱의 현재 상태에 따라 언제, 어떻게 view hierarchy를 보여줄지 결정
  • Scene의 some Scene을 반환하는 body 연산 프로퍼티에 하나 혹은 그 이상의 Scene 프로토콜을 따르는 Scene들을 넣어 조합해 커스텀 씬에 들어갈 콘텐츠를 지정할 수 있음
struct MyScene: Scene {
    var body: some Scene {
        WindowGroup {
            MyView()
        }
    }
}
  • WindowGroup 같은 SwiftUI가 기본 제공하는 빌트인 Scene들을 사용할 수 있고, 커스텀 Scene을 만들어서 다른 Scene들과 조합할 수도 있음. iPadOS, macOS에서 여러 window를 띄우는 기능을 제공
  • 커스텀 Scene을 만들려면 Scene 프로토콜을 따르는 타입을 선언해 만들 수 있음

 

View

  • 앱의 UI 부분을 나타내고, 뷰를 설정하는 데 쓰이는 modifiers들을 제공하는 프로토콜
  • Scene에 들어가는 View hierarchy(뷰 계층)의 기초가 됨
  • View 프로토콜을 따르면 커스텀 뷰를 만들 수 있음
  • 어떤 View를 반환하는 body 연산 프로퍼티를 구현해 커스텀 뷰에 들어갈 콘텐츠를 지정
  • SwiftUI에서 제공하는 Text 같은 빌트인 뷰들을 조합해 뷰의 body 프로퍼티를 채울 수 있음
struct MyView: View {
    var body: some View {
        Text("Hello, World!")
    }
}

 


 

그럼 App의 body, Scene의 body, View의 body 연산 프로퍼티는 차이가 있는 걸까?

다르다. 문서도 다 따로 있다. 무슨 차이가 있는지 살펴보자.

 

App - body 

앱의 콘텐츠와 행위를 나타내는 필수 프로퍼티

var body: Self.Body { get }
  • 앱의 scene들을 정의하는 body 연산 프로퍼티가 필요
  • App의 body 프로퍼티 안에 들어가는 것들은 Scene 프로토콜을 따르는 객체들
  • 예를 들어 다음과 같이 싱글 뷰를 담은 싱글 씬을 앱에 담을 수 있음
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            Text("Hello, world!")
        }
    }
}

 

Scene - body

씬의 콘텐츠와 행위를 나타냄. 선언은 App의 body와 똑같다.

struct MyScene: Scene {
    var body: some Scene {
        WindowGroup {
            MyRootView()
        }
    }
}
  • 어떤 app을 만들든 간에 body 프로퍼티가 있어야 하고, 이 프로퍼티는 app의 Scene 프로토콜을 따르는 scenes을 정의한다. 

 

View - body

뷰의 콘텐츠와 행위를 나타냄. 선언은 App의 body와 똑같다.

struct MyView: View {
    var body: some View {
        Text("Hello, World!")
    }
}
  • 커스텀 뷰를 구현할 때, 반드시 구현해야 하는 연산 프로퍼티로 뷰의 콘텐츠를 정의함
  • SwiftUI 빌트인 뷰들의 조합과 커스텀 뷰의 조합으로 이뤄진 단일 뷰를 반환

 

정리하자면, App은 빌드될 수 있는 단위로 프로젝트 자체에서 다루는 앱 그 자체를 이루는 프로토콜이다.

Scene은 App의 body 프로퍼티에 들어갈 수 있는, View보다는 좀 큰 개념의 프로토콜이다.

정확히 말하자면 Scene은 View hierarchy의 가장 최상위 루트 뷰를 담고 있다.

View는 사용자에게 보이는 UI를 나타내는 프로토콜이다. View는 또다른 View를 포함할 수 있다. 

 

App의 body와 Scene의 body 연산 프로퍼티 모두 1개 이상의 Scene 객체를 담을 수 있다.

    var body: some Scene {
        WindowGroup {
            MailViewer()
        }
        Settings {
            SettingsView()
        }
    }

하지만 View의 body 연산 프로퍼티는 오직 1개의 싱글 뷰만 담는다.

    var body: some View {
        HStack {
            landmark.image
                .resizable()
                .frame(width: 50, height: 50)
            Text(landmark.name)
            Spacer()
            
            if landmark.isFavorite {
                Image(systemName: "star.fill")
                    .foregroundColor(.yellow)
            }
        }
    }

그래서 한 뷰에 여러 커스텀 뷰, 빌트인 뷰들을 담기 위해 VStack, HStack, List 등으로 뷰들을 묶어서 표현하는 것이다.

위의 예시도 HStack 하나로 통째로 묶여서 반환된다. 

웹 개발로 치자면 이 스택들은 마치 div 같은 거랄까.. 

 

 

WindowGroup까지 한 번 살펴보자. 내친김에..

WindowGroup은 동일하게 구조화된 windows(창)들의 그룹을 나타내는 Scene이다.

struct WindowGroup<Content> where Content : View

WindowGroup은 앱에 보일 view hierarchy의 컨테이너로서 쓸 수 있다. 그룹 콘텐츠로 선언한 view hierarchy는 그룹으로부터 만들어진 앱이 생성하는 각 창에 템플릿을 제공한다. (쓰면서도 뭔말인지? 헷갈린다)

@main
struct Mail: App {
    var body: some Scene {
        WindowGroup {
            MailViewer() // Declare a view hierarchy here.
        }
    }
}

SwiftUI는 특정 플랫폼에 특화된 행위를 보인다. 예를 들면, macOS나 iPadOS 같은 경우 사용자들은 동시에 창 한 개 이상을 열 수가 있다. 그룹에서 만들어진 모든 윈도우들은 각자 독립 상태를 갖고 있는데 이것은 어떻게 이루어지냐면.. 시스템은 그룹에서 만들어진 새로운 창마다 State나 StateObject를 담을 새 저장소를 할당하는 방식으로 이뤄진다. 그래서 한 창에서 상태를 변경하도 다른 창에는 영향을 주지 않는다.

보통 WindowGroup을 앱의 메인 인터페이스로 사용하는데, 이는 document-based는 아니다. document-based 앱을 만들려면 DocumentGroup을 사용하면 된다.

 

 

 

References

 

 

728x90
반응형
Comments