Skip to content

Instantly share code, notes, and snippets.

@unnnyong
Last active April 18, 2024 13:02
Show Gist options
  • Star 41 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save unnnyong/439555659aa04bbbf78b2fcae9de7661 to your computer and use it in GitHub Desktop.
Save unnnyong/439555659aa04bbbf78b2fcae9de7661 to your computer and use it in GitHub Desktop.

일본어 블로그 아티클의 @young의 번역글 입니다. 의역이 포함되어 있습니다.


"SwiftUI에서 MVVM 사용을 멈추자"라고 생각이 들었던 이유

선언적인 UI에서, MVVM이 불필요한 이유는?

iOS 개발 현장에서, 선언적 UI가 당연하게 사용되는 시대가 되었습니다. SwiftUI를 사용해본 경험은 멋졌습니다. 최고입니다.

하지만 최근, SwiftUI에서 당연하게 "MVVM을 사용하자" 라고 되었을 때, "정말 그걸로 괜찮을까?" 라는 의문이 들기 시작했습니다.

제 생각을 깊이 파보면,

  • 질문
    • iOS를 개발할 때, 선언적 UI에서 MVVM을 사용하는 것은 정말로 괜찮은걸까?
  • 결론
    • SwiftUI를 사용한다면, MVVM을 사용하는 것을 멈추자
  • 이유
    • ViewModel의 존재는 선언적 UI 시대에는 필요 없다 고 생각하기 때문

라는 결론에 다다랐기에 생각한 것을 이 아티클에 정리합니다.

ViewModel은 필요하지 않다.

iOS 개발 현장에서, 깊게 생각하지 않고 프로젝트의 아키텍쳐로 MVVM을 선택하고 있지 않나요?

혹시라도 당신이 SwiftUI에서 MVVM 패턴이 방해된다고 생각하거나, 실제로 구현할 때 그정도로 유용하지 않다고 느꼈다면, 그것은 MVVM 디자인 패턴이 SwiftUI의 특징과 맞지 않기 때문 이 아닐까요 ?

이전에 저(글쓴이)는 아래와 같은 내용은 트위터에 게시했습니다.

모바일 어플 개발에서 MVVM에서의 ViewModel을 생각하는 것이 주류이던 시절이 있었다. SwiftUI 등의 선언적 UI를 사용하는 세계에서는 생각하는 법을 바꿀 필요가 있다. 원래 ViewModel이라는 것은 상태를 View에 Binding해서 Reactive로 반영하는 것이 목적으로 도입되었지만, 선언적 UI에 그 기능이 내포되어버렸기에 ViewModel은 불필요하다.

MVVM불필요이론 은 해외에서도 종종 논란이 된다

Apple의 개발자 포럼이나 레딧, 유튜브에서도 "iOS개발(SwiftUI)에서 MVVM을 사용하는 것을 멈추자" 와 비슷한 주제의 글들이 눈에 띄는 경우가 있습니다.

Stop using MVVM for SwiftUI https://developer.apple.com/forums/thread/699003

Is MVVM an anti-pattern in SwiftUI? https://www.reddit.com/r/swift/comments/m60pv7/is_mvvm_an_antipattern_in_swiftui/

STOP using MVVM for SwiftUI | Clean iOS Architecture https://www.youtube.com/watch?v=SOA0IT7sxvc

SwiftUI에서 MVVM을 사용하는 것은, "호버보드로 하늘을 날 수 있는데도, 일부러 바퀴를 달아서 달리는 것과 같은 것이다." 라는 비아냥거리는 글도 있습니다.

image

그러면 왜 우리는 MVVM을 선택해버리는걸까?

최근, MVVM로 개발에서 SwiftUI를 사용하는 기회가 늘었습니다.

SwiftUI를 사용한 어플리케이션에서, 아키텍처를 어떻게 할 것인가 하고 고민하고 있습니다. 모바일 어플리케이션 개발을 하다보면, 왜인지 아키텍처는 MVVM로 선택해버리고 맙니다.

저(글쓴이)는 "어째서?" 라고 의문을 가집니다.

