[Clean Architecture, SwiftUI] SwiftUI를 위한 클린 아키텍처

2024. 9. 7. 07:32🍏/Architecture

SwiftUI를 위한 클린 아키텍처에 대한 고찰

팀 프로젝트를 준비하며, SwiftUI에서의 클린 아키텍처에 대해 고민하게 되었습니다. SwiftUI 관련 아키텍처를 검색하던 중 가장 먼저 눈에 띈 아티클이 바로 "SwiftUI Clean Architecture"였습니다. 다행히도 이 아티클은 한국어 번역본도 제공하고 있어, SwiftUI의 클린 아키텍처에 대해 조금 더 깊이 이해할 수 있는 좋은 기회가 될 것 같아 천천히 읽어보았습니다. 이번 글에서는 아티클의 주요 내용을 요약하고, 제 개인적인 생각도 함께 나눠보고자 합니다.
아래 링크는 해당 아티클의 한국어 번역본 링크입니다.

 

SwiftUI를 위한 클린 아키텍처

들어가기에 앞서

gon125.github.io


UIKit과 SwiftUI, 그리고 아키텍처 패턴의 변화

이 아티클은 기존 UIKit에 대해 먼저 얘기하며 시작하여, UIKit 개발에서 사용되어 온 다양한 아키텍처 패턴들에 대해 언급합니다. MVC, MVP, MVVM, VIPER, RIBs, VIP 등 여러 아키텍처를 언급하고 있습니다. 하지만 SwiftUI의 등장으로 이러한 전통적인 아키텍처 패턴들이 점차 그 필요성을 잃고, 새로운 패러다임으로 전환될 것이라고 예견하고 있습니다.
 
기존 UIKit은 명령형으로 현대적인 언어와는 조금 거리가 먼 것을 기능 위주로 설명하여 예시하고 있으며, 반면 SwiftUI의 선언적, 상태 중심의 프레임워크가 더 편리하고, 이미 UIKit의 기능들은 SwiftUI가 어떤식으로 대체할 수 있다는 것을 설명합니다. 또한 SwiftUI의 구조상 UIKit보다 더 성능상 우위를 점하게 될 것이라는 것을 주장하고 있습니다. *(구조적으로 View는 struct타입이고 스택 영역을 차지하는 struct 특성상 UIKit의 class보다 생성속도가 빠른것을 단편적 예시로 들고 있습니다.)


SwiftUI와 MVVM

SwiftUI는 MVVM(Model-View-ViewModel) 아키텍처가 내재되어 있다고 아티클은 설명합니다. 가장 기본적인 예로, View의 상태를 관리하기 위한 로컬 @State 변수가 있습니다. 이는 MVVM 패턴에서 ViewModel이 하는 역할과 유사한 기능을 수행할 수 있습니다. SwiftUI의 View는 이러한 상태를 기반으로 UI를 업데이트하며, 외부의 State에 의존적이지 않고 자체적으로 Binding 메커니즘을 통해 UI와 데이터를 일치시킵니다.

조금 더 복잡한 예에서는, View가 외부의 ObservableObject를 참조하고, 이를 통해 MVVM 패턴을 따르도록 구현할 수 있습니다. 아티클은 이러한 SwiftUI의 상태 관리 방식이 기존의 MVVM 패턴과 매우 유사하다고 결론을 내립니다.


이 글에서는 코드적 예시 및 MVVM이 무엇인가 에 대해서 언급하지 않겠습니다.
대신 어떻게 MVVM 모듈이 적용되는지에 대해서는 하단의 사진으로 대체합니다.


내부적으로 SwiftUI는 ELM기반으로 되어있다

“MCE 2017: Yasuhiro Inami, Elm Architecture in Swift” 28:26 부분 영상에서 SwiftUI의 프로토타입을 시연하였다고 합니다. 
SwiftUI는 ELM과 근본적인 개념을 공유하는 것입니다.

  • Model - 앱의 상태
  • View - 상태를 HTML로 변환하는 방법
  • Update - 메세지들에 따라 상태를 업데이트 하는 방법

