Engineering
앱실행속도 개선을 위한 최적화 가이드 (2)
2018년 5월 30일
원문에서 보기 ↗스마트폰의 하드웨어적 성능은 날로 높아만 가고 있다. 당연한 얘기같지만 필자가 경험한 게임들은 기기 성능에 따라 실행시간이 대체로 빨라졌었다. 그럼 결론은 간단해 진다. '고객님 기기가 문제였네요. 고성능 폰을 쓰세요'라고 말이다.
실제로 대상기기에서 문제가 많이 발생하거나 실행이 원활하지 않은 기종을 제외하는 경우가 있다. 그렇지만 우리게임에는 저사양폰이지만 대중적인 기종이고 경쟁사 게임이 원활하게 돌아가는 사양이라면 어떻게 할 것인가? 본문에는 언급하지 않았지만 저사양 실행옵션을 제공하는 게임도 있다. 품질과 기기확보간의 트레이드 오프이고 이를 받아들이고 말고는 유저의 몫이다.
기기성능을 최적화로 극복해서 유저는 저사양 고품질로 게임을 즐기고, 개발사는 한명의 유저라도 더 확보하는 상생의 길을 찾고자 하는 것이 본 글을 목적이다. 내용에 비해서 너무 뜻을 크게 부풀려 부담이 되지만, 아는 길도 네비를 켜고 가는 마음으로 조곤히 짚어 보고자 한다.
3. 무엇을, 어떻게, 얼마나 최적화 할 것인가?
실행속도가 상대적으로 빨랐던 App에 대한 인터뷰 내용과 대내외 App 실행속도 개선을 위한 연구사례를 통해 네가지 범주의 개선안을 도출했다.
- 첫 째, 이미지 리소스 최적화다. App 용량과 메모리를 점유하는 주요 요소는 이미리 리소스다. 실행시간 개선을 위한 최적화 우선 대상을 이미지 리소스로 잡고 살짝 파보자.
- 둘 째, Asset bundle 리소스 처리 App 실행속도를 빠르게 하기 위해서는 Asset을 쓰지 말라는 것인가? 그럴 수는 없다. 필자도 서비스에 Asset 패치를 뻔질나게 하고 있다. 어떻게 쓰면 좋을지 고민해 보자.
- 세 째, 이벤트 등 타 시스템 연동 처리 게임만 잘 만들면 된다는 얘기는 ‘교과서로만 공부했어요’라는 말과 같은 것이다. (좋은 서비스를 위해서는 당연히 게임을 잘 만들어야 한다) 홍보와 유저들을 대상으로 이벤트를 제공하는 것이 게임 성공에 무시할 수 없는 영향을 미치는 것은 모두 알고 있는 내용이다. 쾌적한 App 실행을 위한 트레이드 오프도 고려해 보자.
- 네 째, 음원 리소스 및 기타 최적화 크다면 크고, 적다면 적다 할 수 있는 음원 리소스까지 챙겨본다.
그 외 패키징과 거창하지 않은 수준에서 개발방법론까지 훑어 보도록 하겠다.
3.1 실행시간 단축방안 - 이미지 리소스 최적화
왜 이미지가 우선 대상인가, 아래의 표를 보면 Texture2D 용량이 App 사이즈의 가장 많은 부분을 차지하는 것을 알 수 있다.

