본문 바로가기
Android

Google TV Android 앱 성능 극대화

by CodeDiver 2014. 7. 23.

Google TV Android 앱 성능 극대화


출처: https://developers.google.com/tv/android/articles/supercharge_your_gtv_apps?hl=ko



(하드웨어 가속 및 비동기식 다운로드) 
바야 바나자(Bhavya Vanaja), 크리스챤 커즈크(Christian Kurzke) - Google TV 개발자 관계팀(Developer Relations)

  1. 개요
  2. 하드웨어 가속이 필요한 이유
  3. 하드웨어 가속 및 슬라이드 전환
  4. 알파 애니메이션을 이용한 슬라이드쇼
  5. ExecutorService를 이용한 비동기식 비트맵 다운로드
  6. 빠른 실행을 위한 이미지 캐싱
  7. 알려진 문제
  8. 요약

개요

TV를 시청하고 있으면 누구나 선명하고 수준 높은 그래픽과 부드럽고 자연스러운 장면 간 전환을 기대하기 마련입니다. 이 섹션에서는 멋진 시각 효과를 이용해 모두가 반할 만한 Google TV 앱을 개발할 수 있는 방법에 대해 설명합니다. 또한 유명한 Android 개발자인 로메인 가이(Romain Guy)가 자신의 블로그에서 범용 Android 하드웨어 가속 그래픽에 대해 자세하게 설명한 (Android 3.0 하드웨어 가속) 포스트 기사도 읽어볼 수 있습니다.

하드웨어 가속이 필요한 이유

모든 Google TV 장치는 Android OpenGL ES 2.0 API를 지원합니다. 개발자가 기본 그래픽 프로세서에 직접 액세스 하여 고성능 3D 뷰를 제작할 수 있는 것도 OpenGL ES 2.0 API 덕분입니다. 하지만 강력한 기능을 지원하는 API를 이용하려면 OpenGL과 3D 프로그래밍에 대한 지식도 필요합니다.

Android는 일반 '2D' 그래픽 API도 지원합니다. 이 API는 이미지 등을 표현하거나 ListView를 렌더링 하는 데 매우 유용합니다. 장면 전환이 부드러워 간단한 슬라이드쇼 앱에서부터 아티스트 정보와 커버 아트를 전환하는 뮤직 플레이어에 이르기까지 어떤 앱이든 멋진 시각적 효과를 추가할 수 있습니다. TV는 고해상도 디스플레이(최대 1920 x 1080 픽셀)이기 때문에 전체 화면 전환 시 CPU를 많이 사용하게 되어 화면이 출렁이는 현상이 발생할 수 있습니다.

Google TV Android 3.2(Honeycomb) 소프트웨어 업데이트 이후로는 2D API에서도 Android 애니메이션 프레임워크에 하드웨어 가속 을 사용하여 CPU를 많이 사용하는 그리기 작업에 고성능 OpenGL 엔진을 선택적으로 사용하게 되었습니다.

그 밖에 개발자가 자주 부딪히는 문제 중 한 가지는 서버에서 다수의 썸네일을 로드 할 때 발생합니다. 이 경우에는 AsyncTask 클래스와 같이 편리한 Android API를 사용하면 됩니다. 이번 예제에서는 Java Executor 프레임워크를 사용해 성능을 더욱 높일 수 있는 방법에 대해 소개합니다.

하드웨어 가속 및 슬라이드 전환

하드웨어를 가속할 경우 애니메이션과 스크롤 동작이 부드러워질 뿐만 아니라 전반적인 성능도 향상됩니다. 앱에서 애니메이션을 실행하는 경우, 하드웨어 가속 렌더링을 구현할 수 있으며 그 설정 방법은 다음과 같습니다. 매니페스트의 <application> 요소나 개별 <activity> 요소에서android:hardwareAccelerated = 'true'로 설정합니다. 런타임 시 개별 뷰에 대한 하드웨어 가속을 비활성화할 수도 있습니다. 앱의 일부가 다른 부분보다 그래픽 자원을 많이 사용하거나 전체 앱을 다시 테스트 하고 싶지 않을 경우에는 설정을 세분화하는 것이 바람직합니다.. 다음 코드는 액티비티와 앱 레벨에서 하드웨어 가속을 활성화한 예제입니다.

