이 책의 모든 챕터를 따라오신 독자 여러분, 정말 수고하셨습니다. 우리는 초반의 챕터 2, 챕터 3에서 TCA의 기본 개념에 대해 접하며 값 타입의 안정적인 변형에 대해 TCA가 제안하는 답을 살펴보았습니다. SwiftUI와의 유기적인 연동을 위해 TCA가 추가적으로 제공하는 MultiStore와 Navigation에 대한 설명을 통해 각 기능을 모듈화하여 관리하는 방법도 익혔습니다. 마지막으로 각 기능이 우리가 기대하는대로 동작하는지 확인할 수 있는 유닛 테스트 방법도 살펴보았습니다.
지금까지 살펴보신 것처럼 TCA는 SwiftUI의 값 타입 구조체인 View가 갖는 특성에 아주 적합한 아키텍처 패턴을 제공합니다. TCA는 사용자 인터랙션, 상태 업데이트, 뷰 렌더링 등이 명확한 순서와 방향
을 가지도록 하는데, 이는 SwiftUI가 단방향 흐름을 기반으로 하는 것과 동일한 방식이며, 이러한 흐름을 강화하는 강력한 도구
로 작동합니다.
어쩌면 MVVM과 TCA를 비교하며 후자가 절대적으로 좋은지, 전자와는 어떻게 다른지 궁금할 수 있습니다. MVVM과 TCA의 불편한 관계를 간단히 언급하자면 다음과 같습니다. 이 두 아키텍처는 모두 데이터의 단방향성을 지향합니다. TCA는 View와 View에게 필요한 상태를 관리하는 Store 객체로 구성된 아키텍처입니다. 한편, MVVM은 객체들의 역할을 강조하는데, 특히 ViewModel이 SwiftUI에서 무용하다는 의견이 여러 커뮤니티에서 불거지고 있습니다. SwiftUI와의 궁합을 생각해보면 TCA가 더 좋을 수도 있겠습니다만, 이 또한 정론은 아닙니다. TCA는 SwiftUI가 제안하는 Binding을 벗어나는
태도를 조금씩 보이기 때문입니다. 어느 한 쪽이 갖는 단점이 다른 쪽의 장점이 되지는 않는다는 점도 유념해야 합니다.
집필진이 생각한 MVVM과 TCA의 가장 큰 차이점은 구현의 자유도에 있습니다. MVVM 구조로 앱 개발을 한다고 하면, View와 ViewModel과 Model을 작성하고 서로 잘 연결하는 것만으로도 MVVM 구조의 구색을 갖출 수는 있습니다. 따라서 그 내부의 구현 자체는 꽤나 유연하고 개발자의 취향에 따라 구성되고는 합니다. 반면에 TCA는 아키텍처를 적용하는 순간 그 규칙에 엄격히 따라야
합니다. 그렇지 않다면 오작동할 수 있고 경우에 따라 컴파일도 불가능합니다.
다만 TCA만이 갖는 강점은 분명히 있습니다. SwiftUI는 State의 변화에 따라 View를 업데이트하는데, TCA는 이를 관리할 뿐만 아니라, 개발자로부터 이를 추적 가능하게
프로그래밍을 하도록 가이드라인
을 제시합니다. 직관적으로 이해하기 쉽게 Action을 설계할 수 있다는 점과 일관된 방법으로 View와 Store를 구조화할 수 있다는 점은 협업하는 개발자들의 소통 비용을 상당 부분 절감할 수 있다는 장점으로 이어집니다.
또한 이를 구성하는 모든 컴포넌트의 재사용 가능성
이 높아집니다. MVVM은 객체 간 통신 및 재활용에 대한 일관된 가이드라인이 없지만 TCA는 MultiStore의 도움으로 컴포넌트 간 통신, 재활용이 유연하게 가능합니다. 특히 State와 로직을 분리하기 때문에 각 컴포넌트 속 부품화 되어있는 reducer 함수의 테스트와 UI테스트에 용이
합니다.
이렇게 보면 TCA가 정말 많은 장점을 가진 만병통치약 아키텍처처럼 비추어질 수 있지만 실제로는 그렇지 않습니다.
TCA는 그만큼 러닝커브가 높고, 프로젝트의 복잡성
을 늘릴 수 있습니다. TCA의 메인테이너는 해당 아키텍처를 유지하기 위해 자체적으로 준비한 또 다른 프레임워크들을 TCA에 적용하기 때문에, 추가적인 프레임워크에 의존성
이 늘어나는 것 또한 마냥 기쁘지는 않습니다. 특히, 작은 프로젝트에서는 TCA의 도입이 과도한 설계
가 되는 경우가 있으므로, 이 경우엔 TCA를 사용하지 않는 것이 바람직하다고 집필진이 조심스럽게 의견을 밝혀봅니다.
또한 혹자는 TCA가 SwiftUI의 강점들을 활용하지 않는다는 비판을 하기도 합니다. @State
와 @Binding
과 같은 강력한 상태관리 프로퍼티 래퍼
를 사용하여 상태를 간단하고 쉽게 관리
할 수 있게 하는 것이 SwiftUI의 강점인데, TCA는 이러한 SwiftUI의 고유한 기능을 활용하기 보다 TCA의 Binding 방식을 제안합니다. 이는 TCA가 지향하는 일관된 아키텍처와 테스트 용이성에 더 초점을 맞춘 것 같은 태도로 보입니다.
예를 들어, SwiftUI는 Alert와 Confirmation Dialog의 Navigation을 설명할때, Point-Free개발진들은 SwiftUI가 제시하는 이니셜라이저를 사용하지 않고 바인딩이 매우 강한 형태로, 더욱 복잡한 형태
로 이니셜라이저를 직접 구성하여 사용하곤 했는데, SwiftUI의 바인딩의 간결성이 희생
되는 아주 대표적인 예로 볼 수 있습니다.
그리고 TCA는 아직도 살아 움직이는 날것의 프레임워크 입니다. 현재 1.0.0 버전이 배포되었다고는 하나, iOS 17 버전 소개와 함께 대대적인 업데이트가 다시 예고
되었습니다. 제너릭 파라미터 팩이나 macro
와 @Observable
등 새로운 API에 대한 Point-Free의 관심도를 보면 TCA가 다시 한 번 큰 변화를 맞이할 것은 꽤나 자명해 보입니다. 끊임없이 변화하며 살아있는 프레임워크를 적용할 때 그 변화 흐름에 잘 따라간다면 큰 무기가 되겠지만 그렇지 못한다면 추후 대응할 수 없는 문제를 마주칠 수도 있다는 점을 염두에 두어야 합니다.
집필진의 소감을 간단히 남기며 서적을 마무리하고자 합니다. 책을 작성하고 TCA를 직접 프로젝트에 적용해본 경험으로 미루어보면, 전반적인 코드의 품질이 상당히 향상
되었다는 것을 공통적으로 느꼈습니다. 물론 TCA를 사용함으로써 프로젝트의 복잡성이 적지 않게 증가한다는 점을 부정할 수는 없지만, 장기적으로 보았을 때 앱이 확장
될 것을 생각한다면 TCA 적용이 탁월하다는 사실 또한 부정할 수 없었습니다. 특히 필자 개인적으로 TCA를 이용하여 작성한 컴포넌트들을 다른 앱, 혹은 다른 뷰의 코드를 작성할 때 재사용한 경험이 많기 때문에, 앱의 복잡성이 증가한다는 단점을 어느정도 보완
할 수 있다고 생각합니다. 하지만 TCA 공식 문서만을 읽으며 앱에서 요구하는 모든 부분을 개발하기엔 상당한 학습을 요구하며, Point-Free사에서 제시하는 방식으로 모든 Navigation(기본 navigation, deeplink, alert, confirmation dialog 등)을 구성하려면 설계 단계에서부터 적지 않은 노력이 필요합니다. 가끔은 이 강력한 Binding 도구들이 과하다는 생각
이 들기도 합니다. 하지만 책 내용에서도 알 수 있듯, 이 모든 도구들은 더 안정적으로 State
의 변형을 추적하고, 앱에서 발생하는 모든 상황을 통제
하기 위함입니다. 더 효과적으로 앱을 관리하고자 한다면 이 정도의 러닝 커브는 충분히 투자할 가치가 있다는 점에 공감하시리라 생각합니다.
TCA에 대한 기본적인 이해를 익혔으니, 간단한 프로젝트를 시작해보며 손에 익혀보기를 제안합니다. 책을 통해 SwiftUI와 TCA를 효과적으로 결합하는 방법에 대한 깊은 이해를 얻기를 바랍니다. 책의 제목처럼 상태관리와 테스트를 함께 고려할 수 있는 개발자가 되시기를 바라며, 책을 마무리합니다.