본문 바로가기
iOS & macOS

Lazy-loading으로 메모리 관리 및 성능 최적화하기

by Bokoo14 2024. 9. 21.

iOS에서 lazy loading은 데이터를 효율적으로 로드하여 성능을 최적화하는 중요한 기법이다.

특히 큰 데이터나 이미지 파일을 처리할 때, 필요한 시점에만 데이터를 로드하는 방식으로 메모리와 성능을 관리할 수 있다.

UITableViewUICollectionView 같은 스크롤뷰 기반의 UI 컴포넌트에서 자주 사용된다.

 

iOS에서 lazy loading은 스크롤 뷰에서 많이 활용되며, 필요할 때 데이터나 이미지를 비동기적으로 로드하여 메모리 관리와 성능 최적화를 할 수 있다. 

1. UITableView 또는 UICollectionView에서 Lazy Loading - UITableView, UICollectionView

UITableView나 UICollectionView에서 lazy loading을 쉽게 구현할 수 있다.

이 컴포넌트들은 스크롤하면서 현재 화면에 보이는 셀에 대해서만 데이터를 로드하기 때문에 효율적인 데이터 로딩이 가능하다.

UITableView에서 Lazy Loading 구현 예시:

import UIKit

class LazyLoadingViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    @IBOutlet weak var tableView: UITableView!
    
    let imageURLs = [
        "https://example.com/image1.jpg",
        "https://example.com/image2.jpg",
        "https://example.com/image3.jpg"
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.dataSource = self
        tableView.delegate = self
    }

    // TableView DataSource 메서드
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return imageURLs.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ImageCell", for: indexPath)
        let imageUrl = imageURLs[indexPath.row]
        
        // Lazy loading으로 이미지 비동기 다운로드
        loadImage(urlString: imageUrl) { image in
            cell.imageView?.image = image
            cell.setNeedsLayout()  // 셀이 다시 레이아웃 되도록 설정
        }

        return cell
    }
    
    // 비동기 이미지 다운로드 함수
    func loadImage(urlString: String, completion: @escaping (UIImage?) -> Void) {
        DispatchQueue.global().async {
            if let url = URL(string: urlString),
               let data = try? Data(contentsOf: url),
               let image = UIImage(data: data) {
                DispatchQueue.main.async {
                    completion(image)
                }
            } else {
                DispatchQueue.main.async {
                    completion(nil)
                }
            }
        }
    }
}

이 코드에서는 비동기 이미지 로딩을 통해 셀이 화면에 나타날 때마다 이미지를 로드하여 성능을 최적화한다.

백그라운드 스레드에서 이미지를 다운로드하고, 완료되면 메인 스레드에서 UI 업데이트를 한다.

2. UIImageView에서 Lazy Loading

이미지 로딩은 특히 큰 이미지 파일을 처리할 때 성능에 영향을 줄 수 있다.

UIImageView에 이미지를 로드할 때, 미리 모든 이미지를 불러오지 않고, 필요할 때마다 로딩하는 방식으로 lazy loading을 구현할 수 있다.

예시:

 
extension UIImageView {
    func loadImage(from url: URL) {
        DispatchQueue.global().async { [weak self] in
            if let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
                DispatchQueue.main.async {
                    self?.image = image
                }
            }
        }
    }
}

3. SwiftUI에서 Lazy Loading - LazyVStack, LazyHStack

SwiftUI에서는 LazyVStack 또는 LazyHStack을 사용하여 스크롤되는 동안 실제로 화면에 나타나는 뷰에 대해서만 로딩을 하도록 할 수 있다.

즉, 스크롤하기 전까지는 뷰가 생성되지 않는다.

공식 문서: https://developer.apple.com/documentation/swiftui/lazyvstack

예시:

import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(0..<1000) { index in
                    Text("Row \(index)")
                }
            }
        }
    }
}

LazyVStack을 사용하면 스크롤 시 필요한 항목만 메모리에 로드하게 되어, 메모리 사용량을 최적화할 수 있다.

 

 

+ 추가

Kingfisher