프로그래밍공부(Programming Study)/IOS 개발

Swift에서 View, ViewModel, Service에 대한 개념과 역할

Chann._.y 2024. 10. 17.
728x90

 

1. View, ViewModel, Service란?

View, ViewModel, 그리고 Service는 iOS 앱 개발에서 흔히 사용되는 MVVM 패턴(Model-View-ViewModel)에서 중요한 요소입니다. 이 패턴은 코드의 재사용성유지보수성을 높이기 위해 고안되었습니다.

  • View: 사용자에게 보여지는 UI를 담당하며, 사용자 입력을 받습니다.
  • ViewModel: 비즈니스 로직을 포함하며, View와 Model 사이의 중재 역할을 합니다. View에서 발생한 이벤트를 처리하고, Model의 데이터를 가공하여 View에 전달합니다.
  • Service: 외부 서비스(예: API 호출, 데이터베이스 처리)를 관리하는 계층으로, 데이터를 ViewModel에 제공합니다.

2. MVVM 패턴에서의 View, ViewModel, Service 역할

MVVM 패턴에서는 각 요소가 다음과 같은 역할을 수행합니다:

  • View: 사용자와의 상호작용을 책임지며, UI를 표시합니다. 이 계층은 ViewModel에 의존하여 데이터를 바인딩하고, 사용자 이벤트(예: 버튼 클릭)를 ViewModel에 전달합니다.
  • ViewModel: View와 Model 사이의 중재자로, 데이터 로직을 처리하고 View에 데이터를 전달합니다. Binding을 통해 View의 상태 변화를 반영합니다.
  • Service: 데이터 소스와 관련된 모든 비즈니스 로직과 API 호출, 데이터베이스 연결 등의 작업을 처리합니다. 이 계층은 ViewModel에 의해 호출됩니다.

3. 각 요소의 특징

View

  • UI와 직접적으로 관련된 코드를 포함하며, SwiftUI 또는 UIKit을 사용하여 구성됩니다.
  • ViewModel로부터 데이터를 받아서 화면에 렌더링합니다.
  • 사용자로부터 입력(이벤트)을 받아 ViewModel에 전달합니다.
  • ViewModel과 데이터를 Binding하여 자동으로 업데이트됩니다.

ViewModel

  • 데이터 로직과 UI 로직을 분리하는 중간 계층입니다.
  • View에서 발생하는 이벤트를 받아서 처리하고, 필요한 데이터를 Service로부터 받아서 View에 제공하는 역할을 합니다.
  • View와의 강한 의존성을 최소화하기 위해 설계됩니다.
  • View와는 주로 데이터 바인딩 방식으로 연결됩니다(예: @Published나 Combine의 @Binding을 사용).
  • View의 상태를 관리하고, ObservableObject와 같은 프로퍼티 래퍼를 사용하여 상태 변화를 감지하고 UI에 반영합니다.

Service

  • API 호출 및 네트워크 통신을 담당합니다.
  • 예를 들어, 서버에서 데이터를 가져오거나 로컬 저장소에서 데이터를 관리하는 일을 합니다.
  • ViewModel은 Service로부터 필요한 데이터를 요청하고, 그 결과를 전달받습니다.
  • Alamofire와 같은 네트워크 라이브러리를 사용하여 구현될 수 있으며, 데이터 처리 후 ViewModel에 전달합니다.

 

                +---------------------+
                |      Service         |
                +---------------------+
                         |
                         v
                +---------------------+
                |     ViewModel        |
                +---------------------+
                         |
                         v
                +---------------------+
                |       View           |
                +---------------------+

4. Swift에서의 구현 예시

import SwiftUI
import Combine

// Service: 네트워크 요청을 처리하는 예시
class ApiService {
    func fetchData(completion: @escaping (Result<[String], Error>) -> Void) {
        let url = URL(string: "https://api.example.com/data")!
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            if let data = data, let responseData = try? JSONDecoder().decode([String].self, from: data) {
                completion(.success(responseData))
            } else {
                completion(.failure(NSError(domain: "", code: -1, userInfo: nil)))
            }
        }.resume()
    }
}

// ViewModel: 데이터를 처리하고 View에 전달하는 예시
class MyViewModel: ObservableObject {
    @Published var items: [String] = []
    private var apiService = ApiService()

    func loadData() {
        apiService.fetchData { result in
            DispatchQueue.main.async {
                switch result {
                case .success(let data):
                    self.items = data
                case .failure(let error):
                    print("Error: \(error)")
                }
            }
        }
    }
}

// View: UI를 나타내는 SwiftUI View
struct ContentView: View {
    @StateObject private var viewModel = MyViewModel()

    var body: some View {
        List(viewModel.items, id: \.self) { item in
            Text(item)
        }
        .onAppear {
            viewModel.loadData()
        }
    }
}

이 예시에서는 ApiService가 네트워크 요청을 처리하며, MyViewModel이 이를 받아서 데이터를 가공한 뒤 ContentView에 전달합니다. Swift의 Combine을 활용하여 @Published 프로퍼티를 통해 View와 ViewModel 간의 바인딩이 자동으로 이루어집니다.


5. 장단점 및 사례

장점

  • 모듈화: View, ViewModel, Service로 코드를 분리하면 유지보수성이 향상됩니다.
  • 테스트 용이성: ViewModel을 통해 비즈니스 로직을 처리하므로, 유닛 테스트가 용이합니다.
  • 데이터 바인딩: Combine을 사용한 데이터 바인딩으로 UI와 데이터 상태가 동기화됩니다.

단점

  • 복잡성 증가: 단순한 애플리케이션에서는 과도한 구조로 인해 복잡성이 증가할 수 있습니다.
  • 의존성 관리: ViewModel과 Service 간의 의존성을 적절히 관리하지 않으면 코드가 엉킬 수 있습니다.

사례

MVVM 패턴은 규모가 크고 복잡한 앱, 특히 비동기 처리API 통신이 많은 앱에서 널리 사용됩니다. 예를 들어, News 앱에서 기사 목록을 API로 받아와 표시하고, 사용자가 클릭하면 세부 기사를 보여주는 구조에 적합합니다.

728x90

댓글