표안의 App은 Android OS 게임으로 APK크기는 모두 100MB 미만이다.
이미지 리소스를 처리하여 메모리에 올라오는 이미지 사이즈를 줄이고 App용량을 덜어내는 방법으로 이미지 압축과 텍스트 아틀라스 최적화 방안을 사용하고자 한다. 손실압축을 할 경우 이미지 리소스 사이즈는 줄어드나, 품질 저하가 있을 수 있어 게임에 따라서 트레이드 오프 가능한 수준에서 진행해 최적화를 해야 한다. 원본 이미지를 그대로 사용할 경우 Unity3D의 텍스처 크기에 따라서 메모리 낭비가 있을 수 있다. 2의 거듭제공(POT) 크기의 텍스처에 스프라이트 이미지를 올려 사용할 수 있도록 아틀라스로 구성하여 사용하도록 한다.
면적과 메모리의 관계를 보면, 사이즈가 절반이면 용량은 1/4로 줄어든다. 여기에 RGBA 값을 적절히 넣고, 빼거나 색깔 수를 조정하면 보다 크게 용량 이득을 볼 수 있다.
Texture 면적과 메모리 관계: (Width x Height) x (R + G + B + A) 2048 x 2048 => 4MB => 4MB x 32bit(RGBA) => 16MB 1024 x 1024 => 1MB => 1MB x 32bit(RGBA) => 4MB Alpha 값이 필요없는 경우: 4MB x 24bit => 12MB, 1MB x 24bit => 3MB 가로세로 길이가 절반이면 이미지 사이즈는 ¼ 사이즈를 줄이면 한번에 로드되는 용량이 적어 메모리 낭비를 막고 로딩 시간 단축 가능 압축을 통해 다운로드 시간 이득 디스크 용량과 I/O 병목부담 경감
3.1.1 이미지 리소스 최적화 - 압축포맷
OS별 주요 압축방법과 효율, 고려사항에 대한 내용이다. iPhone은 PVRTC 방식, Android는 ETC1이 가장 일반적으로 지원되는 압축방식이다.

※ PVRTC 로딩속도 출처 링크 ※ ETC1 로딩속도 출처 링크
Untiy에서 제공하는 플랫폼별 오버라이드를 위한 텍스처 압축 포맷이라는 가이드가 있다. Unity 가이드의 표현을 빌자면(왈도체 느낌이다),
3D 그래픽스 하드웨어에서는 빠른 텍스처 샘플링을 위해 최적화된 지정된 포맷으로 텍스처를 압축해야 합니다. 각자 사용이 가능한 다양한 플랫폼과 디바이스에는 고유의 독점적인 포맷이 있습니다.
※ 플랫폼별 오버라이드를 위한 텍스처 압축 포맷(Texture compression formats for platform-specific overrides) 링크
플랫폼(OS, WebGL 등)과 디바이스(제품 모델)에 따라 사용하는 압축포맷이 다를 수 있다라는 얘기다.
우리는 스마스폰 App(게임)에 대한 최적화를 논하고 있으니, 플랫폼은 iOS와 Android에 한정하고, 변수는 GPU만 놓고자 한다. GPU별 지원하는 압축포맷이 어떻게 다른지 조금 더 알아보겠다. 위의 표와 같이 iPhone은 PRVTC, Android폰은 ETC를 주로 지원하지만, 모두 그렇지는 않다. 서비스 타겟으로 여기는 디바이스의 GPU를 파악하고 그에 맞춰 리소스 압축포맷을 지정하는 것이 필요하다. 앱에서 설치 기기의 GPU를 확인할 수 있고 분석한 GPU에 맞는 Asset을 내려주도록 처리하는 것을 권장한다. GPU별 압축포맷에 맞는 리소스를 각각의 경로를 통해 배포하도록 분기하면 되겠다.
- 제조사별 GPU와 지원하는 압축방식이다.
| 제조사 | 대표GPU | 압축방식 | 특징 |
|---|---|---|---|
| ARM | Mali | ETC | -ETC1은 거의 모든 Android 기기가 지원 -ETC1은 Alpha가 지원되지 않음 -ETC2는 Alpha 지원 (openGL 3.0부터 가능) |
| Qualcomm | Adreno | ATITC | |
| Imagination | PowerVR | PVRTC | -2^n 크기의 정방형 텍스처만 압축 가능 -이에 해당하지 않을 경우 강제로 2^n 크기로 텍스처 변경 -단, 압축하지 않는 텍스처는 정방형 제한 없음 |
| nvidia | Tegra | DXT | -PC에서 사용된 DXT 방식을 그대로 사용 가능 |
※ 출처: 드라곤준 블로그 링크
- 아래는 스마트폰 기종별 GPU 리스트다.
| Smartphone | GPU model |
|---|---|
| Apple iPhone 7 | PowerVR Series7XT Plus |
| Apple iPhone 7 Plus | PowerVR Series7XT Plus |
| Samsung Galaxy S8 - EMEA | Qualcomm Adreno 540 |
| Samsung Galaxy S8 - USA and China | ARM Mali-G71 MP20 |
| Google Pixel | Qualcomm Adreno 530 |
| Google Pixel XL | Qualcomm Adreno 530 |
| Sony Xperia XZ Premium | Qualcomm Adreno 540 |
| LG G6 | Qualcomm Adreno 530 |
| HTC U11 | Qualcomm Adreno 540 |
| Huawei P10 | ARM Mali-G71 MP8 |
| Xiaomi Mi 6 | Qualcomm Adreno 540 |
| Oneplus 5 | Qualcomm Adreno 540 |
출처: DeviceAtlas
3.1.2 이미지 리소스 최적화 - 압축 대상
압축 방법 중 텍스처 아틀라스를 압축하는 방식과 원본 이미지를 압축하는 두 가지에 대해 알아본다.
- 파일 용량을 크게 줄이고 싶다면 텍스처 아틀라스를 압축해서 사용한다. 원본 이미지로 아틀라스를 생성하고, 아틀라스를 손실압축하는 방식이다.

