현재 구조
메인콜렉션뷰컨트롤러에서 뷰모델에게 포켓몬 리스트를 요청해 가져와 리스트의 id 값을 셀에게 넘겨주어 셀에서 해당 id를 가지고 셀 뷰모델에게 이미지를 요청
뷰모델
- MainViewControllerModel과 MainViewCellModel이 독립적으로 fetchPokemonData()와 fetchPokemonImage(for:)를 처리하고 있습니다.
이미지 로딩
- 이미지를 개별 셀에서 직접 요청하는 방식입니다. MainViewCell에서 viewModel.fetchPokemonImage(for:) 메서드를 호출하여 이미지를 로드하고, PublishRelay를 사용하여 이미지를 전달합니다.
콜렉션 뷰 셀
- 셀에 데이터를 바인딩할 때 MainViewCell에서 이미지를 로드하고, 셀의 이미지가 업데이트됩니다.
장단점을 생각해보자
장점:
각 셀에 대한 독립적인 로직
- 각 셀에서 자신이 필요한 이미지를 직접 로드하는 방식으로, 각 셀이 독립적으로 이미지를 관리하므로 유연성이 있습니다.
뷰모델의 역할 분담
- MainViewCellModel은 이미지 로딩에 집중하고 있으며, MainViewControllerModel은 포켓몬 데이터를 관리합니다. 역할이 분명하게 분리되어 있습니다.
이미지 캐싱
- 만약 이미지를 캐싱하거나 관리할 필요가 있다면, MainViewCellModel에서 처리하기 용이합니다.
단점
중복된 네트워크 요청
- 만약 여러 셀이 동일한 이미지를 요청할 경우, 네트워크 요청이 중복될 수 있습니다. 이는 효율성을 떨어뜨릴 수 있습니다.
콜렉션 뷰 셀의 비효율성
- 이미지 로딩이 셀 단위에서 이루어지므로, 여러 셀이 화면에 나타날 때마다 이미지 요청이 반복됩니다. 화면을 스크롤할 때 많은 요청이 발생할 수 있습니다.
비즈니스 로직의 분산
- 셀마다 비즈니스 로직이 들어가게 되면, 뷰모델에 비즈니스 로직이 분산되어 관리가 어려워질 수 있습니다.
리팩토링
셀 뷰모델을 제거하고 셀 뷰모델에서 하던 로직을 메인콜렉션뷰 모델로 옮겨 포켓몬 리스트를 가져오고 그 가져온 id 값에 해당하는 이미지를 가져와 뷰에 흐르도록함
뷰모델
- MainViewControllerModel에서 포켓몬 데이터를 로드하고, 이미지를 포함한 모든 데이터를 한 번에 처리합니다. pokemonImagesSubject를 사용하여 포켓몬의 이미지를 관리합니다.
이미지 로딩
- 이미지가 MainViewControllerModel에서 관리되며, 포켓몬 데이터를 로드하면서 동시에 이미지를 가져오는 방식입니다. MainViewCell은 이미지를 뷰모델에서 받아서 표시합니다.
콜렉션 뷰 셀
- MainViewCell에서는 이미지를 pokemonImagesSubject에서 받아서 업데이트합니다.
장단점을 생각해보자
장점:
네트워크 요청 최적화
- 이미지를 한 번에 로드하고, MainViewControllerModel에서 데이터를 관리하므로 네트워크 요청이 중복되지 않습니다. 이미지 로딩은 한 번만 처리되고, 셀은 이미 로드된 이미지를 사용합니다.
비즈니스 로직의 집중화
- 이미지 로딩 로직이 MainViewControllerModel에 집중되어 있어, 뷰모델의 책임이 명확하고 비즈니스 로직이 중앙 집중화됩니다.
성능 최적화
- 이미지는 한 번만 요청되며, 이후에는 이미지 데이터가 딕셔너리에 저장되어 있어 성능 상 이점이 있습니다.
단점
뷰모델의 책임 증가
- 이미지 로딩과 포켓몬 리스트 관리가 모두 MainViewControllerModel에 포함되어 있어 뷰모델의 역할이 다소 복잡해질 수 있습니다. MainViewCell에 대한 로직이 상대적으로 단순해지지만, 뷰모델이 과도하게 많은 책임을 맡게 될 수 있습니다.
셀에서 이미지 처리 로직 없음
- MainViewCell에서 이미지를 로드하는 로직이 없어져서, 셀 자체가 뷰모델에 의존하게 되며, 이를 변경하려면 뷰모델을 수정해야 합니다.
리팩토링한 이유
셀이 재사용될 때 마다 중복적으로 네트워크 요청을 막기 위한 선택....