디자인 패턴을 쓰는 건 유지보수성, 확장성을 확보하려는 목적이 있음
MVVM 패턴 구조로 짜보았고 코드 기반 레이아웃, SnapKit을 활용해서 직관적인 뷰 계층을 구축하려 노력함
MVVM을 도입하면서 먼저 고민한 부분은 데이터 흐름을 어떻게 구성할 것인가. 였음..
특히 BookViewModel이 데이터를 가져온 이후 정보를 BookView에 어떻게 반영할지 헷갈렸음!
ViewModel 내에 onUpdate, onError 클로저를 정의하고 ViewController에서 클로저에 로직을 바인딩하도록 구성
viewModel.onUpdate = { [weak self] in
guard let self = self, let book = self.viewModel.currentBook else { return }
self.updateUI(book)
}
비동기 네트워크 로딩 → 뷰 반영
View, Model의 결합도를 낮춤
UIKit 컴포넌트를 여럿 구성해야 했는데 대부분의 속성이 중복되는 경우가 많았음
이걸 모두 수작업으로 작성할 경우에 가독성, 유지보수성이 떨어질 수 밖에 없음..
커스텀 팩토리 메서드로 반복되는 UI 요소 생성 코드를 모듈화함
func createLabel(font: UIFont, textColor: UIColor, ...) -> UILabel {
...
}
레이아웃 구성 할 땐 선언만 하면 간결하게 컴포넌트를 생성할 수 있음
lazy var authorLabel = createLabel(font: .systemFont(ofSize: 18), textColor: .darkGray)
선언형 구성 방식이랑 비슷함
책 이미지, 출판일, 페이지 수 같은 것들이 동적으로 변경되는 데이터라 뷰 계층이 깨지거나 레이아웃이 어긋날 수 있었음.. 특히 스택뷰를 사용할 때는 콘텐츠 우선순위 설정이 필수
SnapKit을 사용한 Auto Layout 설정 외에도 setContentHuggingPriority, setContentCompressionResistancePriority를 설정했음!
bookImageView.setContentHuggingPriority(.required, for: .horizontal)
textStackView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
동적 텍스트, 이미지가 레이아웃을 흐트러뜨리지 않고 안정적으로 렌더링될 수 있게 하려 노력함..
이미지를 UIImage(named:)으로 불러올 때
JSON 데이터의 순서와 이미지 리소스의 인덱스를 매칭시켜야 했음
근데 인덱스 오프셋이 맞지 않아 이미지가 잘못 표시되는 오류가 발생함
현재 인덱스에 +1을 해서 이미지명을 매칭시킴
bookImageView.image = UIImage(named: "harrypotter\(viewModel.currentIndex + 1)")
ViewModel에서 관리하는 currentIndex를 기반으로 해서 책 데이터, 이미지 간의 연결을 분리하고 유지함
MVVM 구조로 설계하고 뷰 구성의 효율성을 높이는 방법을 실전에서 체득할 수 있었던 것 같음!
특히 SnapKit, 클로저 바인딩, 팩토리 메서드 같은 것들을 조합해서 가독성 좋은 코드와 유지보수가 쉬운 구조를 짜려고 노력했지만 더 .. 노력 .. 해야겠음 ..
continue..) combine / RxSwift 비교
SnapKit도 더 파보고...