결과는 눈으로만 봐도 저품질인것을 바로 알 수 있다. 물론 용량도 많이 줄일 수는 있다.

테스트 결과에 따르면 TinyPNG로 Atlas PNG 손실압축 할 경우, 원본 이미지 대비 88% 용량절감이 가능했다.
- 이미지의 품질을 어느정도 유지하는 가운데 용량을 줄이고자 한다면 원본이미지를 압축하는 방식을 사용해 본다. 원본 이미지를 압축하고, Low Quality의 이미지로 아틀라스를 생성한다.

압축 대상을 바꾸었더니 압축률과 품질에 많은 차이가 생겼다. 이미지의 색과 글자가 일부 다른 것은 작업과정 중에 정교하게 비교를 하지 않아서 그런 것이다. 막눈인 필자가 봤을 때는 이전 방식에서의 열화현상을 찾을 수 없었다.

용량은 이득은 TinyPNG로 원본 PNG 손실압축 한 경우 약 28%정도가 되었다.
3.1.3 이미지 리소스 최적화 - 텍스처 아틀라스 최적화
스프라이트 이미지를 조합 가능한 최소 단위로 모아서 텍스처 아틀라스를 제작하여 사용한다. 텍스처는 GPU 안에서 2^n 크기로 저장한다. 아래와 같이 원본 이미지를 텍스처에 올려 사용하려면 메모리 낭비가 있을 수 있다.