* Updates를 어떻게 구현할 것인지만 생각해보면 된다.
데이터의 흐름이 이미 쉽게 추적 가능하기 때문에, 별도의 프레임워크나 라이브러리 없이 Vanilla SwiftUI를 통해 구현이 가능하다.


Coordinator is SwiftUI

SwiftUI는 UIKit의 VIPER, RIBs, MVVM-R 아키텍처에서 필수적으로 사용되는 Coordinator(aka Router) 패턴이 필요하지 않습니다. UIKit에서는 ViewController 간의 직접적인 라우팅이 종종 긴밀한 결합(tight coupling)을 유발하여 복잡성을 초래하지만, SwiftUI는 구조적으로 이를 허용하지 않습니다. SwiftUI의 View는 렌더링 엔진(State)을 필요로 하며, 직접적으로 다른 View를 관리하거나 라우팅할 수 없습니다. 따라서 SwiftUI에서는 프로그램화된 네비게이션이 Binding을 통해 상태(State)에 의해 제어되며, 화면에 표시되는 구조를 변경하는 것은 NavigationView, TabView, .sheet()와 같은 View들을 활용하여 이루어집니다. 이러한 방식으로 SwiftUI는 선언적 프로그래밍의 이점을 최대한 활용하여 복잡한 라우팅을 간소화합니다.
아키텍처를 구현해내고자 SwiftUI의 이점을 버리고 아키텍처를 위한 아키텍처를 구상하는 것을 그만두자라고 아티클의 저자는 이야기 하고있습니다. 
 


Clean Architecture

저도 한번 다뤄본적이 있는, 엉클 밥의 클린아키텍처 (https://chanhhh.tistory.com/258)를 참조하네요. 이 클린 아키텍처를 토대로 SwiftUI의 요구사항을 적용시킨다면 아래 그림과 같을거라고 합니다.

이 패턴을 사용한 데모 프로젝트 https://github.com/nalexn/clean-architecture-swiftui 링크도 주시네요.
그리고 해당하는 아키텍처 View, Interactor, AppState, Repository에 관해서 자세하게 설명을 해줍니다.


느낀점

SwiftUI에서 클린 아키텍처를 구성하려면 어떤 기준을 가지고 접근해야 하는지 다시 한 번 생각해 보는 시간을 가졌습니다.
SwiftUI 아키텍처를 사용하면 간결하고 선언적인 코드 스타일 덕분에 가독성, 유지보수성, 테스트 용이성 측면에서 큰 장점이 있다는 점을 알게 되었습니다. 😊

  SwiftUI의 선언형 프로그래밍 스타일의 장점에 대해 생각해 보면, UI가 어떤 상태인지 선언하면 SwiftUI가 자동으로 그 상태에 맞게 UI를 업데이트해 준다는 점이 가장 큰 특징으로 보입니다. UIKit에서는 ViewController에서 직접 UI 요소들을 명령형으로 제어해야 했지만,  물론 MVVM을 도입한 UIKit에서도 같은 기능을 하지만, SwiftUI에서는 더 간략하게 데이터가 바뀌면 UI가 자동으로 업데이트되므로 코드가 훨씬 간결해진다는 것. 이러한 접근 방식은 코드의 가독성을 높이고 유지보수를 용이하게 만듭니다. 즉, 코드를 작성할 때 "어떻게" 구현할지보다는 "무엇"을 그릴지에 더 집중할 수 있게 되는 것이 큰 장점인 것 같습니다.

상태관리와 데이터 바인딩이 UIKit보다 훨씬더 잘 맞는 프레임워크라는 것을 다시금 깨닫게 됐으며, 이래저래 SwiftUI의 장점을 많이 알아보는 시간이 된것 같습니다. 긴 글 읽어주셔서 감사합니다. 😉

 

참고 문헌