[iOS] SwiftUI와 MVVM

2025. 1. 27. 15:07iOS

반응형

SwiftUI는 MVVM (Model-View-ViewModel) 패턴을 자연스럽게 지원하도록 설계되어 있으며, View와 ViewModel 간의 데이터 흐름과 역할 분담을 명확히 정의합니다.


1. SwiftUI View와 ViewModel의 역할

  • SwiftUI View
    • UI를 선언적으로 정의합니다.
    • 상태 변화에 따라 UI가 업데이트됩니다.
    • 데이터와 로직에 대한 의존성이 없으며, UI 렌더링에만 집중합니다.
  • ViewModel
    • 비즈니스 로직과 상태 관리를 담당합니다.
    • View에서 사용하는 데이터를 준비하거나 변환합니다.
    • @Published 프로퍼티를 통해 View에 상태 변화를 알립니다.
    • Model과 통신하거나, API 호출, 데이터 처리 등의 작업을 수행합니다.

2. SwiftUI와 ViewModel의 연결

SwiftUI와 ViewModel은 바인딩을 통해 연결됩니다. 이 과정에서 ObservableObject@StateObject, @ObservedObject, @Binding 같은 속성 래퍼가 사용됩니다.

1) ViewModel 설정

ViewModel은 ObservableObject 프로토콜을 채택해야 합니다. 이 프로토콜은 데이터 변경 사항을 관찰할 수 있도록 설정합니다.

import SwiftUI
import Combine

class MyViewModel: ObservableObject {
    @Published var text: String = "Hello, SwiftUI!"
    
    func updateText() {
        text = "Text Updated!"
    }
}

2) View와 ViewModel 연결

View에서는 ViewModel 인스턴스를 @StateObject 또는 @ObservedObject로 선언합니다.

  • @StateObject: View의 초기화 시점에 ViewModel을 생성하고 소유합니다.
  • @ObservedObject: 이미 생성된 ViewModel을 외부에서 주입받아 사용합니다.
struct ContentView: View {
    @StateObject private var viewModel = MyViewModel()
    
    var body: some View {
        VStack {
            Text(viewModel.text) // ViewModel의 text 값을 표시
                .padding()
            
            Button("Update Text") {
                viewModel.updateText() // ViewModel의 메서드 호출
            }
        }
    }
}

3) 부모 View에서 ViewModel 주입

부모 View에서 생성한 ViewModel을 하위 View로 전달하려면 @ObservedObject를 사용합니다.

struct ParentView: View {
    @StateObject private var viewModel = MyViewModel()
    
    var body: some View {
        ChildView(viewModel: viewModel)
    }
}

struct ChildView: View {
    @ObservedObject var viewModel: MyViewModel
    
    var body: some View {
        Text(viewModel.text)
    }
}

3. View와 ViewModel의 데이터 흐름

  • ViewModel → View
    • @Published로 선언된 프로퍼티 값이 변경되면 SwiftUI의 View는 자동으로 새로 고침됩니다.
  • View → ViewModel
    • 사용자 입력 이벤트(버튼 클릭, 텍스트 필드 등)를 통해 ViewModel의 메서드나 속성을 업데이트합니다.
struct ContentView: View {
    @StateObject private var viewModel = MyViewModel()
    
    var body: some View {
        TextField("Enter text", text: $viewModel.text)
            .padding()
    }
}

4. MVVM의 장점

  • 분리된 책임: UI 로직(View)과 비즈니스 로직(ViewModel)이 분리됩니다.
  • 테스트 가능성: ViewModel은 View와 독립적이므로 테스트가 쉽습니다.
  • 재사용성: ViewModel은 여러 View에서 재사용이 가능합니다.
  • 반응형 프로그래밍: SwiftUI의 데이터 흐름과 Combine을 활용해 상태 변경을 간단하게 처리할 수 있습니다.

SwiftUI와 ViewModel은 MVVM 아키텍처를 손쉽게 구현할 수 있는 조합으로, 선언형 UI와 데이터 바인딩을 통해 더 깨끗하고 유지 보수 가능한 코드를 작성할 수 있게 도와줍니다. 😊

반응형