텍스처를 효율적으로 사용하기 위해 아틀라스를 만들어서 사용한다.
여기서 용어 몇가지를 잠깐 짚고간다.
- 스프라이트란? (나무위키 등에서 확인)
- 게임 개체의 동작을 표현할 때 사용하는 방법이다. 게임 내에서 일단 움직이면 그 비슷한 것들 도 싸잡아 다 스프라이트라고 부른다.
- 애니메이션 작업의 특성상 스프라이트는 배경과 분리되어 움직이는 물체에 쓰이는 만화적 이미지란 의미로 쓰이고 있다.
- 스프라이트란 아틀라스를 이루는 논리적 단위로서 부품처럼 조합이 가능하거나 혹은 단독으로 의미를 표현 할 수 있는 있는 이미지 단위
- 텍스처란?
- 텍스처란 Material (머티리얼)에 사용되는 이미지를 말하며, 머티리얼이 적용되어 있는 표면에 매핑된다. (언리얼엔진 텍스처: http://api.unrealengine.com/KOR/Engine/Content/Types/Textures/)
- 스프라이트 이미지를 올리는 2^n(POT) 크기의 그림판
- 텍스처 아틀라스
- 여러개의 스프라이트를 텍스처에 모아 놓은 것
스프라이트를 텍스처에 모아서 만드는 것에 대한 작업은 본 글에서는 언급하지 않는다.

텍스처 아틀라스의 개별 이미지를 수정할 경우에도 아틀라스를 다시 만들어야 한다. 가능하다면 스프라이트와 텍스처를 1대1로 구성하는 것을 권장한다. 가능하다면 말이다.
텍스처 아틀라스 최적화를 위한 방법은 여러 가지가 있다. 가이드에 담기에는 내용이 많고 지엽적이니 필요하신 분들은 따로 찾아보기 바란다.
- 아틀라스 최적화라는 측면에서 간략히 살펴보겠다. 완성된 이미지를 각각 텍스처에 올리지 않고, 아래처럼 분리해서 넣는다. 512 x 512 사이즈를 512 x 256으로 줄일 수 있다.

스프라이트 sliced 등의 방법도 활용하면 대칭 이미지를 만들어, 원본 사이즈를 줄이는데 도움이 될 수 있다.

위와 같은 방법으로 최적화를 한 결과, 8Mbytes (2048 x 1024) 사이즈를 4Mbytes (1024 x 1024)로 줄일 수 있었다.

물론 Atlas 최적화에 따른 단점도 있다. 어셋 제작 난이도가 상승하고, 그로 인해 작업 기간이 늘어날 수 있다. 또한 분리하고, 나누는 가운데 스프라이트가 추상화 되어 유지보수 난이도가 상승할 수 있다.
3.2 실행시간 단축방안 - 이벤트 처리
App을 실행하면, 게임에 따라 네다섯 개의 팝업창을 헤치고 게임화면에 접속을 하게 된다. 이런 이벤트들은 유저들에게 플레이 방향을 제시하고 보상을 제공함으로써 리텐션을 유지하고 게임을 흥하게 하는 요소로써 많이 활용되고 있다. 유저 좋고, 개발사 좋은 것임에도 의도치 않게 이벤트창으로 인한 게임접속 스트레스를 주는 경우가 있다. 더러는 무리하게 고퀄의 이미지를 띄우느라 유저에게는 데이터부담과 접속시간 지연의 한 요소가 되기도 한다. 팝업 요소 중 구분이 가능한 것은 lazy loading 처리하여 게임시작 시의 트래픽을 분산/경감하여 진행시간을 단축하는 것을 고려하는 것도 필요하다. 이벤트에 따라서는 시작화면에 바로 띄우는 것 외에 아래처럼 유저들이 필요할 때 찾아볼 수 있도록 하는 것도 고려해볼 필요가 있다.
[JUMANJI : THE MOBILE GAME]
3.3 실행시간 단축방안 - Asset 리소스 처리
리소스를 App에 포함하여 빌드하여 게임 진입 시 Asset 다운로드와 체크 시간에 이득을 볼 수 있다. 리소스 수정이 필요한 경우 신규빌드 배포가 필요하다. 구글 플레이에 출시를 할 때 100MB를 넘기게 되면 확장파일(OBB)의 활용을 고려해 보는 것도 좋다. 역시 Asset을 분리하는 방식이 아니라 리소스 수정이 필요하면 신규 빌드를 릴리즈 해야 한다.
App의 용량과 Asset 활용에 따라 최적화가 필요하다. 그 중 하나가 멀티다운로드 기법을 활용하는 방식이 있겠는데, 여기서는 자세한 방식은 생략한다. 멀티다운로드 솔루션으로 ToastCloud의 스마트다운로더를 활용하면 간단하게 적용이 가능하다.
https://toast.com/service/game/smart_downloader
특정 스테이지에 등장하는 영웅/몬스터 등의 리소스는 스테이지 오픈/진입 시나 해당 캐릭터를 획득할 때 다운로드 하는 것도 많이 사용된다. 한편으로는 Asset bundle로 분리를 하되, App에 포함하여 빌드, 배포를 하고 이후에는 수정여부에 대한 체크와 소규모 Asset만 패치되도록 처리를 하는 경우도 있다.
Asset 다운로드 용량이 많아서 이렇게도 저렇게도 효과를 볼 수 없다면 연출을 통해 더딘감을 덜기도 한다.
[Crusaders Quest]
3.4 실행시간 단축방안 - 음원 및 기타 방안
음원도 사용하기에 따라서 용량과 메모리에 올라가는 사이즈가 다를 수 있다. 동일 음원을 반복사용(효과음)하느냐 BGM으로 사용하느냐에 따라 다르겠다. 고퀄의 서비스를 고려한다면 그에 맞춰 음원 포맷과 사이즈를 확보하는 것을 권한다. App 진입을 위해 절충이 가능한 요소로 본다면 아래의 내용을 참고하여 적절하게 사용하는 것이 좋겠다.
3.4.1 음원 최적화
-
MP3를 주로 사용
-
96kbs정도면 사용자가 듣기에 큰 차이가 느껴지지 않음(작자 기준)
-
꼭 필요하지 않다면 스마트폰게임에서는 Stereo 대신 Mono 사운드를 사용(1/2 사이즈)
-
‘우파루사가’의 경우에는 63kbs사용했고 음질에 문제는 없음 (필자와 주변 유저의 상호주관적 사실)
-
플레이 시간별 용량

3.4.2 패키지 최적화
패키지 최적화도 필요한 요소가 된다.
- 처음부터 모든 리소스를 Scene이나 Prefab에 참조로 걸지 말고 다운로드하거나 런타임 로드할 Asset은 계획적으로 선정하여 별도 관리한다.
- Scene과 prefab은 가능한한 Asset을 공유하지 않는다. 공유하게 되면 패키지에 중복으로 리소스가 포함되어 용량이 증가한다.
- Scene을 분리하여 번들로 묶어서 필요 시에 다운로드해서 사용 (BuildStreamedSceneAssetBundle)/Resources나 /StreamingAssets 디렉토리에 사용하지 않는 Asset이 있으면 삭제한다, 사용하지 않더라도 패키지에 포함된다.
3.5 실행시간 단축방안 - 리소스 최적화 Tip
리소스 최적화팁이라는 제목으로 앞서 얘기한 최적화 요소를 요약해 본다.
- 텍스처 컬러
- 32Bit-> 16Bit로 감소(1/2로 용량감소)
- Texture를 보통 32bit를 사용하지만, 16bit로 줄여도 보통 사용자 눈에 큰 차이가 느껴지지 않음
- 텍스처 사이즈
- 3D Object에 입힐 Texture의 경우 Size를 줄여도 큰 차이가 보이지 않음(UI에 보이는 Texture는 차이가 좀 있음)
- 가로세로를 반으로만 줄여도 ¼로 용량감소
- 배경 이미지
- 게임에 따라 다르지만, 일반적으로 큰 용량을 차지하는 부분.
- 배경은 Alpha가 필요 없(을 수 있)으니, RGB만 사용
- 반복되는 배경이라면 일정크기로 잘라서 패턴화.
- JPEG등의 압축 파일포맷 사용.
- Font 사용
- 국가별로 자기들 언어만 들어있는 Font를 사용하거나 시스템 폰트 사용 권장
- 한국어나 중국어 등이 포함된 Font를 사용하면 용량 증가(normal, Bold포함해서 약 4MB)
- 불필요한 파일 삭제
- C:\Users\NHNEnt\AppData\Local\Unity\Editor\Editor.log 에서 빌드에 어떤 파일들이 용량을 크게 사용하는지 알 수 있음.
- 프로젝트 일정에 최적화 작업 반영
- 기획과 설계 단계부터 최적화에 대한 고려 필요
- 작업 단계 전후에 리소스 최적화를 위한 공유와 확인 일정 반영
4. 최적화 활동을 통한 기대효과
4.1 협업 마인드 제고
위에 작성한(짜집한) 내용을 보면, 내 게임이 어느 날 갑자기 최적화가 되기 어렵다는 것을 알 수 있다. 디자이너가 최적화를 위해 노력하더라도 개발에서 발적화를 하면 아무 소용이 없다. 그 반대도 마찬가지가 되겠다. 최적화를 하려면 App 기획단계부터 이에 대한 고려가 필요하다는 것을 알 수 있다. 안정적이며 쾌적한 App을 만들기 위해서는 구성원들 모두의 관심과 협업이 전제 되어야 한다. 최적화를 위한 업무를 통해 여러 긍정적이 효과를 기대해 본다.
- 실행시간 측정 연례화
- 지속적인 실행시간 모니터를 통한 관심과 관리
- 서비스 중인 App에는 실행시간 증감에 대한 확인
- 신규 App은 기획/설계부터 최적화를 고려하여 진행
- 구성원간 원활한 커뮤니케이션
- 실행시간 개선을 위한 최적화는 프로젝트 구성원 모두의 몫
- 기획자, 서버 개발자, 클라이언트 개발자, 디자이너, 사업담당까지 관심과 의사소통 필요
- 노하우가 아닌 일상 업무
- 최적화는 경험 많은 개발자의 숨겨진 스킬이 아닌, 일상적인 업무
4.2 App 실행시간 개선 효과
당연히 서비스 경쟁력 향상이 우선일 것이다. 쾌적한 실행시간으로 게임 플레이 빈도가 늘어나는 것이 기대된다. 짧은 게임 진입시간으로 고객 이탈가능성도 조금은 낮출 수 있지 않을까 감히 기대해 본다.
글을 마치며
Meet Up에 글을 올리기 전에 동일 컨텐츠로 사내에 선을 보였었다. 첫번째 반응은 대부분의 개발자들이 아는 내용인데 자료가 도움이 되겠느냐는 물음표였다.
당연한 말씀이라고 생각한다. 위의 내용들은 이미 대부분의 게임업계 종사자들이 어느수준으로든 고민하고 연구해 봤을만한 내용이다. 본 자료를 준비하면서 만나본 분들의 공통된 말씀들도 신입이나 전임(대리) 수준에서는 도움이 될(잘 모를 수도 있는) 내용이라는 평가를 받았다. 반면에, 몰라서 못하는 것은 아니지만 여러가지 이유로 충분한 최적화를 못하고 출시하는 경우가 있다는 말씀도 적지않았다. 본 자료가 아는 분들은 아는대로, 몰랐던 분들은 또 그런대로 최적화에 대해 고민해 볼 수 있는 계기가 되기를 바란다.
게임을 개발하면서 저마다의 '입장'이 있다. 중요한 것도 다르고, 품질에 대한 눈높이와 저항선도 다를 것이다. 성공적인 서비스가 모두의 목표라는 것에는 이견이 없을 것이고, 최적화된 깔끔한 App으로 다듬어 진다면 그렇지 못한 경우보다 좀더 성공조건에 가깝다라는 것에도 이견이 없을 것이라고 기대한다.
서두에도 언급했듯이 '하드코어 하지 않게' 작성을 했다. 기획, 사업, 디자인, 개발자 등이 모두 소화할 수 있고 구성원들 간에 최적화를 위한 커뮤니케이션 도구로써의 활용한다면 좀더 넓게 쓰임새를 찾을 수 있을 것으로도 생각한다.