
Model : 데이터 구조와 비즈니스 로직을 관리합니다. 서버에서 데이터를 가져오거나 로컬 데이터베이스를 사용해 데이터를 유지한다.
View : 데이터를 표시하고, 사용자 상호작용을 처리합니다. SwiftUI를 사용하면 @Published프로퍼티를 이용해 뷰 모델의 데이터를 자동으로 감시하고 업데이트할 수 있습니다.
ViewModel : 뷰 모델은 모델의 데이터를 가공하고, 뷰가 필요로 하는 형식으로 변환하여 전달한다. 뷰와 모델 사이의 중간 역할을 하며, 뷰와의 양방향 바인딩을 통해 뷰가 업데이트 될 수 있도록 합니다.
struct User {
let id: Int
let name: String
}
import Foundation
class UserViewModel {
// 뷰에서 사용자 이름을 표시하기 위한 변수를 옵셔널 클로저로 정의
var onUserNameChanged: ((String) -> Void)?
private var user: User? {
didSet {
// 사용자 정보가 변경되면 클로저를 호출하여 뷰를 업데이트
if let name = user?.name {
onUserNameChanged?(name)
}
}
}
func fetchUser() {
self.user = User(id: 1, name: "Kim")
}
}
import UIKit
class UserViewController: UIViewController {
private let nameLabel = UILabel()
private let fetchButton = UIButton(type: .system)
private let viewModel = UserViewModel()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
// 뷰 모델의 클로저를 설정하여 데이터 변경 시 UI를 업데이트
viewModel.onUserNameChanged = { [weak self] name in
self?.nameLabel.text = name
}
}
private func setupUI() {
view.backgroundColor = .white
nameLabel.text = "User Name"
nameLabel.textAlignment = .center
fetchButton.setTitle("Fetch User", for: .normal)
fetchButton.addTarget(self, action: #selector(fetchUser), for: .touchUpInside)
view.addSubview(nameLabel)
view.addSubview(fetchButton)
// Auto Layout 설정 (예시로 중앙에 배치)
nameLabel.translatesAutoresizingMaskIntoConstraints = false
fetchButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
nameLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
nameLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
fetchButton.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: 20),
fetchButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
}
@objc private func fetchUser() {
viewModel.fetchUser()
}
}

