SwiftUI / Deep Dive

Minsang Kang·2023년 8월 1일
2

SwiftUI

목록 보기
3/12
post-custom-banner

Apple Developer 문서에 표현된 SwiftUI 탐방
https://developer.apple.com/documentation/swiftui

해당 글은 wanted 프리온보딩 iOS 챌린지 8월 을 통해 진행된 yagom 님의 강의를 계기로 작성하였습니다!
좋은 내용을 알려주신 wantedyagom님께 감사의 말씀을 드립니다!!🙌

UPDATE : 2023-08-10 00:16

SwiftUI

SwiftUI 는 Framework 형태로 만들어졌습니다.
모든 플랫폼에서 앱의 사용자 인터페이스 및 동작선언한다고 표현합니다.

OverView

SwiftUI는 UI로 표시되는 사용자 인터페이스를 표시하고, 사용자의 인터렉션을 받아올 수 있는 기능들을 모두 제공하며, 하나의 Framework로 묶여서 제공된다 라고 볼 수 있겠습니다!

SwiftUI로 앱을 만들기 위해서는 App 프로토콜로 정의가 필요하며 각 UI 요소들은 View 프로토콜을 준수해야 한다고 볼 수 있겠습니다.
그리고 중요한 부분은 각 View의 modifier를 사용하여 커스터마이징을 할 수 있다는 부분이였습니다! 일종의 함수형 프로그래밍처럼 여러 modifier를 거치는 형태로 제공되네요!
그리고 여러 View들을 compose 하여 UI를 구성한다 라는 표현도 중요합니다.
다행이도 기존의 UIKit 프레임워크 및 AppKit, WatchKit과도 같이 사용할 수 있게 만들어졌다고 볼 수 있겠습니다.
그리고 accessibility를 지원하기에 국가 또는 문화 지역에 따른 현지화할 수 있습니다.

이렇게 SwiftUI를 정의한 내용을 살펴봤는데, UI를 제공하는 Framework 형태이며 추가적으로 App 프로토콜과 View 프로토콜을 알아봐야겠죠?
그리고 각 View들의 modifier 들이 중요하다고 보여집니다!


그러면 이제 하나하나 탐방을 해보겠습니다.

App protocol

https://developer.apple.com/documentation/swiftui/app

앱의 구조와 동작을 나타내는 protocol 입니다.

위 코드 형태처럼 App 프로토콜을 준수하는 형태로 앱 프로젝트를 생성할 수 있습니다. UIKit의 AppDelegate와 같은 역할이라고 볼 수 있겠네요!
그리고 body라는 컴퓨티드 프로퍼티로 앱의 content를 구현할 수 있습니다.

@main을 선언하여 앱의 entry point(진입점)를 설정할 수 있습니다. 이 진입점은 앱에서 단 하나만 존재해야 합니다!
그리고 @main 이 선언된 App 프로토콜은 자동으로 main() 메소드를 실행하여 default implementation을 제공합니다.

여기서 default implementation이 무엇일까요?

Default Implementation

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols/#Providing-Default-Implementations

제가 이해한 Default Implementation은 쉽게 말해 특정 Protocolextension으로 정의된 메소드를 Protocol 채택으로 사용할 수 있는것을 의미합니다.
class에서 상속을 통해 부모의 메소드를 사용할 수 있는 것과 비슷한 맥락이라고도 볼 수 있죠!

즉, 정리하면 App 프로토콜을 채택함으로써 main() 메소드가 실행되며 이때 main() 동작은 Default Implementation을 통해 동작된다! 라고 이해할 수 있을 것 같습니다!

그러면 위 예시코드처럼 App 프로토콜을 extension하여 main() 메소드를 새롭게 구현할수도 있겠죠? (아마 야곰님께서 말씀하신 부분이 이 부분이지 않을까 생각합니다!)

그러면 main() 메소드도 한번 살펴볼까요?

main()

https://developer.apple.com/documentation/swiftui/app/main()

앱을 초기화하고 실행하는 메소드입니다

위에서 살펴본대로 @main 이 선언된 App 프로토콜로 자동으로 앱을 실행하는 main() 메소드가 실행됩니다.
여기서 중요한점은 SwiftUI는 플랫폼에 적합한 방식의 default implementation을 제공한다고 합니다!

iOS, iPadOS, macOS, 그리고 새롭게 나올 visionOS 등 각 플랫폼별 앱 실행을 위한 동작이 App 프로토콜을 채택함으로써 알아서 실행된다고 볼 수 있겠네요!

