...
본문 바로가기

아키텍처

아키텍처 공부중.. RIBs, TCA 트리구조 ?

 

지금까지는 내 직무와는 무관한 내가 하고 싶었던걸 했었고( flutter) , 이제는 커리어 측면에서 도움이 되는 공부를 하려고한다. 

그래서 몇달간은 Swift, 아키텍처 공부를 중점으로 하려고 한다. 

 

그동안 아키텍처없이 MVC, MVVM 만 써왔는데, 클린아키텍처 책을 읽고서, flutter 개발하면서 내가 이해한 클린아키텍처를 적용하면서 앱을 만들어봤었다. 그러면서 이제는 다른 자명한 아키텍처를 공부하고 있다.

 

RIBs 맛보기 

 

RIBs도 구조만 잠깐 봤다. 무려 3년전에 찍먹으로 RIBs 강의를 들은적이 있었지만, 다 까먹어서

RIBs의 요소들을 천천히 살펴보면서, 실제 예시 코드까지 보니까 머리가 도라방스

 

RIBs 의 요소들의 세부구조는...

아래처럼 다이어그램 짜볼수 있을것 같다. ( -> 는 의존인데, 닫힌화살표는 상속또는 구현했다는 뜻)

Presentable, Listener, Interactable ..... 어우 프로토콜이 왜캐많은지 이때부터 머리가 어지러웠다.

그래도 단어의미를 차근차근보니 이해가 되는것 같기도하다. ( 네이밍이 참 중요하다 )

 

 


그래서 잠시 멀리보면서, 큰 구조를 보았다. 트리가 보였다.

RIBs의 큰 구조는 트리라는걸 보니 한결 더 이해하기 쉬웠다.

 

 

 

약간 여기서 영감을 얻었다라고 해야하나, 트리라는걸 이해하는 순간, 내가 그렇게 어렵게만 생각해왔던 아키텍처도 그리 어려운건 아니다라고.. ? 

( 회사 동기가 나한테, "아키텍처가 다 거기서 거기다." 라는 말을 해줬는데, 그친구의 의미가 내가 이해한것과 같을까 ? 싶기도하다. )

 

 

개인적인 생각으로 앱의 구조는 트리라고 생각한다. 

부모가 있고, 그안에 자식들이 있고, 또 그안에 자식들이 있고, 

뷰가 그렇다. 뷰안에 서브뷰가 있고, 네비게이션뷰도 마찬가지로. 

단순히 부모뷰가 서브뷰를 가지는건 쉬운데, 여기서 이제 예외케이스로 서브뷰가 부모뷰에게 이벤트를 전달해야하는 상황이다. 

 

그래서 나는 앞으로 어떤 아키텍처를 보게된다면, 이런 예외케이스를 보려고 할것 같다. 

대부분 아키텍처들은 요소들이 있다면, 이요소들이 한 덩어리가 되어 트리구조가 되어질것이고,

그러면 여기서 이제 서브뷰가 부모뷰에게 어떻게 이벤트를 처리할건지를 보면 좀 더 이해가 쉽지 않을까? 

 

암튼 다시 돌아와서, Router가 자식 Router를 바로 가질순 없으니, 자식 Builder를 갖도록 하여, 트리구조를 구현한것 같다. 

이제 자식 interactor가 부모 interactor에게 전달하는것을 통해, 하위뷰가 부모뷰에게 이벤트를 전달하는것을 구현한것 같다. 

 

그리고 대부분, View와 비즈니스로직은 분리라는게 거의 정석이 된것 같고.  MVVM도 View와 ViewModel을 나눈것처럼.

이러한 관점에서 보면, Interactor가 ViewModel의 역할을 한다고 봐도 될것 같다. 

 

RIBs 트리구조를 보면서 드는 생각이 내가 Flutter로 만들면서 내가 적용한 아키텍처와 굉장히 유사하긴했다.

나는 좀 들뜨긴했는데, 사실 이제와서 생각해보면 트리구조면 다 비슷비슷할것 같다라는 생각이다 ㅎ.. 

 

 

TCA 맛보기 (개인적인 생각)

아직 개념이 정립되지 않아, 틀릴 수 있습니다. 개인적인 생각입니다. 참고해주세요..!

 

아직 몇일 안보긴했는데, 크게 느낀점은 요소자체는 어렵지 않다. State, Action, Reducer, Environment, Store.

오히려 RIBs보다 훨씬 간단해보인다. State는 말그대로 상태. 뷰의 업데이트를 일으키는 상태값.

Action은 말그대로 View안에서의 행위이고, 

Reducer는 Action이 들어오면 State를 변형시키는 비즈니스로직을 담당하고, (ViewModel 같다) 

Store는 이러한 Reducer를 View에서 사용할수있게끔 만들어주는 친구같고,

Environment는 이제 그외 컴포넌트들이라고 보면될것같다. 네트워크, DB같은 ? 

 

TCA도 트리구조라고 생각한다. 

Reducer가 자식 Reducer를 갖도록하는... 

 

근데 RIBs나 기존 UIKit, AppKit에서 사용하던것과 생각해보면.. TCA는 굉장히 View에 의존적이라는 생각이 든다. 

기존에 사용하던 아키텍처들은 UI를 내가 컨트롤할수있다는 느낌이 강하다. 

RIBs의 트리구조는 UI와 독립적이라고 생각한다. RIBs의 트리구조를 봐도 Router가 돌고돈다. 그안에 View가 있을뿐 

 

근데 TCA는 아무리봐도 Reducer를 갖는 Store가 View안에 속해있다. 물론 로직자체는 Reducer에만 있긴하지만.

 

그래서 생각할수록 swiftUI에 최적화된 아키텍처가 왜 TCA라고 하는지 알것같다.

 

일단 swiftUI는 상태관리가 기존 방식과는 다르기때문인것 같다.

 

아직 정확히 설명을 못하겠는데...

swiftUI에서 View는 상태를 완전히 소유할수있다. View는 상태를 바라보면서 새롭게 매번 인스턴스가 생성되어 그려질수있는데, 상태는 독립적이다. 하지만 View가 필요없어지는 상황이 온다면, 상태도 없어질수있다. 

상태를 완전히 소유하면서도 View는 새롭게 매번 그려질수있고, 이 아이러니라고 해야하나 .. 

핵심은 View가 struct타입이므로, 새롭게 인스턴스가 생성되어서 다시 그려지지만, View가 소유하고 있는 상태는 독립적으로 존재하는것 같다.

그래서 swiftUI에서는 struct를 이용해 값싸게 그려내면서, View와는 독립접으로 상태가 존재할수있도록  @ObservedObject, @State, @StateObject, @Binding 이라는 다양한 개념을 도입을해서 이것을 구현한것 같다. 

 

다른 아키텍처들은 시작지점을 View와 무관하게 시작할수있는데, TCA는 무조건 View안에 있어야하니까, 이런점이 UI에 의존적이라고 생각이든다. 

 

결국 이 핵심때문에 TCA는 View에 의존적으로 속해있게 된게 아닌가 싶다. 

 

TCA의 요소들의 개념자체는 어렵지 않은데, 코드가 난해한것 같다. ㅎ 게다가 TCA버전이 업데이트가 아주 빠르고, 블로그에 나와있는 코드들은 deprecated된 경우가 많았다.  장단점이 있는것 같다. 

그만큼 TCA에 지원이 많다는 장점이면서도 코드가 많이 바뀌는것도 단점인것 같기도. 어쩌면 변화는 숙명일지도... 

 

TCA의 트리를 이용하려면 scope라는 개념도 있는것 같은데, 더 공부해봐야겠다. 물론 swift도.