주말동안 심심해서 SwiftUI Beta를 설치해서 사용해 봤다. SwiftUI를 통해 간단한 UI를 구성해보았고, ViewController가 없어진 View가 어떤식으로 Logic을 구성하고 어떻게 Data와 Model과 관계를 맺어 동작하는지 살펴보았다. 

Declarative Syntax (선언적 표현)

  SwiftUI는 Declarative syntax를 사용하여 GUI를 구성한다. 예전에 Web나 React Native같은 Declarative 방식을 사용하는 프레임워크로 앱을 개발해 본 경험이 있는데, 개인적으로 GUI를 이러한 선언적 방식을 사용하여 구현하는게 내 취향에는 맞지 않았다. (여러 tool을 사용해봤지만 만족스럽지 못했던 기억이...) 그런데 SwiftUI도 Declarative 기반이라고 하여 첫인상은 썩 좋지 않았다. 

  경험적으로 봤을 때 Declarative 표현방식으로 구현하는 GUI는 보는 것보다 읽는 것에 비중이 크다 보니 iOS Storyboard같이 드래그 앤 드롭 방식으로 UI를 개발하는 것보다 인지적 노력이 더 필요했다. 이는 직관적이지 않음으로 내가 오래전에 구현했거나 다른 사람이 구현한 GUI를 수정하려고 할때 많은 애를 먹곤 했었다. 하지만, SwiftUI는 이러한 문제를 아래와 같이 꽤 괜찮은 GUI Tool을 통해 해결했다.

직관적인 GUI Tool

[그림 1. Inspector로 속성 바꾸기]

  Code Editor 영역 혹은 Canvas 영역에서 Cmd + Click -> Inspector를 선택하면 View가 가지고 있는 속성들을 손쉽게 바꿀 수 있다. 

 

[그림 2. Drag and Drop으로 View 추가하기]

  Drag and Drop으로 View를 직관적이고 쉽게 추가 하고 수정할 수 있다. 이 기능 역시 Editor와 Canvase에서 모두 사용할 수 있다. Declarative syntax 방식의 장점과 Drag and Drop 방식의 장점들이 잘 어울러졌다.

 

[그림 3. Preview]

  코드를 수정하면 거의 실시간으로 Preview 영역만 빠르게 컴파일하여 미리보기가 가능하다. 이는 내가 작성한 GUI의 유사한 화면을 보여주는 것이 아닌 live app으로 실제 빌드된 화면과 동일함을 보장한다.

  [그림 3] 25~31 Line에서 Preview를 설정하는 부분을 볼 수 있는데, 해당 부분(28Line)에서 View가 의존하는 Class들을 Mock으로 대체하여 전달 할 수 있다. 따라서 매번 앱을 Full build하여 실제 데이터와 유저 시나리오 시퀀스대로 따라 가면서 View를 디버깅 할 필요가 없게 되었다. 이로 인해 View의 개발 및 유지보수 시간을 굉장히 절약 할 수 있을 것으로 보인다.

Two-Way Data Binding

[그림 4. State and Data Flow]

  드디어 iOS에서도 Data Binding을 지원한다. SwiftUI에서 제공하는 Property를 사용하여 User의 액션이 데이터로 전달되고 변경된 데이터는 뷰를 갱신한다. 바인딩된 Property의 Memory capture(strong, weak, unowned)도 신경쓸 필요 없게됐다.

 

[그림 5. 기존의 ViewController]

  기존의 방식에서는 유저의 액션으로 데이터를 변경하고 View를 갱신하기 위해서 UIViewController가 필요했다. UIViewController는 여러 View와 Model들을 가지고 있으며, 그 둘의 데이터 상태를 동기화 해주는 코드가 필요했다. 그리고 이런 일련의 동작들을 좀 더 깔끔하게 하기위해 우리는 꽤 많은 수고를 들여 기반코드를 작성했어야 했다.

 

[그림 6. SwiftUI에서의 View]

  SwiftUI에서는 UIViewController가 사라졌다. View는 Struct가 되었고, 그 대신 SwiftUI는 상태를 유지하고 추척할 수 있는 @Binding,  @State, @ObservableObject, @Environment등을 제공한다. 이제 iOS는 MVC가 아닌 MVVM을 사용할 수 있게 되었다.

 

  아래는 아이디와 패스워드를 입력하면 로그인 버튼이 활성화되는 테스트 코드이다. 이제 View와 Data간의 Binding하는 글루코드가 한결 깔끔해질 수 있게 되었다.

 

 

[그림 7. DataBinding]

 

  ObvervableObject protocol을 사용하여 LoginViewModel를 만든 모습니다. @Published를 사용하여 필드를 만들면 해당 값이 변경될때마다 바인딩 된 뷰에 자동으로 값을 갱신 할 수 있다. 그리고 View에서 변경된 값이 ViewModel에도 자동으로 갱신된다.

 

  View에서는 @EnvironmentObject를 사용하여 ViewModel를 선언하고 environmentObject를 통해 외부(22 Line)에서 데이터를 받을 수 있다. 이렇게 전달 받은 ViewModel은 위 코드에서 보이는것과 같이 손쉽게 View와 바인딩되어 사용될 수 있다.

결론

  SwiftUI를 하루 정도 사용해 보았는데, Declarative과 Drag and Drop 방식의 UI구성을 적절히 잘 지원하는 것 같다. 그리고 Data Binding을 지원하게 되어 이제 MVC가 아닌 MVVM을 좀더 쉽게 사용할 수 있게 되었다.

  Beta라 그런지 아직 버그가 많은것 같고, 잘못 사용한 문법 때문에 런타임에 crash가 나는 경우가 종종 있는데 로그로 충분히 crash 정보가 표현되지 못하고 있어서 좀 애를 먹긴 했다. 그리고 Apple Developer 사이트가 튜토리얼을 기가막히게 잘 작성해 놨다. 

 

https://developer.apple.com/tutorials/swiftui/creating-and-combining-views

 

Apple Developer Documentation

 

developer.apple.com

 

'iOS' 카테고리의 다른 글

Swift에서의 DI(Dependency Injection)  (0) 2020.08.11
Swift에서의 AOP  (0) 2020.08.03
Realm은 thread safe하지 않다.  (0) 2019.09.01

+ Recent posts