관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 9. Memory Deep Dive - 백그라운드에서 메모리 최적화하는 방법 본문

iOS 응용 (swift)

[iOS - swift] 9. Memory Deep Dive - 백그라운드에서 메모리 최적화하는 방법

jake-kim 2023. 12. 16. 01:57

* 가장 기초) iOS 메모리 기초 개념 - virtual memory, dirty memory, clean memory, compressed memory, swapped memory 이해하기 포스팅 글

 

1. Memory Deep Dive - iOS 메모리 운영체제 기초 (가상 메모리, 페이징, clean memory, dirty memory, compressed memory)

2. Memory Deep Dive - Memory를 줄여야 하는 이유 (+ 앱 메모리 사용량 아는 방법)

3. Memory Deep Dive - Memory Footprint (페이징, Compressed 메모리)

4. Memory Deep Dive - Memory Footprint 프로파일링 방법 (Allocation, Leaks, VM Tracker, Virtual memory trace)

5. Memory Deep Dive - Memory Footprint 프로파일링 방법 (2) (Xcode Memory Debugger, Memory Graph, Memgraph)

6. Memory Deep Dive - Memory Footprint 프로파일링 방법 (3) (vmmap, leaks, heap, malloc_history)

7. Memory Deep Dive - 이미지 로드 매커니즘, 이미지 핸들링 최적화 (UIGraphicsBeginImageContextWithOptions, UIGraphicsImageRenderer)

8. Memory Deep Dive - 이미지 리사이징, 이미지 다운 샘플링 (ImageIO, ImageSource)

9. Memory Deep Dive - 백그라운드에서 메모리 최적화하는 방법

복습) 앱 Memory를 줄이면 얻을 수 있는 것들

  • 앱이 빠르게 실행됨 (launch faster)
  • 시스템 성능이 증가 (system performance)
  • 자기 자신의 앱은 물론이고, 다른 앱들까지 메모리에 더 오래 유지되게함
    • 앱을 백그라운드에 놓았을때 메모리를 많이 사용하면 자동으로 앱이 종료되는데, 만약 A앱의 메모리 사용량이 높으면 A앱 뿐만이 아닌 다른 앱도 메모리에서 내릴 수 있다는 점

이미지 처리를 백그라운드에서 최적화하는 방법

  • 이미지가 띄워져 있는 상태에서 앱 사용 중에 백그라운드로 이동하는 경우 (다른 앱의 push 탭, 홈 버튼 탭 등...), 그 이미지는 메모리에 계속 적재되어 있음

(Xcode에서 memory guage로 확인했을때, 앱이 background로 내려가도 memory가 유지되는 것을 확인)

백그라운드에서의 메모리 최적화

  • 백그라운드에 내려간다면 이미지는 사용자에게 보여지지 않지만 메모리에 남아 있으므로 큰 이미지의 경우 unload하는 처리가 필요
  • 앱 라이프 사이클에 따라 background와 foreground 시점을 파악하여 처리하기
  • 뷰 라이프 사이클 시점에 파악하여 처리하기
    • viewWillAppear
    • viewDidDisappear

ex) background, foreground 관련 예제 코드

func bind() {
    NotificationCenter.default.addObserver(
        forName: UIApplication.willEnterForegroundNotification,
        object: nil,
        queue: .main
    ) { [weak self] (note) in
        print("foreground")
        self?.loadImage()
    }
    
    NotificationCenter.default.addObserver(
        forName: UIApplication.didEnterBackgroundNotification,
        object: nil,
        queue: .main
    ) { [weak self] (note) in
        print("background")
        self?.unloadImage()
    }
}
  • 이미지를 load하고 unload하는 방법?
    • load하는것은 UIImage를 UIImageView에 바로 대입 -> 이 행위는 메모리에 이미지가 적재된다는 것을 알 것
    • unload하는것은 UIImageView에 nil을 대입하면됨 -> 메모리에서도 내려감

ex) 고해상도 이미지를 UIImageView에 넣고 foreground, background에서 각각 아래 함수를 호출하도록 하고 확인

func loadImage() {
    imageView.image = UIImage(named: "high_resolution_img")
}

func unloadImage() {
    imageView.image = nil
}

결과) xcode memory guage를 보면 background로 이동할 때 unloadImage가 불리면서 182MB였던 메모리 공간이 18MB로 변화 (약 1/10 감소)

정리

  • 메모리를 감소해주면 사용자 경험에 있어서 좋은 경험을 줄 수 있음 (앱 속도, 시스템 성능 등)
  • 메모리에서 큰 영향을 미치는 이미지 처리가 중요
  • 이미지 데이터를 사용할 때, 관성으로 "imageView.image = 이미지"를 viewDidLoad시점이나 init시점에 수행하는데 이보다는 이미지가 사용자한테 보이기 직전에 image를 사용하고 안보일때는 unload하는 코드가 필요

* 전체 코드: https://github.com/JK0369/ExImageOptimazationBackground

* 참고

- https://developer.apple.com/documentation/uikit/uiapplicationdidenterbackgroundnotification

- https://developer.apple.com/documentation/uikit/uiapplication/1622944-willenterforegroundnotification

- https://developer.apple.com/videos/play/wwdc2018/416/

 

Comments