App 프로토콜을 알아보다가 Default Implementation, 그리고 main() 메소드로 잠깐 빠졌죠!
다시 App 프로토콜 부분을 이어서 살펴보겠습니다!

App protocol (이어서)

https://developer.apple.com/documentation/swiftui/app

위에서 body 라는 컴퓨티드 프로퍼티로 앱의 content를 구현할 수 있다고 봤는데요, 이 body는 Scene 프로토콜을 준수하여 구성됩니다.
scene은 view 계층구조의 root view와 시스템에서 관리하는 life cycle을 지니고 있다고 합니다
또한 앱이 공통적으로 다루는 documents 나 setting와 같은 contrete scene 타입들도 제공한다고 합니다!
Scene 프로토콜을 채택하여 custom scene도 만들 수 있겠네요!

여기서 Scene 프로토콜도 좀 더 살펴봐야겠죠? 그리고 WindowGroup으로 여러 Secne들을 제공할 수 있는 형태로도 보이네요!

Scene protocol

https://developer.apple.com/documentation/swiftui/scene

시스템에서 관리하는 life cycle이 존재하는 앱의 UI 단위라고 볼 수 있겠습니다!

App 프로토콜의 body 내에서 Scene 프로토콜을 준수하는 하나 이상의 scene 들을 결합하여 앱을 만든다고 합니다! 이때 통상 내장된 WindowGroup을 사용하겠지만, Scene 프로토콜을 채택하여 새롭게 custom scene을 반환할수도 있습니다.

저희는 custom scene을 만들 단계가 아니므로 여기까지만 확인해보고 다음으로 WindowGroup 프로토콜을 살펴보겠습니다!

WindowGroup protocol

https://developer.apple.com/documentation/swiftui/windowgroup

동일하게 구성된 window들의 group을 나타내는 scene 입니다.

앱의 view hierarchycontainer로써 WindowGroup을 사용합니다.
WindowGroup 내에 선언된 view hierarchy는 생성되는 window 별 탬플릿이 됩니다.

말이 어렵죠? 여기서 window는 쉽게말해 이라고 이해할 수 있어요!
아이폰의 경우는 앱을 하나의 창에서 실행하는 식이지만, 아이패드나 맥에서는 같은 앱이여도 여러 창을 띄우거나, 들을 띄울 수 있잖아요?
그때 각 window별로 화면이 표시되는 기본세팅이 바로 WindowGroup 내 선언된 view hierarchy, 즉 View 라고 볼 수 있겠습니다!

view hierarchy 라고 표현한것은 View를 예시코드처럼 MailViewer()처럼 하나의 View로 표현할수도 있지만

VStack {
  Text("Hello")
  	.font(.title)
  Text("World")
  	.font(.subtitle)
}

이런식으로 계층구조가 있는 View도 WindowGroup 내 명시할 수 있다는 의미인 것 같아요!

아까 말한대로 iPadOS나 macOS에서는 동시에 둘 이상의 창을 열 수 있기에 WindowGroup 형태로 제공한다고 볼 수 있겠습니다!
그리고 SwiftUI는 이런 플랫폼별 동작을 자동으로 처리해주죠!

추가로, iPadOS에서 여러 창을 동시에 표시하려면 UIApplicationSupprotsMultipleScenes = true여야 한다고 합니다.

window 들은 독립적인 상태 및 스토리지를 지닌다고 합니다!
@state나 @stateObject 등과 같은 스토리지들을 개별적으로 할당하여 유지된다고 합니다!
그리고 Document 기반 앱인 경우 DocumentGroup을 사용하여 window를 정의하라고 합니다.

정리해보면, SwiftUI는 Framework로 제공되는데 App 프로토콜을 통해 플랫폼별 앱 실행동작을 자동으로 설정해주고, UI를 만들어 WindowGroup으로 묶으면 플랫폼별로 자동으로 여러창을 지원하거나 창별 독립적인 기능들을 제공한다고 볼 수 있겠습니다!

SwiftUI을 알면 알수록 애플의 여러 플랫폼을 모두를 아우를 수 있으며 매우 쉽고 간단하게 앱을 제작할 수 있는 FrameWork 라고 보여집니다!!

이렇게 WindowGroup을 통해 window 관리와 window별 독립적으로 제공이 된다는 것을 알 수 있었습니다!
그러면 Scene 프로토콜을 이어서 살펴보겠습니다!