액티비티 레벨:

<activity android:hardwareAccelerated="true" ... >

앱 레벨:

<application android:hardwareAccelerated="true" ... >

뷰 레벨:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

알파 애니메이션을 이용한 슬라이드쇼

Android에서는 몇 가지 애니메이션 클래스를 정의하여 뷰의 확장, 회전, 이동 또는 페이드인이나 페이드아웃 같은 장면 전환을 쉽게 할 수 있습니다. 아래 예제에서는 오브젝트의 페이드인과 페이드아웃에 일반적으로 사용되는 알파 레벨 애니메이션을 사용했습니다. 오브젝트의 '알파 레벨'은 화면에 드로잉 했을 때 오브젝트의 '투명도'를 나타냅니다. 투명 값의 범위는 1.0(완전 불투명) ~ 0.0(완전 투명)이며 부동 소수점으로 표시합니다.

애니메이션은 XML로 또는 런타임 시 API를 통해 동적으로 정의할 수 있습니다. 다음은 슬라이드쇼 도중 두 이미지 간 페이드인과 페이드아웃의 장면 전환을 표현하기 위한 샘플 코드입니다. 코드는 예제 코드 클래스 SlideShowActivity 메소드 playAnim()에서 확인할 수 있습니다.

AlphaAnimation mFadeOutAnimation = new AlphaAnimation(1.0f, 0.0f); 
mFadeOutAnimation.setStartOffset(3000);
mFadeOutAnimation.setDuration(3000);
mFadeOutAnimation.setFillAfter(false);
mFromImage.startAnimation(mFadeOutAnimation);

위 애니메이션이 완성되면 메소드 onAnimationEnd(..)를 호출하여 다음 이미지를 로드 합니다. 또한 AnimationListener를 사용하여 애니메이션이 종료되는 것을 감지할 수도 있습니다.

다음 이미지를 로드 한 후 애니메이션을 반복합니다. 단, 다음 이미지를 페이드인하려면 AlphaAnimation에서 알파 값을 역순으로 입력해야 합니다.

전체 소스 코드는 여기에서 확인할 수 있습니다.

하드웨어 가속 애니메이션과 기존의 소프트웨어 렌더링 애니메이션의 차이를 시험해보려면 앱 매니페스트에서 'android:HardwareAccelerated' 속성만 변경해주면 됩니다.

ExecutorService를 이용한 비동기식 비트맵 다운로드

비트맵을 다운로드 하는 가장 단순한 방법은 getView에서 HTTP를 연결한 다음 mImageView.setImageBitmap()을 사용해 비트맵을 설정하면 되지만 이미지가 다운로드 될 때까지 UI 스레드가 대기 상태가 되기 때문에 시간이 지연되어 ANR(Application Not Responding) 대화상자가 표시될 수 있습니다. 위의 단순한 이미지 다운로드 방법은 초기 구현 단계에서 종종 사용되기도 하지만 최종 버전에서는 사용하지 않습니다. Android는 우발적인 네트워크 또는 파일시스템 액세스를 찾아주는 메커니즘을 지원하므로 개발 중에 'Strict Mode'를 활성화할 것을 권장합니다. 이 모드를 활성화하면 앱이 UI 스레드에서 네트워크에 액세스 하려고 할 때마다 로그가 기록됩니다.

비트맵을 다운로드 하는 권장 방법은 별도의 스레드에서 Android AsyncTask 또는 Java 동시성 프레임워크 Executor 클래스를 통해 실행하는 것입니다. 비트맵을 동시에 다운로드 할 수 있다는 장점 외에도 비트맵을 로컬에서 캐싱 하여 향후 네트워크 액세스까지 방지함으로써 속도를 더욱 높일 수 있는 장점까지 있습니다.

