TCA(The Composable Architecture)란?

yeton·2023년 10월 13일
0
post-custom-banner

현재 사이드 프로젝트로 TCA패턴과 SwiftUI를 사용하고 있어서 TCA 패턴에 대해 공부한 것들을 정리해보려고 합니다. 처음에 이해가 쉽지 않았기에 글로 정리해놓으면 좋을 것 같아 글로 정리해보려고 합니다. 🌷

TCA란?

TCA는 Point-Free에서 개발하고 있는 오픈소스 라이브러리입니다.

TCA는 SwiftUI와 함께 사용하도록 디자인이 되었지만 UIKit도 사용할 수 있도록 지원하며 모든 애플 플랫폼(macOS, tvOS, watchOS)에서 사용 가능합니다.

작동 방식

출처

위 이미지는 TCA의 작동 방식을 나타낸 것입니다.

View부터 시작해서 화살표를 따라가보면,
먼저 View에서는 Action을 보낼 수 있습니다. 예를 들어 사용자가 버튼을 누르면 그 행위로 Action을 발생시키고, Action은 Reducer로 들어가게 됩니다.
Reducer는 Action이 들어왔을 때 현재의 State를 다른 상태로 변화시키는 함수입니다.

단, 우리는 평소에 앱 내부의 데이터만 사용하는 것이 아닌, 앱 외부의 데이터를 사용해야 하는 경우가 훨씬 더 많습니다. 이때 우리는 API 통신을 하게 되는데 이때 앱은 해당 API에 의존성(Dependency)를 갖게 됩니다. 이러한 의존성을 가지고 있는 타입을 Environment라고 합니다.

요약하자면,
Reducer 함수가 실행되면 두 가지 경우의 수로 나뉘는데, 바로 State를 변화시키거나 혹은 Environment를 실행시켜 외부 api와 통신을 하는 것입니다.

( 최근에 저희 프로젝트에서는 Environment 대신 조금 더 간편하게 의존성을 주입시킬 수 있게 업데이트 된 @Dependency(.apiClient)를 사용하였습니다. 아래에서는 저희 프로젝트에서 Dependency apiClient를 사용한 예시를 적어놓았습니다 )

// API 통신하는 apiClient 정의
struct LoginCore: ReducerProtocol {
  @Dependency(\.apiClient) var apiClient
}

// Reduce 내에서 사용 
Reduce { state, action in
      switch action {
      case .kakaoLoginTapped:
        return .run { send in
          do {
            let kakaoLoginResponse = try await self.apiClient.request
          }
  
      ...

Environment를 통해 외부 API와 통신을 한 뒤 그 값을 Effect 타입으로 반환합니다.
위에 첨부된 이미지를 보면 Environment에서 반환한 Effect값은 다시 Action 단계로 진행되는 것을 볼 수 있습니다.

원하는 Effect 가 들어온 경우와 Side Effect 가 발생한 경우 각각을 Action으로 받아들이고, 다시 Reducer에서 로직을 실행해주기 위해서입니다.

예시를 들어서, api 통신을 통해 Effect 값이 제대로 들어왔다면 State에 있던 값을 이값으로 업데이트 해주면 끗!인 것입니다. State가 업데이트 되면 View가 다시 이에 맞춰서 그려지겠죠!

마지막으로는 Store입니다.
Store는 실제로 기능이 작동하는 공간(State, Reducer, Environment가 포함돼있는)을 말합니다.
우리가 Action을 보내서 Store는 Reducer와 Effect를 실행할 수 있고 State의 변화를 관찰해서 UI를 변경시킬수도 있겠죠!
Store가 존재하는 이유는 state에 대한 모든 변경을 관찰하고 다시 렌더링할 수 있도록 하기 위함입니다. 따라서 모든 사용자의 action을 store로 보내서 state를 변경할 수 있는 것이죠!

다음 시간에는 TCA에서 부모-자식 뷰 간의 데이터 전달 방법을 적어보겠습니다. (과거 매우 헷갈렸었던 나...)

참고 문헌

profile
🤗제 깃허브 링크는 https://github.com/yeeton37🤗
post-custom-banner

0개의 댓글