TeamCoook / iOSInterviewQuestions

✅ iOS 개발자 기술 면접 대비
18 stars 0 forks source link

[레벨 0] `6주차` 11. iOS 앱의 메모리 사용량 최적화를 위한 방안과 고려 사항에 대해 설명해주세요. #11

Open longlivedrgn opened 4 months ago

longlivedrgn commented 4 months ago
JasonLee0223 commented 4 months ago
메모리 캐싱 기법(예: NSCache, 이미지 캐싱)의 개념과 iOS에서의 구현 방법을 설명해주세요.
[이전 블로그 기재](https://velog.io/@jaonlee0223/iOS-NSCache%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%BA%90%EC%8B%B1)
대용량 데이터(예: 이미지, 비디오) 처리 시 메모리 최적화 방안(예: lazy loading, 썸네일 활용)에 대해 설명해주세요
이미지와 관련된 부분은 NSCache와 같이 이미지 캐싱을 활용하여 해결할 수 있을 것 같습니다. 비디오, 음악과 같은 KB이상의 단위의 데이터들은 Core Data 혹은 SQL Lite등 파일시스템을 활용하여 관리할 수 있을 것 같습니다. 보안과 관련된 데이터의 경우는 가볍게는 UserDefault를 높은 보안성이 요구된다면 KeyChain을 사용하면 좋습니다. 이외의 경우 순환 참조 문제가 발생할 수 있는 코드 구간에 대해서도 주의하면 좋을 것 같습니다.
ohdair commented 4 months ago

블로그 기재

longlivedrgn commented 4 months ago

메모리 캐싱 기법(예: NSCache, 이미지 캐싱)의 개념과 iOS에서의 구현 방법을 설명해주세요.

NSCache

NSMutableDictionary

대용량 데이터(예: 이미지, 비디오) 처리 시 메모리 최적화 방안(예: lazy loading, 썸네일 활용)에 대해 설명해주세요

Lazy loading

soo941226 commented 3 months ago

이번건 아래 두개의 질문의 의도를 잘 모르겠는데요.

제목을 바탕으로 iOS 앱의 메모리 사용량 최적화를 위한 방안과 고려 사항에 대해 설명해주세요에 대해 정리해보겠습니다.

여기서 사용량이라는 말이 두가지 관점이 있을 것 같습니다. 하나는 최대한 적은 인스턴스를 메모리에 올리는 것이고, 하나는 최대한 적게 메모리에 접근하는 것입니다. 그리고 이 둘 사이에 교집합이 존재합니다. 저는 각각의 유형을 나열한 뒤 교집합을 이야기하겠습니다.

최대한 적은 인스턴스를 메모리에 올리기 위해서 제가 당장 생각나는 방법이 두가지 있습니다. 하나는 사용되지 않는 값을 메모리에서 내리는 것이고, 하나는 중복되는 값을 메모리에 올리지 않는 것입니다. 스위프트는 사용이 끝난 인스턴스는 메모리에서 내려가도록 언어레벨에서 기능이 구현되어있습니다. ARC 정도의 고민이 더 필요하지만 크게 어렵진 않습니다. 나아가 중복되는 값을 메모리에 올리지 않기 위해서 내장된 컬렉션 타입에 Copy On Write라는 기법을 적용해놓았습니다. COW는 컬렉션이 참조가 되는 과정에서, 단지 사용만 되고 첨삭이 이루어지지 않는다면, 카피가 아니라 참조가 이루어지게 하여 동일한 요소를 메모리에 반복적으로 올리지 않도록 하는 기법입니다. 이러한 맥락에서 Swift의 컬렉션 컨테이너들은 제가 아는 선에서는 모두 값타입으로 구현이 되어있습니다. 구조적인 관점에서는 상위 계층에 Source of truth가 하나만 존재하도록 설계하고, 하위 계층들에서는 이를 참조하면서 소비만 하는 형태로 작성이 되면 좋겠네요

최대한 적게 메모리에 접근하는 것은, 저는 사실 저희가 고민할 영역은 전혀 아니라고 생각하는데요. 솔직히 잘 모르기도 합니다. 하지만 고민을 해보면, 결국 누가 언제 어떻게 메모리에 접근하는지를 고민해볼 필요가 있겠습니다. CPU와 말단 입력장치들이 메모리에 접근을 할 것 같네요. 그러면 언제 어떻게 접근하는지 고민해볼 필요가 있겠습니다. 다양한 관점에서 표현할 수 있지만 제가 피곤하므로 나이브하게 작성을 하면, 필요할 때,결국 프로그램은 함수로 이루어진다는 점에서, CPU가 우리가 작성한 함수를 메모리에서 찾고, 메모리에 올리고, 실행하는 절차가 필요합니다. 이러한 관점에서 최대한 적게 메모리에 접근하기 위해서는 함수의 단위와 양이 불필요하게 많아지는 것을 경계해야 합니다. 또 각각의 함수에서 사용하는 기능들조차 얼만큼 효율적인지를 고민해볼 필요가 있습니다. 여기서 기능의 목적, 인간이 인지할 수 있는 한계, 컴퓨터의 처리 효율과 같은 부분에서 트레이드 오프가 있을 것 같네요. 기능의 목적은 결국 해야하는 것이니 어쩔 수 없고, 나머지는 결국 저희보다는 시스템 개발자의 영역이라고 생각합니다.

여기서 교집합은, 최대한은 아니고, 가능한 한 메모리에 적게 올리면서 또 가능한 한 적게 접근하는 것입니다. 이럴 때 사용되는 것이 캐싱입니다. 반복적으로 나타나는 값들을 메모리에 유지시키고 이 값들에 접근하는 인터페이스를 가벼운 형태로 구현하는 것인데요. 배열을 사용하기도 하고, 연관배열을 사용하기도 합니다. 따로 컨테이너를 만들 수도 있고요. iOS에서는 보통 연관배열의 한 형태로 NSCache이라는 타입을 사용하게 됩니다.

이때 물리메모리가 비싼 자원이면서, 프로세스마다 한계가 주어지기 때문에, 캐싱을 함으로 인해서 시기적절하게 메인메모리를 비워주는 작업이 필요할 수 있는데요. NSCache는 이러한 작업이 내부적으로 처리가 되어있기는 하나, 오히려 이 때문에 메모리에 무언가가 올라가고 내려가는 작업이 불필요하게 많아질 수 있습니다. NSCache의 옵션을 조정하여 이를 어느 정도 제어할 수는 있으나 결국 메인메모리만으로 캐싱을 하기에는 한계가 존재합니다. 이러한 맥락에서 보조메모리에도 캐싱을 하여 접근속도를 빠르게 하는 방법을 꾀하고는 하는데, 이때 특히 CoreData가 많이 사용됩니다. 쓰면서 갑자기 생각이 난 건데 트렌드에 민감한 사람들은 지금쯤이면 벌써 SwiftData를 쓰고 있을 수도 있겠다 라는 생각이 드네요.