SwiftUI - TCA (.merge와 .concatenate)

CodeCat·2024년 9월 8일

IOS SwiftUI TCA

목록 보기
8/20
post-thumbnail

안녕하세요 !

이번에는 .merge와 .concatenate 주제로 포스팅 작성해보려 합니다

.merge와 .concatenate 이 두 연산자는 여러 개의 Effect를 결합하는 데 사용되며, 각각 고유한 특성을 가지고 있어요 ㅎㅎ

자 이제 본격적으로 알아보도록 할게요

.merge 연산자

.merge 연산자는 여러 Effect를 병렬로 실행하고 결과를 결합 시켜요 이는 동시에 여러 작업을 처리해야 할 때 유용합니다.

struct Feature: Reducer {
  struct State { var count = 0 }
  enum Action { case incrementTapped, decrementTapped }
  
  func reduce(into state: inout State, action: Action) -> Effect<Action> {
    switch action {
    case .incrementTapped:
      state.count += 1
      return .merge(
        Effect.run { _ in print("Increment") },
        Effect.run { _ in print("Logged") }
      )
    case .decrementTapped:
      state.count -= 1
      return .none
    }
  }
}

예제 설명

.incrementTapped 액션이 발생하면 두 개의 Effect가 병렬로 실행됩니다
"Increment"와 "Logged"가 동시에 출력될 수 있으며, 단 순서가 어떻게 될지는 알 수 없어요!
.merge는 여러 작업을 동시에 처리해야 할 때 유용해요!

.concatenate 연산자

.concatenate 연산자는 여러 Effect를 순차적으로 실행하며 특정 순서로 작업을 수행해야 할 때 사용됩니다

struct Feature: Reducer {
  struct State { var count = 0 }
  enum Action { case incrementTapped, decrementTapped }
  
  func reduce(into state: inout State, action: Action) -> Effect<Action> {
    switch action {
    case .incrementTapped:
      state.count += 1
      return .concatenate(
        Effect.run { _ in print("First") },
        Effect.run { _ in print("Second") },
        Effect.run { _ in print("Third") }
      )
    case .decrementTapped:
      state.count -= 1
      return .none
    }
  }
}

예제 설명

.incrementTapped 액션이 발생하면 세 개의 Effect가 순차적으로 실행됩니다. "First", "Second", "Third"가 순서대로 출력됩니다. .concatenate는 작업의 순서가 중요할 때 사용하면 좋아요

사용 예시 !

struct UserProfile: Reducer {
  struct State {
    var user: User?
    var posts: [Post] = []
    var friends: [Friend] = []
  }
  
  enum Action {
    case loadUserData
    case userDataLoaded(User)
    case postsLoaded([Post])
    case friendsLoaded([Friend])
  }
  
  func reduce(into state: inout State, action: Action) -> Effect<Action> {
    switch action {
    case .loadUserData:
      return .concatenate(
        Effect.run { send in
          let user = await fetchUser()
          await send(.userDataLoaded(user))
        },
        Effect.merge(
          Effect.run { send in
            let posts = await fetchPosts()
            await send(.postsLoaded(posts))
          },
          Effect.run { send in
            let friends = await fetchFriends()
            await send(.friendsLoaded(friends))
          }
        )
      )
    case .userDataLoaded(let user):
      state.user = user
      return .none
    case .postsLoaded(let posts):
      state.posts = posts
      return .none
    case .friendsLoaded(let friends):
      state.friends = friends
      return .none
    }
  }
}

이 예제에서는 .loadUserData 액션이 발생했을 때, 먼저 사용자 데이터를 가져오고 (.concatenate의 첫 번째 Effect), 그 후에 게시물과 친구 목록을 동시에 가져옵니다 (.merge를 사용한 두 번째 Effect).
이렇게 사용하면 사용자 데이터가 먼저 로드되고, 그 다음에 게시물과 친구 목록이 병렬로 로드되는 효율적인 데이터 로딩 흐름을 구현할 수 있어요

이상으로 포스팅 마무리 하겠습니다.

.
.
.

감사합니다.

profile
코드와 고양이의 만남

0개의 댓글