iOS

[iOS] SwiftUI + MVVM에 대한 고찰

Hatchling.dev 2024. 2. 5. 22:48

(편의상 편한 말투로 작성하는 점 이해 부탁드립니다.😅)

(부정확한 정보가 있을 수 있습니다. 지적 환영🤗)

 

오늘 글은 순전히 내 개인적인 궁금증에 의한 글이며 혼자 생각해봤던 내용을 정리하는 용도이지 다른 사람들에게 정답을 제시하거나 하는 글은 아님을 밝힙니다.

 

요즘 SwiftUI에 대해 공부하고 있는데 내가 개발을 시작하기 전 가장 많은 시간 고민하는 부분이 방법론이다. 개발할 때 문제들을 해결할 수 있는 방법론들을 찾아보다가 과거에 MVVM으로 개발하면서 의존성에 대한 부분을 신경쓰지 않고 개발하다가 아작난 경험이 있어 이 부분을 보완해보고 싶어 MVVM + Clean Architecture를 적용해보던 중 급 의구심이 들었다. SwiftUI는 View에서 Property Wrapper를 통해 상태관리를 하고 있는데 이걸 굳이 ViewModel로 관리해야하나...?에 대한 생각을 하게 되었다.

 

이부분에 대해 검색해보니 역시나 굉장한 양의 아티클들이 쏟아졌다.. (다들 고민 많이 하고 있구나..)

아직 어떤게 정답이다! 라는게 없을 정도로 다양한 의견들을 보며 들었던 생각?을 정리해보고 나랑 같은 고민을 하고 있는 사람들에게 이 글이 도움이 되길 바란다.

 

MVC? MVVM?

먼저 개발자들이 왜 Apple이 만들어놓은 MVC가 아닌 MVVM에 열광하고 표준처럼 쓰려고 하는지부터 간단하게 알아보자