다음 코드는 5개의 아이템으로 크기가 고정된 스레드 풀(newFixedThreadPool)을 생성하는 예제입니다. 즉, 최대 5개의 이미지를 동시에 다운로드 할 수 있다는 것을 의미합니다. 나머지 다운로드 요청은 모두 지정되지 않은 대기열에 저장됩니다.

ExecutorService  mExecutorService = Executors.newFixedThreadPool(5);

전체 소스 코드는 여기에서 확인할 수 있습니다.

빠른 실행을 위한 이미지 캐싱

아래 예제에서는 사용자가 Picasa 앨범에 다수의 사진을 보유하고 있다고 가정합니다. 사용자가 특정 앨범에 접속할 때, 앱이 다운로드 한 사진을 로컬 스토리지에 캐싱 하기 때문에 매번 모든 이미지를 다운로드 할 필요가 없습니다. 따라서 앱의 성능이 대폭으로 향상되는 것을 느낄 수 있습니다.

Google TV 장치는 항상 지원하지는 않지만 이동식(USB-드라이브) 파일시스템을 지원합니다. 아래 코드 샘플에서는 먼저 외장 드라이브를 이용할 수 있는지 확인한 후, 만약 이용할 수 없다면 앱의 기본 캐시 디렉토리를 사용합니다. 기본 캐시 디렉토리는 용량이 더 작기 때문에 시스템에서 여유 메모리가 필요한 경우에는 자동으로 삭제될 수 있습니다.

if (android.os.Environment.getExternalStorageState().equals(
        android.os.Environment.MEDIA_MOUNTED)) {
    mCacheDir = new File(android.os.Environment.getExternalStorageDirectory(), "List");
} else {
    mCacheDir = context.getCacheDir();
}
if (!mCacheDir.exists())
    mCacheDir.mkdirs();

캐싱의 또 다른 문제점은 사용자가 실제로 페이지 아래로 스크롤 하여 보지도 않을 다수의 이미지를 앱이 미리 로드 하는 경우가 있다는 것입니다.

GridView/ListView에 이미지가 많을 경우에는 사용자가 보지도 않을 다수의 이미지를 다운로드만 하다가 끝날 수도 있습니다. 이 문제를 해결할 수 있는 가장 좋은 방법은 온디맨드 방식으로 필요한 이미지만 별도의 스레드에 로드 한 다음 메인 UI 스레드 내의 ImageView에 배열하는 것입니다.

이 솔루션에 대한 예제는 소스 코드 ImageManager 클래스에서 확인할 수 있습니다.

알려진 문제

2D 드로잉 작업을 위한 Android 하드웨어 가속 방법은 장치의 그래픽 드라이버와 긴밀한 관련이 있는 새로운 기술입니다. 물론 휴대기기와 Google TV 장치 간에는 차이가 있기도 하지만 장치마다 하드웨어가 다르기 때문에 일부 장치에서는 미묘한 버그가 발견되는 경우도 있습니다.

따라서 앱을 실행할 때 하드웨어 가속을 사용하려면, 다른 장치 하드웨어에서도 폭넓게 테스트 한 후 UI 렌더링에 미묘한 버그가 발생하지 않는지 전체적으로 확인해야 합니다. 예를 들어, 일부 인스턴스에서 폰트 크기가 너무 클 경우(60+dps), 텍스트 렌더링 엔진의 메모리가 부족하게 되어 문자가 제대로 또는 아예 렌더링 되지 않는 상황이 발생할 수도 있습니다.

하드웨어 가속이 앱의 성능을 높여주는 것은 분명한 사실이지만 앱을 Google Play 스토어에 게시하기 전에 부작용이 없는지 반드시 테스트 하기 바랍니다.

요약

지금까지 Google TV 앱의 속도를 높일 수 있는 주요 기술 몇 가지를 예제를 통해 살펴보면서 슬라이드쇼에서 하드웨어 가속을 통한 뷰의 전환 방법, 이미지 다운로드 속도를 높이는 방법, 이미지를 로컬 파일시스템에 캐싱 하여 전반적인 앱 성능을 향상시키는 방법에 대해 알아 보았습니다.