본문 바로가기

iOS Programming

뉴아이패드(2012) 레티나 이미지 메모리 가용성에 관한 고찰

필자는 아직 국내에 출시되지 않은 아이패드 3세대를 미국 현지 친척에게 부탁하여 어렵게 전달받았습니다.

아이패드3 출시 이전 레티나 채용에 대해 필자는 매우 부정적이었습니다.

고해상도 2048x1536을 위한 이미지로딩과 처리를 위해서는 매인메모리가 최소한 2기가는 되어야 한다는게 필자의 생각이었고

메모리를 2기가로 탑재한다고 해도 2기가의 메모리에 전력공급을 위한 배터리 성능 문제와 발열 문제등을 예상하여

아이패드3에는 레티나가 지원되지 않을 것이며, 만일 나온다면 매인메모리는 반드시 2기가 이상이어야 한다는게 필자의 주장이었습니다.

순전히 개발자 입장에서의 주장이었죠.


그러나 막상 아이패드 3세대는 물리적 해상도 2048x1536으로 나왔고 메모리는 아이패드2의 2배인 1기가로 알려졌습니다.

필자는 궁금했습니다.

과연 1기가의 메모리로 고해상도 이미지 처리와 운용이 멀티태스킹(스위칭)과 함께 아이패드2 보다 쾌적한 환경을 제공할까?

만일 그렇다먄 애플은 기술적으로 어떻게 해결했을까?

gpu에 자체 이미지 디코딩 기능을 넣었을까?

획기적인 메모리 스왑 기술이 들어 갔을까? 


결론은...

아이패드3의 레티나 채용으로 인해 예상되는 메모리 부족(?)현상에 애플은 기술적으로 그 어떤 해결책도 넣지 않았습니다.

지금부터 제가 나름대로 실험한 내용을 소개하고자 합니다.

무척이나 제한적인 실험이라 100% 정확하지 않을 수도 있음을 먼저 말씀드립니다.



1. 사전 인지 사항

아이패드1은 물리해상도 1024x768로서 매인메모리는 256MB입니다. 

아이패드2는 물리해상도 1024x768로서 매인메모리는 512MB입니다. 

아이패드3는 물리해상도 2048x1536으로 매인메모리는 1GB입니다. 

1픽셀의 표시를 위해서는 RGBA(Red/Green/Blue/Alpha)값 각 1바이트씩 4바이트의 메모리가 요구됩니다.


2. 실험의 목적

본 실험은 이미지가 메모리에 어떻게 로드되고 관리되는지 알아보기 위한 목적입니다.

그리고 이미지 로딩을 계속하여 언제 메모리 부족이 발생하여 앱이 강제종료 되는지 알아보기 위한 실험입니다.

실제 개발에서는 출력될 이미지 크기에 맞게 리사이징 하거나 임시저장과 복원을 통한 스와핑등 코드 최적화를 통해 메모리 관리를 하지 이렇게 코딩하는 개발자는 아무도 없을 것입니다. ^^


3. 준비 사항

먼저 아래의 그림처럼 하나의 뷰컨트롤러 기반의 간단한 앱 프로젝트를 생성하여 이미지 로드 버튼을 올리고 이미지가 몇 번 로드 되었는지 나타내는 레이블을 하나 만들었습니다. 버튼을 클릭하면 이미지를 로드하는데 1024x768의 test.png 파일과 2048x1536 test@2x.png 파일 리소스가 로딩되도록 하였습니다.




"Load Image" 버튼을 클릭하면 아래의 코드가 실행되도록 하였습니다.

NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"png"];

UIImage *windowImage = [[[UIImage alloc] initWithContentsOfFile:path] autorelease];

[capturedImages addObject:windowImage];

captureCount.text = [NSString stringWithFormat:@"%d times loaded.", [capturedImages count]];

UIImageView *iv = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)] autorelease];

iv.contentMode = UIViewContentModeScaleAspectFill;

iv.image = windowImage;

[self.view addSubview:iv];


여기서 imageNamed 메서드 대신 initWithContentsOfFile을 사용한 이유는 imageNamed로 동일한 이미지 리소스를 로딩할 경우 새로운 메모리를 생성하지 않고 처음에 로딩된 기존 메모리영역을 그대로 이용하기 때문입니다.


그리고 앱의 메모리 현황을 보기 위해 Instruments를 이용하였습니다.



파란색으로 선택된 앱이 실험으로 사용된 앱이며 Real Mem 항목이 해당 앱이 사용하고 있는 메모리량을 표시하는 곳입니다.




4. 아이패드1 에서의 실험


아이패드1에서는 1024x768 크기의 test.png 이미지가 로드됩니다.

아래의 그림은 이미지가 하나씩 로드될 때 마다 메모리량을 나타낸 것입니다.




위의 그림에서 알 수 있듯이 실험 앱의 메모리 용량이 4메가 -> 7메가-> 10메가 각 3메가씩 늘어남을 알 수 있습니다.