이것은 모바일 어플리케이션 개발의 옛날부터의 전통으로, 2016년에 구글이 안드로이드 개발에서 MVVM을 제창하는 것으로 시작되고 있습니다. (어디까지나 제창한 것뿐, 발상의 시작은 마이크로소프트입니다)

원래는 안드로이드 개발 실무에서부터 MVVM의 사용이 시작되었지만, iOS 개발에까지 영향을 받게 되어서 당연한 것처럼 현재 사용이 확산되어 버렸습니다.

하지만, "구글이 권장한 아키텍처는 MVVM이다" 라는 말은 실제로 존재하지 않습니다. (글쓴이가 찾은 한에는)

현재, 구글 공식 아케틱처 가이드에서 MVVM이라는 단어는 지워져 있는 상태입니다.

하지만 MVVM의 발상은 마이크로소프트, (모바일에서는 안드로이드) 애초에 본가 Apple에서는 MVVM이라는 단어를 사용한적조차 없습니다.

구글도 "최종적으로 Jetpack Compose에서는 MVVM/ViewModel을 없애고 싶다." 라는 어투가 느껴지기 때문에, 안드로이드 개발에서도 MVVM이라는 단어가 사라져가는 분위기가 느껴지고 잇습니다. (* 글쓴이의 개인적인 생각입니다.)

MVVM이란?

애초에 iOS 개발에서 MVVM은, 아직 SwiftUI가 없던 시대에 RxSwift 등의 Reactive library를 사용해서, View와 ViewModel의 값을 바인딩 하던 시대에 사용되던 것입니다.

View   <->   ViewModel  <->  Model
      Binding
class ViewController {
    override func viewDidLoad() {
        viewModel.username
            .bind(to: label.rx.text)
            .disposed(by: disposeBag)
    }
}

SwiftUI.View에 ViewModel정도의 기능이 포함되어 있습니다.

하지만, SwiftUI의 View에는 원래부터 데이터 바인딩의 기능이 포함되어 있습니다. 바꿔말하면, "UIKit.View MVVM" 으로 했던 것이 "SwiftUI.View 하나"로 된다, 가 됩니다.

즉, SwiftUI.View라는 것은 이미 "View + ViewModel"의 기능을 갖고 있어서, 직접 Model의 값을 Reactive하게 View에 반영하는 것이 가능하다는 것 입니다.

SwiftUI.View  <->  Model
            Binding

image

선언적 UI의 등장으로, ViewModel은 존재이유를 잃고 있다.

SwiftUI에서 ViewModel의 데이터바인딩이 포함되어버린 시점에서, ViewModel은 존재이유를 잃고, 'ViewModel'이라는 단어 자체도 의미가 애매해져버린 단어가 되어버렸습니다.

MVVM을 사용하면, 불필요한 복잡성을 만들어버린다.

SwiftUI에서 MVVM을 사용해버리면 ViewModel이라는 불필요한 레이어(계층)을 끼워버리기 때문에 복잡해집니다.

View와 Model의 사이에 ViewModel이라는 중간 레이어(계층)가 끼워진 양방향 Data flow가 되어버립니다.

Apple 공식에서도 보여주는 단방향 Data flow과는 괴리가 생겨버립니다.

image https://developer.apple.com/documentation/swiftui/state-and-data-flow

선언적 UI 시대에서는 데이터플로우를 단방향으로 하는 것이 장점이 있다고 생각함니다. Single Source of Truth으로 하기 위한 상태관리를 하는 장소나 Property Wrapper를 활용해서 데이터플로우를 고민할 필요가 있습니다.

@d_date 의 트윗 ❌「SwiftUI에서MVVM를 사용하는걸 멈추자.」 ⭕️「선언적 UI와 Property Wrapper의 역할을 이해해서 데이터플로우를 어떻게할까 고민해보자」 https://twitter.com/d_date/status/1502863294654464007?s=20&t=B9mI0uTKDSgMvEUuQyVBGg

디자인 패턴을 작성하기 위해서 디자인 패턴을 작성하면 안된다.

