본문 바로가기
Swift

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

by mr.conan 2023. 7. 11.
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
반응형