안드로이드 메모리 관리 톺아보기
사실 지극히 평범한 안드로이드앱을 만든다면,
(별다른 애니메이션이 없고, UI구조가 크게 복잡하지 않으며, REST API를 통한 보통의 데이터를 입출력하는 그런 앱)
CPU, 메모리 프로파일링은 굳이 의미가 없다.
fps가 낮게 나올것도 아니고, out of memory 오류가 발생할 가능성도 별로 없다.
게다가 국내 전용앱이라면 워낙 유저들이 최신형 기기를 쓰고 있어서
CPU, 메모리 최적화에 대한 고민을 하는것보다는, UI, UX를 개선한다거나, 빌드나 테스팅을 좀 더 자동화 한다거나
그런곳에 노력을 쏟기를 권하는바이다.
그런데 해외 유저(동남아나 중국)나 저사양기기 사용자를 핵심타겟에 포함하고 있는 앱이거나
애니메이션이 많이 쓰이는 시각적 효과가 중요한 그런 앱이거나
카메라, 사진이 중심인 그런 앱을 만든다면
메모리 관리를 결코 소홀히 할수가 없다.
메모리가 부족하면 out of memory 같은 exception이 발생하여
사용자가 앱을 사용하는 도중 갑자기 죽는 그런현상이 발생하여 핵심고객층이 불만을 갖고 이탈할수 있기 때문이다.
https://d2.naver.com/helloworld/539525
https://medium.com/marojuns-android/안드로이드에서의-비트맵과-메모리의-상관관계-125308c293b9
안드로이드의 메모리 관련한 한글문서중에서는
이 두개의 포스팅이 각각 2013, 2014년도 글이긴 하지만 지금도 유효하고 매우 귀중한 분석이 담긴글이다.
골치 아픈 메모리의 세계에 발을 본격적으로 담기전에 한번씩 정독을 권한다.
안드로이드에서의 메모리 관리에서 가장 큰 비중을 차지하는것이 바로 비트맵이다.
우리가 카메라로 찍은 사진, 또는 누군가가 업로드한 사진을 앱에서 본다거나 다루거나 할때
프로그래머가 다뤄야할 오브젝트가 바로 비트맵인데 이 비트맵이란놈이 용량이 매우 크다.
사실 뭐 간단하게 생각해서 대충 뭐 3000X2000 이런해상도 사진이 해봤자 4MB 정도 나오는데 요즘 폰 메모리가 4GB는 훌쩍넘으니
뭐 그렇게 고민될거 있나? 라고 생각할수도 있겠지만
사실상 우리의 폰이나 피씨에 저장되어있는 사진 파일들은
각각 jpg, png와 같은 압축포맷으로 압축된형태의 파일이라서 그정도 용량이 나오는거고,
실제로 폰에서 비트맵형태로 옮겨질때는 30메가도 훌쩍넘을만큼 메모리 공간을 차지하게 된다.
그리고 폰의 스펙에 메모리가 4GB라고 나와있다고해서,
하나의 앱이 그 4GB의 메모리를 다 사용할수도 없고
하나의 앱이 메모리 문제를 일으켜도 전체의 시스템에 무리를 주지 않는 정도의 limit가 설정되어있다.
그럼 비트맵을 어떻게 관리하면 좋을까?
1. recycle()을 명시적으로
bitmap의 recycle 문제는 위에 링크한 두개의 한글문서에서 워낙 자세하고도 훌륭하게 설명하고 있다.
다시한번 간추려 설명하자면
bitmap을 단순히 나머지 로직에서 사용하지 않는다고해서 가비지컬렉터가 곧바로 비트맵을 회수해가지 않는다.
가비지컬렉터가 더이상 사용하지 않는 비트맵을 회수해갈수 있도록 명시적으로 bitmap의 recycle함수를 호출해야한다.
2. glide, picasso, fresco 같은 라이브러리를 사용해라
Note: There are several libraries that follow best practices for loading images. You can use these libraries in your app to load images in the most optimized manner. We recommend the Glide library, which loads and displays images as quickly and smoothly as possible. Other popular image loading libraries include Picasso from Square and Fresco from Facebook. These libraries simplify most of the complex tasks associated with bitmaps and other types of images on Android.
https://developer.android.com/topic/performance/graphics/
안드로이드 공식문서에 비트맵과 관련된 팁을 다루는 문서 최상단에는 위와 같은 노트가 적혀있다.
구글에서 제시하는 비트맵 다루기 팁은
적절하게 캐싱하기, 화면에 표시될 크기에 맞춰 비트맵을 다운샘플링하여 로드하기 이정도의 팁을 제안하고 있는데
이런 기능들을 이미 glide, picasso, fresco 같은 라이브러리가 다 구현해놓았으니,
간단하게 이러한 라이브러리들을 사용하라고 권장하고 있다.
그리고 사실 그게 맞다.
캐싱이랑, 비트맵 다운샘플링이나 기타 효율적인 부가 팁들을 내가 일일이 코드로 구현하는 것보다,
이미 잘만들어진 라이브러리를 쓰는것이 정신건강뿐만아니라 모든 면에서 낫다.
3. largeHeap
android manifest 파일의 application 항목의 속성으로 boolean 값으로 설정하는 largeHeap 이 이란것이 있다.
명시적 언급이 없는 경우 디폴트값이 false 이다.
안드로이드 메모리는 여러개의 영역으로 구분되는데 그중에 쉽게 설명하면 우리가 작성한 코드에서 사용하는 메모리를 담는 heap이라는 영역이 있다.(자세한건 위에 링크한 한글문서를 참고하면 좋다)
android memory 관련한 문제를 구글링하다보면 stackoverflow 를 비롯하여 많은 곳에서 "largeHeap을 true로 설정하세요" 라는 답변이 주를 이룬다.
이 값에 대해서 안드로이드 개발자 문서를 살펴보면
https://developer.android.com/guide/topics/manifest/application-element
android:largeHeap
Whether your application's processes should be created with a large Dalvik heap. This applies to all processes created for the application. It only applies to the first application loaded into a process; if you're using a shared user ID to allow multiple applications to use a process, they all must use this option consistently or they will have unpredictable results.
Most apps should not need this and should instead focus on reducing their overall memory usage for improved performance. Enabling this also does not guarantee a fixed increase in available memory, because some devices are constrained by their total available memory.
큰 dalvik heap 을 생성하고, 대부분의 앱에서는 이것이 필요 없으니 메모리 사용량을 줄이는것에 초점을 맞추라고나와있긴하다.
그래서 나도 처음에는 largeHeap을 true로 설정해서 메모리 문제를 피해가는것은
뭔가 꼼수로 일을 처리하는것 같아서 프로그래머로서 찜찜하니
이 값을 사용하지 않고 메모리를 최대한 줄여서 해결해보겠다 라는 진취적인 마인드를 가졌었다.
그런데 실제로 맞딱뜨린 알수없는 브랜드의 안드로이드 저가형 기기들을 보고나서는
지난 날의 무모했던 나를 반성하게 되었다.
메이저브랜드가 아닌 일부 보급형 안드로이드 기종중에서 카메라가 상대적으로 메모리에 비해 좋고 메모리는 다소 적은 기종이 있는데,
이 기종에서 해상도 풀사이즈로 촬영을 한 뒤에 원본 비트맵을 다루려고 하면
largeHeap의 도움없이는 메모리 공간의 부족으로 원본 비트맵을 다룰수가 없었다.
아마도 내 추측이건데 카메라 모듈이 상대적으로 저렴하고, 메모리모듈이 비싸서
홍보용으로 카메라를 일단 더 좋은걸로 집어놓고 메모리는 원가 절감을 시도한거아닐까 라는 생각도 들었다.
참고로 안드로이드 스튜디오 3.0 이상, 그리고 안드로이드 5.0 이상의 디바이스에서는
android profiler라고 하는 전보다 더 향상된 프로파일링 도구를 사용할수 있다.
세상은 나날이 발전하고 있음을 느낀다.