SwiftUI.View   <->   ViewModel  <->  Model
             Binding

MVVM           on    MVVM

"SwiftUI에서 MVVM를 사용해버리는 것" 을 바꿔말하면 "SwiftUI + MVVM = MVVM on MVVM", 똑같은걸 두 번 말하는 것이 되어버린다.

"MVVM 덕분에 MVVM이 되어서 다행이다"라는 상태가 되어있습니다.

이것은 "디자인 패턴을 작성하기 위해서, 디자인 패턴을 만드는 것"이 되어서, 목적을 잃은게 아닐까요? "MVVM on MVVM"이 되지않기 위해서도 ViewModel의 레이어(계층)을 없애는 편이 단순하다고 생각합니다.

React/Vue/Flutter 개발에서 MVVM는 사용되고 있지 않다.

비슷한 선언적 UI를 사용하고 있는 React/Vue/Flutter의 분야에서도, MVVM이라는 아키텍처는 사용되고 있지 않고(선언적 UI에 포함되어 있음), SwiftUI에 있어서만 MVVM를 사용하는 것이 이상하다고 생각합니다.

(from. @young | 글쓴이의 주관적인 생각이 깊은 문단)

  • Flutter에서 MVVM를 사용하는 경우도 있지만, SwiftUI에서 사용하는 MVVM과는 다르다고 생각합니다. Provider라고 하는 아키텍쳐의 틀에서 "Provider에서 옮기고 있는 Notifier의 이름"을 ViewModel이라는 것으로 이름을 붙였다는 인식입니다. 아키텍처라는 것은 Provider이므로 제(글쓴이)의 생각으로는 MVVM라고는 생각하지 않습니다. Android개발에서의 MVVM의 연장선으로 Flutter에서도 ViewModel를 만드는 것은 개인적으로는 좋지는 않은 판단이라고 생각합니다.

"ViewModel" 이라는 단어를 사용하는 것은 모바일 세상의 분들이 대부분이므로, 다른 분야의 개발자가 이야기하는 ViewModel이라는 단어의 의미는 또 다르다고 느껴질 때도 있습니다.

iOS의 소스코드를 React 개발자에게 보여줬을 때, "이 ViewModel이라는 것은 무슨 의미가 있는건가요?"라는 질문을 받은적도 있습니다.

MVVM을 사용하지 않으면 어떻게하나요?

UI와 로직의 분리

MVVM을 사용하지 않았을 때, "ViewModel이 없어지면 UI와 로직의 분리는 어떻게하지?"라는 문제가 생깁니다.

답은 Model 또는 Flux적인 Store로 분리하는 것이 좋다고 생각합니다.

중소규모의 어플이라면 MV(Model과 View)라면 충분합니다.

단순히 View와 로직을 분리하기 위해서 ViewModel을 만드는 것은, 이름과 해야하는 일이 맞지 않기 때문에 더 이상 필요하지 않다고 생각합니다.

선언적 UI 시대에 필요한 아키텍처

선언적 UI의 등장으로, "모바일 개발이라면 MVVM이지" 라는 시대는 저물고, 혼돈의 시대에 돌입했다고 생각합니다.

현재, SwiftUI 개발에서 가장 표준적인 아키텍쳐나 Best practice라고 불려오는 것은 아직 없습니다. 모두가 기다리고 있습니다. (혹시 있다면 꼭 알려주세요 !)

선언적 UI 시대의 대규모 어플리케이션 개발에서 우리가 정말로 원했던 것은, MVI(단방향 데이터플로우)나 Flux(The composable architecture), Store/Provider 패턴 등이 아닐까 생각합니다.

SwiftUI를 사용하는 것만으로 MVVM 정도의 기능은 기본으로 가능하게 되었으므로, 이제는 한 계단 위 레이어의 문제를 해결하는 아키텍처가 필요한 시기가 되었다고 말할 수 있습니다. (from. @young | 선언적 UI, SwiftUI에 의해 발생하게 될 이슈들을 이제 개발자들이 이겨내야할 타이밍이 왔다고 이야기하네요.)

