본문 바로가기

Swift/SwiftUI

흔하디 흔한 TCA 기본 개념 정리

TCA의 기본 개념에 정리하기에 앞서

- [참고자료] SwiftUI에서 MVVM 사용을 멈추자"라고 생각이 들었던 이유
 
TCA의 기본 개념에 정리하기에 앞서 왜 SwiftUI에서 MVVM이 필요 없는지에 대한 글이다
진짜 초 간단히 정리 하자면 이미 SwiftUI자체가 이미 MVVM의 구조를 내포하는데 왜 또 MVVM을 더하냐는 글이다

이미 기능적인 목표를 달성했는데 굳이 바퀴까지..?

 
SwiftUI만으로도 MVVM수준의 아키텍처 문제는 해결되었으니 이제 더 상위 레이어의 아키텍처에 대해 고민해보아야 한다라는 글이다
 

MVVM은 뭔데?

Model - View - ViewModel 의 대문자만 따온 패턴으로 주로 RxSwift와 자주 이용된 패턴이다.
Data요청이 먼저냐 Binding이 먼저냐는 때에 따라 다르고 전체적인 로직은 아래와 같다
 
1.  ViewModel의 어떤 Data와 View가 Binding되어있다(ViewModel에서 해당 Data가 변경되면 바로 View에 반영 될 수 있도록 연결되어 있다)
2. View에서 사용자 이벤트가 발생하고 ViewModel로 전달 된다
3. 해당 이벤트를 토대로 Model에 새로운 Data를 요청한다
4. Model에서 새로운 Date를 받아오면 ViewModel에게 알려준다
5. ViewModel은 해당 Date를 가공해 저장한다
6. 해당 Data와 연결되어있는 View가 업데이트 된다
 
장점은 뷰와 그 외의 로직들은 분리해서 코드를 작성 할 수 있고 또 비즈니스 로직 코드 관리가 쉬웠다
굳이 단점을 뽑자면 한 화면에 기능이 많아지면 ViewModel이 비대해지고 관리해야할 요소들이 많아진다는 것인데... 앞으로 공부할 TCA(단방향 로직)가 이것을 해결해 줄 수 있을 지 글을 쓰는 지금 현재는 아직 모르겠다
 
다만, 이 글의 요지는 UIKit에서 MVVM이냐 단방향 로직이냐가 아닌 SwiftUI 에서 MVVM대신의 TCA(단방향 로직) 이기 때문에 MVVM의 장단점은 필요가 없을 것 같다
 
 

TCA란?

'TCA란?' 이라는 이 조그만 공간을 통해 다 설명하긴 어렵겠지만 이 글에서는 아주 간략하게 적어보려고 한다
(튜토리얼 그리고 SwiftUI 상태 관리부터 테스트까지 iOS 개발자를 위한 TCA 1.0 라는 무료 공개된 책자를 통해 차차 공부해 나갈 예정이다.)

 

View : 말 그대로... 뷰..!
 

Store :  State, Reducer, Action, Effect등을 갖고있는 커맨드 센터 같은 역할

- State : 로직을 수행하거나 View를 그릴 때 필요한 Data 집합
- Reducer : Action을 전달받아 이를 처리 후 결과를 State의 상태를 변경해 UI를 업데이트하도록 하는 로직을 구현하는 메서드 (State와 Action을 연결해주는 그런 어떤 무언가...?)
- Action : 사용자 혹은 노티피케이션 등 뷰에서 발생할 수 있는 이벤트와 API호출 결과를 나타냄
- Effect : Dependency와의 상호작용을 통해 얻는 결과 (성공했으면 effect고 실패하면 sideEffect인거고...모 그런...)
- Dependency : 외부시스템과 상호작용 하는 것, ex) API 요청, 디스크 처리 등
 
아무튼 결과적으로 로직은 아래와 같다
 
1. View에서 이벤트 발생해 Action으로 전달
2. Action은 알맞는 Reducer로 전달
    2 - 1. 여기서 외부 상호작용이 필요하면 하고 아니면 처리해서 State 반영
3. State반영에 따른  View 업데이트

 

 개인프로젝트 로아랑에 TCA를 적용한다면...?

 
MVVM이 TCA에 완전 대응되는 것은 아니지만 프로젝트 구조를 전환한다 가정하고 굳이 비교를 해보자면...

CleanArchitecture + MVVM의 구조에서는
1. VM에서 UseCase에 검색 요청
2. UseCase에서 Repository로 API요청 및 DTO반환 받음
3. 반환받은 DTO를 UseCase가 Data가공 후 VM으로 전달
4. VM에서 데이더 변경 및 뷰 반영

이렇게 된다. 즉,
CharacterView
CharacterVM
SearchUseCase
NetworkRepository
가 필요하다

이걸 TCA 개념으로 전환해 보자면
- CharacterView -> CharacterView 그대로
- CharacterVM은 ->
   * ChracterStore
       * State
       * Reducer
       * Action
SearchUseCase의 기능은 위의 Reducer에서 처리하면 될 것 같고
NetworkRepository는 Dependency 영역이라고 생각된다

로직은 아래와 같지 않을까 싶다

1. View에서 onAppear Action 트리거
2. Action에서 이름을 전달받아 Reducer로 전달
3. Reducer에서 해당 이름을 Dependency로 요청
3. Dependency에서 API요청 후 Effect를 Action으로 Reducer에 전달
4. Reducer에서 State업데이트

이런 식으로 흘러가지 않을까 싶다
(앞으로 더 공부하면서 어떻게 적용할지 구체적인 고민을 더 해봐야겠다)

참고자료
- [정대리 유튜브] https://www.youtube.com/watch?v=fYQ9YnbvasU&t=1603s
- [네이버페이 워치앱 SwiftUI TCA 적용기] https://blog.naver.com/naverfinancial/223160757757