[내일배움캠프 53일차] Ch 3. 앱개발 심화 주차 과제 - Challenge2

NH·2025년 5월 16일

내일배움캠프

목록 보기
53/62
post-thumbnail

1. 무한스크롤 기본 구현

  • scrollViewDidScroll 메서드에서 스크롤 위치를 체크하여 화면 끝에 도달할 경우 추가 데이터를 로드하도록 구현.
  • offsetY + height - contentHeight > threshold 조건을 통해 바닥 근처인지 판단.
  • 중복 호출을 막기 위해 isLoading 플래그를 도입.

2. isLoading은 ViewModel 내부에서만 관리

  • ViewController는 viewModel.fetchPokemonList()만 호출하도록 역할 분리.
  • ViewModel 내에서만 isLoading을 true → false로 전환하며 중복 호출 방지.

3. ViewModel에서 데이터 누적 처리

  • allPokemonList 배열에 포켓몬 데이터를 누적 저장.
  • 새로운 데이터가 도착할 때마다 pokemonListSubject.onNext(allPokemonList) 호출.
  • ViewController에서는 pokemonList = pokemons로 교체만 하도록 수정.
  • 기존 코드에서 append(contentsOf:)를 했던 부분은 이중 누적으로 인한 중복 데이터 발생의 원인이었음.

4. 스크롤을 오래 끌어당길 경우 중복 호출 이슈

  • scrollViewDidScroll이 계속 호출되면서 fetchPokemonList()가 반복 요청되는 문제 발생.
  • 해결: viewModel.isLoading을 활용해 조건 충족 + 아직 로딩 중이 아닐 때만 fetch 호출.
if !viewModel.isLoading {
	viewModel.fetchPokemonList()
}

5. 비동기 이미지 로딩 이슈

  • 셀의 재사용 시, 이전 셀에서 요청한 이미지가 나중에 나타나면서 다른 포켓몬 이미지가 잘못 들어가는 현상 발생.
  • 해결 방법:
    • configure(id:) 내부에서 currentID를 저장하고, 이미지 로딩 완료 시점에 비교
    • 또는 Kingfisher, SDWebImage 같은 이미지 캐싱 라이브러리 사용하여 간편하게 해결

킹피셔 쓰기 전

func configure(id: Int) {

	let urlString = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/\(id).png"
	guard let url = URL(string: urlString) else { return }
        
	DispatchQueue.global().async { [weak self] in
	if let data = try? Data(contentsOf: url) { // 동기 실행이여서 비동기로 실행해야됨, 안그럼 UI가 멈춤
		if let image = UIImage(data: data) {
			DispatchQueue.main.sync { // UI 작업은 메인 스레드가 해야됨
				self?.pokemonImageView.image = image
            }
        }
    }
}

킹피셔 사용

func configure(id: Int) {

	let url = URL(string: "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/\(id).png")
	pokemonImageView.kf.setImage(with: url)
}

완성된 앱 모습!

킹피셔를 적용한 모슴

포켓몬 상세 화면


📚 배운 점 정리

항목내용
ViewModel 책임 분리로딩 상태 및 데이터 누적은 ViewModel에서
무한스크롤 조건offsetY + height - contentHeight > threshold
이미지 셀 이슈 해결currentID로 비교 또는 캐싱 라이브러리 사용
중복 호출 방지isLoading으로 fetch 제어
profile
iOS 개발 블로그

0개의 댓글