그 문제를 예로들면 아래와 같습니다.

  • "Component 설계는 어떻게할까?"
  • "Component의 상태와 로직을 View로부터 분리하는 법"
  • "각 Component들간의 상태 관리를 전달하는 법"
  • "단방향 데이터 플로우"
  • 등등

MVVM 아키텍처는 Component 간의 연결, 데이터 플로우의 문제를 해결하기 위한 것이 아닙니다.

위와 같은 문제의 해결방법을 구체적으로 이야기한다면, React라면 Flux(Redux)나 Hooks가 되고, Flutter라면 Provider패턴이나 Riverpod가 될 수 있습니다.

iOS 개발에서도 선언적 UI로부터 야기되는, MVVM의 상위 레이어의 문제를 해결하는 아키텍처나 라이브러리가 필요하다고 생각됩니다.

애초에 아키텍처의 문제가 아닌, "서버로부터 비동기적으로 데이터를 fetch해서, View에 표시하고 싶다"라는 비동기 또는 상태관리의 해결방법은 GraphQL 클라이언트의 data fetch cache libarary를 사용하면 해결될 수 있었을지도 모릅니다.

결론

ViewModel의 존재는 선언적 UI 시대에 필요없다고 생각됩니다.

View에서 로직과 관련된 코드를 분리시키기 위한 장소로 ViewModel이라는 단어를 사용하는 것을 그만했으면 합니다.

이것은 "나는 이렇게 생각합니다"라는 의미이고, "이 생각은 무조건 옳다"라는 주장은 아닙니다. 평소에 보는 코드베이스나 백그라운드, 생각하는 방법, 시점 등에 의해 그 선택이 옳은지 아닌지는 사람마다 다르기 때문에.

"그러면, MVVM을 사용하지 않고, @@아키텍처를 사용하자"라는 둥의 어떠한 특정 아키텍처를 추천하는 것이 이 글의 목적은 아닙니다.

TCA(The Composable Architecture)를 사용하는 것도 사실 검토했었지만, 너무 과장하는게 아닐까 우려되기도합니다. (* 내용추가: 다시 검토해본 결과, TCA는 시기상조라는 의견이 많지만, 저는 한 번 사용하고 싶다고 생각합니다.)

The Composable Architecture https://github.com/pointfreeco/swift-composable-architecture

각 어플리케이션에 맞는 아키텍처를 "잘 고민해서" 사용하는 것을 추천합니다. 혹시라도 고민한 결과가 "역시 MVVM을 사용해야겠다."여도, 그것은 그것으로도 꽤 좋다고 생각하고, 그 생각을 부정할 생각은 일도 없습니다.

어디까지나 저(글쓴이) 개인이 SwiftUI를 사용하는데 있어서, "MVVM 사용을 멈추자"라고 생각에 이르렀기 때문에, 그 이유에 대해서 작성한 글이므로 MVVM을 디스할 생각도 없고, 현재의 "당연히 MVVM을 사용한다"라는 흐름은 좋지 않다고 생각했기에 이 글을 작성했습니다.

마지막까지 읽어주셔서 감사합니다. 혹시 의견이 있다면 댓글로 작성해주신다면 감사합니다.


추가 내용

오해를 산 내용이 있다고 생각되어 추가로 작성합니다.

오해를 샀다고 생각된 트윗 내용

  • "ViewModel = ObservableObject"
  • "그러면 ObservableObject을 사용하지말라는 건가?"
  • "@State만 사용하라는건가?"

"SwiftUI의 ObservableObject는 ViewModel야"라고 하는 것은 맞는 말이기도 하지만 아니기도 합니다.

"ObservableObject는 ViewModel입니다"라는 말은 대체 누가 정한걸까요?

ObservableObject는 단순한 React한 Object로 ViewModel는 아니라고 생각할 수 있습니다.

ObservableObject는 Model/StateHolder로 생각하는게 자연스럽지 않을까요?

하지만 SwiftUI.ObservableObject는 SwiftUI의 일부로 사용하면 사용할수록 좋다고 생각합니다. 이 아티클은 "ObservableObject를 사용하는걸 멈추자"라는 의도가 아닙니다.

