Swift

SwiftUI와 Combine을 활용한 TCA 아키텍처 계산기 예제

mr.conan 2023. 7. 11. 13:32
728x90
반응형

안녕하세요! 이번에는 SwiftUI와 Combine을 사용하여 TCA(Typed Redux with Combine) 아키텍처를 활용한 계산기를 만드는 예제 코드를 소개하겠습니다. TCA는 SwiftUI와 Combine을 결합하여 상태 관리와 애플리케이션 로직을 효과적으로 관리할 수 있는 아키텍처 패턴입니다.

 

  1. 프로젝트 설정 먼저 Xcode에서 새로운 SwiftUI 프로젝트를 생성합니다. SwiftUI 및 Combine 프레임워크가 포함되어 있는지 확인하세요.
  2. 필요한 모듈 가져오기 다음과 같은 Combine 및 TCA 관련 모듈을 import 해줍니다.
import SwiftUI
import Combine
import ComposableArchitecture

 

 

상태(State) 정의하기 계산기의 상태를 정의하기 위해 구조체로서의 상태(State)를 만듭니다. 아래와 같이 코드를 작성해주세요.

struct CalculatorState {
    var expression: String = ""
    var result: Double?
}

 

 

액션(Action) 정의하기 계산기에서 사용자 동작을 나타내는 액션(Action)을 정의합니다. 예를 들어, 숫자 입력, 연산자 입력, 계산 등의 액션을 정의할 수 있습니다. 아래는 일부 예시입니다.

enum CalculatorAction {
    case digit(Int)
    case operator(String)
    case calculate
    // 추가적인 액션들을 여기에 추가해주세요.
}

 

 

리듀서(Reducer) 정의하기 리듀서는 현재 상태와 액션을 입력으로 받아 새로운 상태를 반환하는 함수입니다. 아래와 같이 리듀서를 정의해줍니다.

let calculatorReducer = Reducer<CalculatorState, CalculatorAction, Void> { state, action, _ in
    switch action {
    case let .digit(number):
        state.expression.append(String(number))
    case let .operator(op):
        state.expression.append(" \(op) ")
    case .calculate:
        if let result = evaluateExpression(state.expression) {
            state.result = result
        }
    }
    return .none
}

 

 

계산 로직 구현하기 리듀서에서 .calculate 액션이 발생했을 때, 실제 계산을 수행하는 함수를 구현해야 합니다. 아래와 같이 evaluateExpression 함수를 작성해주세요.

func evaluateExpression(_ expression: String) -> Double? {
    let expressionWithoutSpaces = expression.replacingOccurrences(of: " ", with: "")
    
    let expressionToEvaluate = NSExpression(format: expressionWithoutSpaces)
    return expressionToEvaluate.expressionValue(with: nil, context: nil) as? Double
}

 

 

뷰(View) 정의하기 마지막으로 SwiftUI를 사용하여 계산기 인터페이스를 구성하는 뷰를 정의합니다. 뷰에서는 상태와 액션을 연결하여 사용자 입력을 처리하고, 상태를 업데이트합니다. 예시 코드는 아래와 같습니다.

struct CalculatorView: View {
    let store: Store<CalculatorState, CalculatorAction>
    
    var body: some View {
        WithViewStore(store) { viewStore in
            VStack {
                Text(viewStore.expression)
                    .font(.largeTitle)
                    .padding()
                
                HStack {
                    ForEach(0..<10) { number in
                        Button(action: {
                            viewStore.send(.digit(number))
                        }) {
                            Text("\(number)")
                                .font(.title)
                                .frame(width: 80, height: 80)
                                .background(Color.gray)
                                .foregroundColor(.white)
                                .cornerRadius(40)
                        }
                    }
                }
                
                Button(action: {
                    viewStore.send(.calculate)
                }) {
                    Text("계산")
                        .font(.title)
                        .frame(width: 120, height: 80)
                        .background(Color.orange)
                        .foregroundColor(.white)
                        .cornerRadius(40)
                }
                
                if let result = viewStore.result {
                    Text("결과: \(result)")
                        .font(.title)
                        .padding()
                }
            }
        }
    }
}

 

 

뷰 연결하기 마지막으로, 앞에서 정의한 뷰와 리듀서를 연결하여 최종적인 앱을 구성합니다. 아래와 같이 코드를 작성해주세요.

@main
struct CalculatorApp: App {
    var body: some Scene {
        WindowGroup {
            let store = Store(initialState: CalculatorState(),
                              reducer: calculatorReducer,
                              environment: ())
            
            CalculatorView(store: store)
        }
    }
}

 

 

이제 SwiftUI와 Combine을 활용하여 TCA 아키텍처를 사용한 계산기 앱을 만들었습니다. evaluateExpression 함수를 구현하여 사용자의 수식을 계산하고, 결과를 표시할 수 있습니다. 추가적인 기능을 구현하거나 UI를 확장하는 등 원하는 대로 코드를 수정해보세요. 계산기 예제를 통해 TCA 아키텍처의 간결함과 확장성을 경험해보시기 바랍니다.

728x90
반응형