Scene protocol (이어서)

https://developer.apple.com/documentation/swiftui/scene

위에서 살펴본대로 App 프로토콜의 body 컴퓨티드 프로퍼티 내에서 Scene 프로토콜을 준수하여 만든 scene들로 앱을 구성합니다.
이때 scene은 UI로 표시되는 view hierarchy컨테이너 역할을 합니다!
그리고 SwiftUI는 플랫폼에 따라, 앱의 현재 상태에 따라, 언제 그리고 어떻게 UI를 표시할것인지 결정한다고 합니다!

쉽게 말해 WindowGroup 내 명시된 ViewUI를 표시하고, 해당 UI가 플랫폼별로 아이폰의 경우는 전체 화면을, 그 외의 경우는 여러 창을 생성하거나 제거할 수 있다고 볼 수 있겠습니다!
이때 여러창들은 개별적으로 scene으로 상태와 스토리지를 독립적으로 지니도 있다는 것이죠!

이 모든것을 Scene 프로토콜을 채택하면 SwiftUI가 알아서 플랫폼별로 지정된 UI를 표시해주는 역할을 하고 있는 것이죠!

@Emvironment 프로퍼티래퍼를 사용하여 scenePhase 값을 통해 scene의 활성상태, 또는 다른 상태인지를 확인할 수 있습니다!

또한 Scene 프로토콜은 modifier를 제공합니다.
예를들어 .onChange(of: poerform:) modifier를 통해 scenePhase 값의 변화를 수신할 수 있죠!
해당 예시코드는 scenePhase 값이 background가 되었을 때 캐시를 비우고 있습니다!

여기까지가 Scene 프로토콜의 내용이였습니다!
정리하면 Scene은 life cycle이 존재하는 단위이자 view heirarchy의 컨테이너 역할이자 플랫폼별로 여러 창을 생성할 수 있는 경우 scene별로 독립적으로 상태와 스토리지를 지니고 있으며, @Environment(.scenePhase)를 통해 활성상태 여부를 확인할 수 있습니다!

일종의 UIKit의 SceneDelegate 역할도 같이하고있는 것 같네요!

이제 Secne 프로토콜을 알아봤으니, 진짜 마지막으로 App 프로토콜의 나머지 부분들도 확인해보겠습니다!

App protocol (이어서)

https://developer.apple.com/documentation/swiftui/app

App 프로토콜 내에서 @StateObject 와 같은 프로퍼티래퍼를 통해 앱 내 모든 scene에서 공유할 수 있는 데이터 모델을 설정할 수 있습니다!
데이터 모델의 공유는 environmentObject 방식과 observedObject 방식을 통해 전달 및 접근할 수 있습니다.

여기서
하위 View에서 상위 View의 데이터 모델을 접근하는 방법인 environmentObject 방식과
하위 View 내 선언된 변수로 접근하는 방법인 observedObject 방식이 있습니다.

두 방법 모두 ObservableObject 프로토콜을 채택한 데이터 모델의 변화를 감지하여 접근할 수 있습니다!

더 자세한 내용은 EnvironmentObject 내용과 ObservedObject 내용을 추가로 보면 되겠습니다!


정리

이렇게 SwiftUI를 정의한 애플공식문서를 탐방해봤는데.. 역시 애플이 제일 잘하는 여러 플랫폼을 서로 넘나드는 시스템의 장점이 SwiftUI에도 녹아져있다고 느꼈습니다.

하나의 SwiftUI 프레임워크를 사용하여 특정 프로토콜을 채택하는 것 만으로도 Default Implementation 을 통해 각 플랫폼별로 특화되어 제공된다는 점이 정말... 애플답다 라는 느낌이 들었습니다ㅎㅎ

그리고 저희는 이제 View라는 프로토콜 형식으로 반환되는 것들을 compose 하여 UI를 구현하면 되는 것이죠!

단순히 UI 구현하는 방법을 익히는 것을 넘어서 애플이 어떤것들을 생각하여 SwiftUI를 개발했는지를 알 수 있었다고 생각합니다!

다음글

그리고 View 프로토콜을 통해 UI를 구현하는 내용은 SwiftUI / View 글을 이어서 보시면 되겠습니다!


참고 블로그

https://hryang.tistory.com/18

profile
 iOS Developer
post-custom-banner

0개의 댓글