이해해주시길 바랍니다.

참고로, 그 ObservableObject를 ViewModel라고 명명하는 것에 대해서는 Model명/Store명/Domain명 등의 그대로 이름을 붙이는게 좋지 않을까 생각합니다. (ViewModel레이어(계층) 없애기)

from.@young 글쓴이는 ObservableObject의 이름을 @@ViewModel로 하는 것보다, @@Model, @@Store 등과 같이 하는 역할에 따라 명명하는 것을 추천하네요 !

@unnnyong
Copy link
Author

어디까지나 저(글쓴이) 개인이 SwiftUI를 사용하는데 있어서,
"MVVM 사용을 멈추자"라고 생각에 이르렀기 때문에,
그 이유에 대해서 작성한 글이므로 MVVM을 디스할 생각도 없고,
현재의 "당연히 MVVM을 사용한다"라는 흐름은 좋지 않다고 생각했기에 이 글을 작성했습니다.


글쓴이는 ObservableObject의 이름을 @@viewmodel로 하는 것보다, @@model, @@Store 등과 같이 하는 역할에 따라 명명하는 것을 추천하네요 !

@tokijh
Copy link

tokijh commented Aug 24, 2022

(* 내용추가: 다시 검토해본 결과, TCA는 시기상조라는 결론입니다.)

라는 내용 중에

追記:検討した結果、TCAは時期尚早という意見が多いのですが、ぼく自身は一度使ってみたいと思っています

라고 쓰여있는데요, 제가 의역하면

(* 내용추가: 다시 검토해본 결과, TCA는 시기상조라는 의견이 많지만, 저 자신은 한 번 사용하고 싶고 생각합니다.)

로 번역하게 될 거 같아요.


위 한글 번역을 보고, 'TCA 에 어떤 큰 문제가 있는가' 를 생각하면서 원본을 찾아보게 되었습니다.
번역 이후에 내용이 바뀌었을 수 있는데, 표현의 차이로 인해 TCA 자체 기술에 대해서 부정적인 인식을 가지게 되는 것이 우려스러워 최대한 원 작성자의 의도를 명확하게 표현되었으면 합니다.

@unnnyong
Copy link
Author

https://gist.github.com/unnnyong/439555659aa04bbbf78b2fcae9de7661?permalink_comment_id=4277488#gistcomment-4277488

@tokijh

안녕하세요 : )
저자의 의도를 부정적으로 표현하려고 했던건 아닌데 제가 누락을 했거나 내용이 업데이트가 있었나보네요 .. !
말씀해주신 내용 반영해두었습니다 🙆‍♂️ 코멘트 감사합니다 🙏

@luminouxx
Copy link

영 안녕하세요
이렇게 만나게 되니 정말 반갑네요
저도 비슷한 고민을 하고 있었는데, 정말 많은 도움이 되었습니다!
감사합니다~!~!

@Mercen-Lee
Copy link

ViewModel의 필요성에 대해 계속 생각해왔는데 저와 같은 생각을 하시는 분들이 계셨네요.
유익한 정보 감사합니다!

@zoop1259
Copy link

MVVM패턴에 대해서 공부하다 이 글을 보게 되었네요.
후에 스유에서의 패턴이 어떻게 될지 궁금해집니다.

@yongbeomkwak
Copy link

영 반갑습니다! 2기 러너 오전 세션 Kayle 입니다.좋은 글 공유해주셔서 감사합니다.
MVVM 신봉자로써 (사실 아는 패턴이 MVVM뿐이라는건 비밀)
영이 말한 깊게 생각하지 않고 프로젝트의 아키텍쳐로 MVVM을 선택하고 있는 사람이라 뒷목을 잡았네요!
영과 다양한 디자인패턴에 대한 대화창이 있으면 좋을 것 같아요 :)

@earlysummer0303
Copy link

좋은 자료 잘 읽었습니다 :) 감사해요 영!

@Oreo-Mcflurry
Copy link

좋은 자료 감사합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment