[성서알리미 회고] ViewModel 역할에 맞게 코드 개선

이건준·2024년 7월 2일
0

기존 성서알리미 ViewModel문제점

final class BoardDetailViewController: BaseViewController, BackButtonHandler {
  
  // MARK: - Property
  
  private let viewModel: BoardDetailViewModelType
  private let boardSeq: Int
  private let categorySeq: Int
  private let writeableAnonymous: Bool
  private let writeableComment: Bool
  
  init(categorySeq: Int, boardSeq: Int, writeableAnonymous: Bool, writeableComment: Bool, viewModel: BoardDetailViewModelType = BoardDetailViewModel()) {
    self.viewModel = viewModel
    self.boardSeq = boardSeq
    self.categorySeq = categorySeq
    self.writeableAnonymous = writeableAnonymous
    self.writeableComment = writeableComment
    super.init(nibName: nil, bundle: nil)
  }
  • 하나의 예시로 게시판 상세화면 코드를 보면은 MVVM아키텍처를 채택함에도 해당 화면관련 상태값을 ViewController가 가지고 처리
  • 익명으로 댓글을 작성할 수 있는지에 대한 상태값인 writeableAnonymous가 단순 UI레이아웃을 구분짓는 용도임에도 ViewController초기화함수에서 처리

위 문제 개선 코드

protocol BoardDetailViewModelType {
	var categorySeq: Int { get }
  	var boardSeq: Int { get }
  	var writeableAnonymous: Bool { get }
  	var writeableComment: Bool { get }
}

/// BoardDetailViewController
viewModel.writeableAnonymous
viewModel.writeableComment
  • 위처럼 게시판상세화면에 대한 ViewModel에서 다음 상태값을 관리해줌으로써 ViewController에서는 ViewModel이 가지고있는 값을 사용만하고 ViewModel내부에서 해당 상태값을 기존 내부 로직을 통해 갱신하여 사용
  • 즉, MVVM아키텍처로써 ViewModel이 가져야 할 의미를 명확히 할 수 있음

ViewModel Output관련 개선한 문제

private var cellModel: [BoardDetailCollectionViewCellModel] = []
  
private var boardModel: [BoardDetailHeaderViewModel] = []

Driver.combineLatest(
	viewModel.boardInfoModel,
    viewModel.boardCommentModel
)
.drive(with: self) { owner, result in
    let (boardInfoModel, boardCommentModel) = result
    owner.boardModel = boardInfoModel
    owner.cellModel = boardCommentModel

    owner.view.hideSkeleton()

    owner.boardDetailCollectionView.reloadData()
}
.disposed(by: disposeBag)
  • 기존 화면에 관련된 데이터바인딩코드를 작성할때 위 코드와 같이 프로퍼티에 데이터모델을 작성하고 viewModel의 Subject를 이용해 바인딩시켰음
  • 허나 MVVM아키텍처를 가짐에도 모델에 대한 데이터를 ViewController에서 가지고있다는 부분이 역할에 맞지않는다고 생각

protocol BoardDetailViewModelType {
	var boardInfoModel: [BoardDetailHeaderViewModel] { get }
    var boardCommentModel: [BoardDetailCollectionViewCellModel] { get }
}

/// UI모델 사용하는 부분
viewModel.boardInfoModel
viewModel.boardCommentModel
  • 기존 ViewController의 UI모델 프로퍼티를 통해 값을 갱신하는것이 아니라 ViewModel에서 관리하는 모델데이터만을 가져와 사용해줌으로써 기존 코드가 훨씬 깔끔해짐
  • MVVM아키텍처에 맞게 오로지 ViewModel에서 데이터를 관리하여 UI에 바인딩시키는 구조를 명확
  • 또한 Subject대신에 배열에 대한 프로퍼티로 변경해줌으로써 subscribe하는 과정을 줄일 수 있었음

0개의 댓글