[애니또] ViewController와 View의 분리 - 리팩토링 (1)
앞전에 작성한 글을 보면, UIViewController에서 View를 분리한 과정을 볼 수 있다. Delegate 패턴을 통해 데이터와 액션을 주고 받았다.
DetailWaitView를 MVC패턴에서 MVVM으로 변경하는 과정 중 먼저 한 작업은 네트워크 통신을 통해 방 정보를 불러와서 View에 바인딩하는 작업이었다.
기존의 방식과 크게 달라진 부분은 없지만, 핵심은 Publisher를 사용한 Stream으로 만들었다는 것이다.
이해를 돕기위해 기존 MVC 코드부터 살펴보자.
// 기존 코드
final class DetailWaitViewController: BaseViewController {
private var roomInformation: Room?
override func viewDidLoad() {
super.viewDidLoad()
self.fetchRoomData()
// 생략
}
// MARK: func
private func fetchRoomData() {
self.requestWaitRoomInfo() { [weak self] result in
switch result {
case .success(let room):
DispatchQueue.main.async {
self?.detailWaitView.updateDetailWaitView(room: room)
}
case .failure:
self?.makeAlert(title: TextLiteral.errorAlertTitle,
message: TextLiteral.detailWaitViewControllerLoadDataMessage)
}
}
}
// MARK: network
private func requestWaitRoomInfo(completionHandler: @escaping ((Result<Room, NetworkError>) -> Void)) {
Task {
do {
let data = try await self.detailWaitService.getWaitingRoomInfo(roomId: self.roomIndex.description)
if let roomInfo = data {
self.roomInformation = roomInfo
completionHandler(.success(roomInfo))
}
} catch NetworkError.serverError {
completionHandler(.failure(.serverError))
} catch NetworkError.clientError(let message) {
completionHandler(.failure(.clientError(message: message)))
}
}
}
}
간단하게 핵심은 총 3개다.
위 코드를 보면 ViewDidLoad
단계에서 fetchRoomData()
함수를 실행하고, 불러온 room
데이터를 self?.detailWaitView.updateDetailWaitView(room: room)
해당 뷰에 업데이트 시킨다.
그리고 방 정보를 self.roomInformation = roomInfo
변수에 저장한다.
해당 방 정보를 변수에 저장하는 이유는 초대코드를 복사하는 버튼을 눌렀을 때, 초대코드를 네트워크 통신을 통해 받아오는 것이 아니라 이미 받아왔던 데이터에서 초대 코드를 사용해 복사한다.
guard let invitationCode = self.roomInformation?.invitation?.code else { return }
이 코드 때문에 네트워크 통신으로 받아온 방 정보를 변수에 저장하고 있다.
위의 flow가 기존의 방 정보를 불러와서 View에 연결하는 코드였다.
그렇다면 이젠 MVVM으로 어떻게 변경했을까?
우선 DetailWaitViewModel
을 만들었다.