[TCA] 03. TCA의 바인딩 방식을 알아보자.

2026. 1. 13. 20:34·iOS/TCA
728x90

바인딩?

iOS 개발에서 바인딩이라는 말을 참 많이 쓰는 것 같다. UIKit이나 RxSwift로 개발할 때도 바인딩이라는 말을 참 많이 썼는데, 바인딩이 대체 뭘까? 간단히 짚고 넘어가보자.

 

iOS 개발에서 바인딩(Binding)이란? 말 그대로 데이터와 UI 묶어(Bind) 둘 사이를 동기화하는 것을 의미한다. 자세한 내용은 바인딩 글에서 다뤄보도록 하고, TCA에서의 바인딩 방식을 알아보자.

 

Binding(get:send:)

struct MyView: View {
  let store: Store<State, Action>
    
  var body: some View {
      WithViewStore(store) { viewStore in
          TextField(
              "Name",
              text: viewStore.binding(
                  get: \.name,
                  send: Action.nameChanged
              )
          )
      }
  }
}

가장 기본적으로, Binding(get:send:)의 형태로 바인딩 한다. SwiftUI 기본 컴포넌트의 바인딩 파라미터에 binding 객체를 전달하는 형식이다. 현재 TCA에서는 잘 사용하지 않는데, 모든 상태 변경마다 개별 액션을 만들어야하고, Getter와 Sender를 수동으로 관리하기 때문에 가독성도 떨어지기 때문이다. 문제가 있다기 보단, 귀찮은 점..? 보일러 플레이트의 이유가 가장 큰 것 같다. 

 

+ WithViewStore, ViewStore가 deprecated 되면서 Binding(get:send:) 방식은 거의 사용하지 않는다.

 

BindingState + BindingAction + BindingReducer

BindingState

struct State: Equatable {
  @BindingState var name: String = ""
  @BindingState var age: Int = 0
}

State의 특정 프로퍼티가 View에서 바인딩으로 변경될 수 있음을 알리는 프로퍼티이다. 음.. 쉽게 말하면 "이 프로퍼티는 바인딩이 가능한 프로퍼티입니다!"라고 점찍어주는 프로퍼티라고 생각하면 될 것 같다. (나 바인딩 가능해요!)

 

BindingAction

enum Action: BindableAction {
  case binding(BindingAction<State>)
  case login
  case logout
}

모든 바인딩 변경을 하나의 액션 타입으로 통합하기 위한 프로토콜이다. Action enum에 BindingAction 프로토콜을 채택하여, State의 액션을 하나의 액션 타입으로 통합한다.

 

BindingReducer

@Reducer
struct Feature {
  var body: some ReducerOf<Self> {
      BindingReducer()  
        
      Reduce { state, action in
          switch action {
          case .binding:
              return .none
                
          case .login:
              return .none
          }
      }
  }
}

BindingAction을 받아와 BindingState가 붙은 프로퍼티의 값을 실제로 변경해주는 리듀서이다. 예전엔 리듀서에 .binding을 붙였지만, 지금은 BindingReducer()를 리듀서 빌더 안에 명시적으로 넣어준다.

 

struct BindingReducer<State, Action>: Reducer {
    func reduce(state: inout State, action: Action) -> Effect<Action> {
        guard case let .binding(bindingAction) = action else {
            return .none
        }

        state[keyPath: bindingAction.keyPath] = bindingAction.value
        
        return .none
    }
}

내부적으로 BindingAction의 keyPath와 Value를 사용해서 실제로 state를 변경한다. 

 

struct TextFieldView: View {
  @Bindable var store: StoreOf<TextFieldFeature>
    
  var body: some View {
      VStack {
          TextField("Name", text: $store.name)
      }
  }
}

View에서는 이렇게 사용하면 된다!

 

 

'iOS > TCA' 카테고리의 다른 글

[TCA] 04. TCA의 네비게이션 방식에 대해 알아보자.  (0) 2026.01.19
[TCA] 02. Store를 알아보자.  (1) 2026.01.13
[TCA] 1. The Composable Architecture ?  (0) 2025.10.17
'iOS/TCA' 카테고리의 다른 글
  • [TCA] 04. TCA의 네비게이션 방식에 대해 알아보자.
  • [TCA] 02. Store를 알아보자.
  • [TCA] 1. The Composable Architecture ?
여성일
여성일
  • 여성일
    성일노트
    여성일
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • 탭탭 - TapTap N
        • 리팩토링 N
        • 트러블슈팅
        • 개발일지
      • 애플 디벨로퍼 아카데미
        • 챌린지 회고
        • 하루의 날씨
      • Swift Student Challenge 202..
      • AI를 잘쓰는 개발자가 될래요
      • 우리 같이 협업하자
      • ToyProject - 사카마카 (살까말까 고민 ..
      • ToyProject - Book2OnNon (모바..
      • ToyProject - 바꿔조 (환율 계산기)
      • iOS N
        • iOS N
        • Vapor
        • Design Pattern
        • CoreData
        • Tuist
        • RxSwift
        • ReactorKit
        • TCA N
      • Swift
        • Swift 기본기
        • UIkit
        • SwiftUI
      • 원티드 프리온보딩 챌린지 iOS 과정
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.6
    여성일
    [TCA] 03. TCA의 바인딩 방식을 알아보자.
    상단으로

    티스토리툴바