(https://velog.io/@eddy_song/ios-mvc 여기서 MVC가 왜 애플이 만든건지, MVC가 뭔지, 왜 MVC가 아닌 MVVM을 쓰는지에 대해 자세히 설명하고 있으니 읽어봐도 좋을 것 같다.)

MVC가 아닌 MVVM을 많이 사용하는 가장 큰 이유는 역시 View와 Controller의 결합인 것 같다. UIKit에서 VC는 해당 화면에 관련된 역할 중 대부분을 담당하고 있고 View와 Controller의 결합이 너무 강하다보니(이름부터 ViewController..) 이를 나누기가 굉장히 어렵다는 문제를 해결하기 위해 MVVM이 등장했다. 가장 큰 차이점이라고 한다면 View의 상태관리를 Data Binding을 통해 ViewModel에서 관리해 View를 업데이트한다는 차이점이 있다. 이로인해 View와 ViewModel의 의존성을 최소화해 재사용성을 높이고 테스팅도 편하다는 장점이 있다. 그렇다면 왜 사람들은 SwiftUI에서 MVVM을 지양하라고 할까?

 

위에서 말했듯이 MVVM에서는 ViewModel에서 Data Binding을 통해 상태관리를 한다고 했는데 SwiftUI는 다양한 property wrapper를 활용해 View의 상태관리를 도와주고 있음(@State, @Binding, @Published 등등)

여기서 이번 글을 작성하게 된 궁금증이 생겼음. SwiftUI + MVVM일 때 상태관리는 어디서 해야할까?? View? ViewModel?

찾아보니 Published를 활용해서 ViewModel에서 해라. ViewModel 필요없다. 비즈니스로직만 ViewModel에서 해라. 등등 다양한 의견들이 있었는데 Published를 활용하면 MVVM으로 구현이 가능하지만 Apple이 친절하게 제공하는 걸 걷어찬 느낌....? 그렇다고 View에서 비즈니스 로직까지 구현하기도 부적합해 보이고 비즈니스 로직만 ViewModel에서 하는건 내가 아는 ViewModel이 아닌 무언가...처럼 느껴진달까.. 이게 맞는건가..? 나도 아직 정답은 모르겠다. 실제로 모든 방법론을 활용해본 것도 아니고 개발자마다 무엇에 중점을 두느냐에 따라 의견이 갈릴 수 있는 부분이라고 생각한다.

그래서 찾아보던 중 단방향 아키텍처에 대한 아티클도 많아서 보다가 TCA에 대해 알게 되었다.

 

TCA가 뭔데?

TCA는 The Composable Architecture의 약자로 SwiftUI에 대응하기 위해 등장한 오픈소스 라이브러리다. (react에서 사용하기 위해 페이스북이 만든 Flux 같이 단방향 아키텍쳐다)

TCA 작동 방식

TCA는 위 이미지와 같은 방식으로 동작하는데 View에서 Event가 발생하면 Action을 보내 Reducer로 보내진다. Reducer는 상태를 변화시킬 수 있는 로직을 가지고 있고 들어온 Action에 따라 상태를 변화시키는데 여기서 바로 State를 변화시킬 때도 있고 Environment를 거칠 때도 있죠? 이 둘의 차이점은 바로 통신의 유무입니다. 통신이 필요없다면 바로 상태를 변화시키고 통신이 필요하다면 별도의 과정을 거치게 됩니다. 여기서 Environment는 통신에 필요한 의존성을 가지고 있고 통신 결과(Effect)에 따라 Action에 이펙트가 보내집니다.

여기서 크게 두가지의 이펙트가 발생할 수 있는데 먼저 좋은 이펙트. 바로 통신 성공 결과입니다. 이 이펙트를 Action에 보내면 Reducer를 통해 State가 변화하게 되고 Side Effect(에러나 잘못된 데이터 수신 등?)가 발생하면 Action을 통해 사용자에게 결과를 알려줄 수 있습니다.

결론

그래서 TCA가 좋은거야? 나쁜거야? 써? 말아?

저도 아직 모르겠슴돠.... 분명 SwiftUI와 잘 어울리는 것 같고, Store 단위로 재사용과 테스팅에도 유리하다고 하니 좋아보이긴 하지만 라이브러리이기 때문에 프로젝트 자체가 TCA에 의존한다는 점도 단점으로 꼽히는 것 같습니다.

그래서 저만의 결론을 낸다면 써보기전엔 모른다. 입니다.

너무 당연한 소리지만 이론만 보고 좋고 나쁘고를 알 수 없다고 생각하기 때문에 현재 진행하는 사이드프로젝트에 TCA를 적용해봐야 좋은지 안좋은지 알 수 있을 거 같네요.

다음에 기회가 된다면 후기?같은 TCA에 대한 글을 다시 작성해보도록 하겠슴다

 

다시 말하지만 SwiftUI에서 MVVM이 무조건 나쁘다라고 하는건 아니고 저도 아직 잘 모르니까 고민하고 있다고 알아주십쇼.. 혹시 잘못된 부분이 있거나 조언을 해주고 싶다면 환영합니다.

 

출처:

https://medium.com/@mooyoung2309/swiftui-tca-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-1-1d1c93a79dda

 

SwiftUI + TCA 시작하기 #1

단방향 Flow는 많이 쓰이는 것일까?

medium.com

https://developer.apple.com/documentation/swiftui/model-data

 

Model data | Apple Developer Documentation

Manage the data that your app uses to drive its interface.

developer.apple.com

https://medium.com/@youable.framios/whats-your-eta-what-s-your-tca-mmm-hmm-swiftui-tca%EB%A5%BC-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EC%A0%84%EC%97%90-%EB%B3%B4%EB%A9%B4-%EC%A2%8B%EC%9D%80-%EA%B8%80-6cfeb92dbc29

 

What’s your ETA What’s your TCA ~Mmm-hmm (SwiftUI TCA를 시작하기 전에 보면 좋은 글)

뉴진스 ETA 뮤비를 아이폰 14 Pro로 찍기도 했고 TCA랑 은근 라임도 맞는단 말이죠. 하지만 글은 뉴진스 ETA랑 아무 상관 없는 TCA 입니다.

medium.com

https://medium.com/@Jager-yoo/swiftui-the-composable-architecture-tca-%EC%9E%85%EB%AC%B8-95b69b8c6c16

 

[SwiftUI] The Composable Architecture(TCA) 입문

이 글을 작성하던 2022년 7월에는 TCA 가 0.38.X 버전대였습니다.

medium.com