이는 한 이미지의 RAW 데이터 용량인 1024x768x4 = 3메가 라는 용량과 거의 일치합니다.

이렇게 이미지를 하나씩 로드를 하니 40번째 이미지가 로드될 때 메모리 부족으로 앱이 강제 종료되었습니다.

3메가 x 40 = 120메가 정도로서 iOS 5.1과 필수 기본 앱들이 차지하고 있는 용량등을 합산하면 

알려진대로 여유메모리의 2~30%정도가 남겨진 상태에서 앱이 강제종료 되는 것입니다.



5. 아이패드3에서의 실험


아이패드3에서는 2048x1536 크기의 test@2x.png 레티나 이미지가 자동으로 로드됩니다.

아래의 그림은 이미지가 하나씩 로드될 때 마다 메모리량을 표시를 나타낸 것입니다.



위의 그림에서 알 수 있듯이 아이패드3 실험 앱의 메모리 용량이 4메가 -> 16메가-> 28메가 각 12메가씩 늘어남을 알 수 있습니다.

이는 한 이미지의 RAW 데이터 용량인 2048x1536x4 = 12메가 라는 용량과 거의 일치합니다.

이렇게 이미지를 하나씩 로드를 하니 48번째 이미지가 로드될 때 메모리 부족으로 앱이 강제 종료되었습니다.

12메가 x 48 = 576메가 정도로서 iOS 5.1과 필수 기본 앱들이 차지하고 있는 용량을 합산하면 

알려진대로 여유메모리의 2~30%정도가 남겨진 상태에서 앱이 강제종료 되는 것입니다.



6. 아이패드2에서의 실험

애석하게도 필자에겐 아이패드2가 없어서 아이패드2로는 실험을 진행하지 못했습니다.
그러나 위의 실험결과로 추론하면 비레티나이면서 메모리가 아이패드1의 두 배인 512메가인 점을 감안하면
아이패드1에서 메모리 부족으로 강제종료된 40개를 훨씬넘어 그 두 배 80장  100장까지도 이미지 로드가 가능할 것으로 예상됩니다.



7. 결론

메모리 가용성만 따진다면 아이패드2가 월등합니다.
그만큼 이미지를 많이 쓰는 뷰를 많이 올려도 메모리 부족 상황이 거의 없을 것으로 예상되며
그만큼 앱간의 멀티태스킹과 멀티스위칭도 원활할 것으로 생각됩니다.
필자는 2년 가까이 아이패드1을 이용하면서 메모리 부족을 느낀 경우가 한 두 번이 아니었습니다.
이번에 출시된 아이패드 3세대는 메모리가 아이패드1의 4배인 1기가이지만
레티나의 채용으로 메모리 가용성에서 아이패드1과 비슷한 상황이거나 아주 약간 나아진 상황입니다.
결국...
안정성 있는 앱을 개발하기 위해서는, 그리고 다른 앱들과의 멀티스위칭을 효율적으로 발휘하기 위해서는
메모리 관리에 아주 많은 신경을 써야 하고
디자이너도 통이미지로만 해결할 것이 아니라 개발자와의 협의를 통해
이미지 사용을 최소화하거나 stretchableImageWithLeftCapWidth:topCapHeight: (iOS 5.0 이상에서는 resizableImageWithCapInsets:(UIEdgeInsets)capInsets) 를 적절히 이용하여 최소화된 이미지로 최적화를 진행해야 할 것 같습니다.
코드의 최적화는 결코 쉬운 작업이 아닙니다.
그만큼 기간과 비용이 많이 소모되는 작업입니다.
어쩔 수 없는 개발자의 몫이지만 기획자와 프로젝트 관리자도 이런 점을 잘 이해하는 상태에서 프로젝트를 진행해야 할 것입니다.
사담이지만,
아이패드3가 나오기 전에 필자는 트윗을 통해
 "만일 아이패드3가 레티나를 달고 메모리 1기가 이하로 나온다면 아이패드3를 위한 레티나앱 개발 단가를 두 배로 올리겠다"는 농담아닌 농담을 한 적이 있습니다. ^^
끝으로 개발자들은 아이패드2 보다는
아이패드1과 아이패드3를 개발장비로 선택할 것을 권장합니다.
특히 아이패드1은 정말 코드 최적화를 하기에 정말 좋은 테스트 기기입니다. ^^

긴 글 끝까지 읽어 주셔서 감사합니다. ^^



실험 후기

실험 중간에 필자의 실수로 아이패드3 레티나 이미지 로딩시 12메가가 아닌 3메가씩 늘어나는 것을 목격한 적이 있습니다.
순간....
"그러면 그렇지... 역시 애플이다....  메모리에 Raw데이터가 아닌 인코딩된 파일을 그대로 올리고 GPU에서 이를 실시간 디코딩하여 처리하는구나.... " 라고 기뻤습니다.
그러나 그것은 필자의 실수로 인한 결과 오류였습니다. ㅠㅠ
좋았다가 말았습니다.

전 역시 게으른 개발자인가 봅니다. ㅠㅠ