Android 앱에서 비디오 재생, 카메라 프리뷰, 게임 그래픽 등 고성능 렌더링이 필요한 화면을 구현할 때 SurfaceView와 TextureView 중 어떤 것을 선택해야 할지 고민하게 된다. 두 View 모두 비슷한 목적으로 사용되지만, 내부 동작 방식과 특성이 상당히 다르다. 이 글에서는 각 View의 특징과 차이점을 살펴보고, 상황에 따른 선택 기준을 정리해보고자 한다.
SurfaceView는 Android 1.0부터 존재해온 View로, 일반적인 View 계층과 독립된 별도의 Surface에서 렌더링을 수행한다. 쉽게 비유하자면, 앱 화면(Window)에 구멍을 뚫고 그 뒤에 별도의 레이어를 배치하는 방식이다.
독립적인 렌더링 스레드 사용이 가능하다. SurfaceView는 메인 스레드와 별개로 렌더링을 수행할 수 있어서, UI 스레드에 영향을 주지 않고 고성능 그래픽 작업을 처리할 수 있다.
하드웨어 오버레이를 활용한다. 시스템 컴포지터(SurfaceFlinger)가 직접 합성하기 때문에 GPU 부하가 적고 전력 효율이 좋다.
View 변환이 적용되지 않는다. rotation, scale, alpha 같은 View 속성을 변경해도 SurfaceView에는 반영되지 않는다. 별도의 Window에서 렌더링되기 때문이다.
Z-ordering에 제약이 있다. 기본적으로 앱 Window 뒤에 위치하며, setZOrderOnTop()이나 setZOrderMediaOverlay()를 통해 조정할 수 있지만, 여러 SurfaceView를 겹치는 것은 복잡하다.
TextureView는 Android 4.0(API 14)에서 도입되었으며, SurfaceTexture를 통해 콘텐츠를 일반 View처럼 렌더링한다. View 계층 내에서 하나의 View로 취급되기 때문에 다른 View들과 자연스럽게 어우러진다.
View 계층에 완전히 통합된다. 일반 View처럼 동작하기 때문에 rotation, scale, alpha, translation 등 모든 View 변환이 적용된다.
레이어링이 자유롭다. 다른 View 위에 올리거나, 여러 TextureView를 겹치는 것이 자연스럽다.
getBitmap() 메서드를 제공한다. 현재 렌더링된 프레임을 Bitmap으로 쉽게 캡처할 수 있다.
하드웨어 가속이 필수이다. TextureView는 하드웨어 가속이 활성화된 Window에서만 동작한다. 소프트웨어 렌더링 환경에서는 아무것도 그려지지 않는다.
추가적인 GPU 패스가 필요하다. 콘텐츠가 GPU 텍스처로 변환된 후 View 계층과 함께 합성되기 때문에, SurfaceView보다 전력 소모가 약간 더 크다.
| 항목 | SurfaceView | TextureView |
|---|---|---|
| 도입 시점 | API 1 | API 14 |
| 렌더링 위치 | 별도 Window | View 계층 내부 |
| View 변환 지원 | 불가 | 가능 |
| 하드웨어 가속 필수 | 아니오 | 예 |
| 프레임 캡처 | 복잡함 | getBitmap() 제공 |
| 전력 효율 | 우수 | 상대적으로 높은 소모 |
| DRM 지원 | Secure Surface 지원 | 제한적 |
| 여러 개 겹치기 | 어려움 | 용이 |
전체 화면 비디오 플레이어를 구현할 때 적합하다. View 변환이 필요 없고, 배터리 효율이 중요한 경우 SurfaceView가 최선의 선택이다. ExoPlayer의 기본 설정도 SurfaceView를 권장한다.
게임이나 고성능 그래픽 앱을 개발할 때 유리하다. 별도 스레드에서 렌더링하면서 UI 스레드에 영향을 주지 않아야 하는 경우, 그리고 OpenGL ES를 직접 다루는 경우에 SurfaceView(또는 GLSurfaceView)가 적합하다.
DRM으로 보호된 콘텐츠를 재생할 때 필요하다. 넷플릭스나 왓챠 같은 서비스에서 사용하는 Widevine DRM은 Secure Surface를 요구하는 경우가 많은데, 이는 SurfaceView에서만 지원된다.
배터리 소모를 최소화해야 할 때 고려해야 한다. 장시간 비디오 재생 앱이라면 SurfaceView의 전력 효율 이점이 무시할 수 없는 수준이다.
View에 애니메이션을 적용해야 할 때 필수이다. 비디오나 카메라 프리뷰에 rotation, scale, fade 효과를 주고 싶다면 TextureView를 사용해야 한다. SurfaceView에서는 이런 변환이 동작하지 않는다.
스크롤 컨테이너 내부에서 사용할 때 권장된다. RecyclerView나 ViewPager 안에서 비디오를 재생하는 피드형 UI를 구현할 때, SurfaceView는 스크롤과 동기화 문제가 발생할 수 있다. 인스타그램이나 틱톡 스타일의 피드를 구현한다면 TextureView가 더 안정적이다.
다른 View와 복잡하게 겹쳐야 할 때 적합하다. 비디오 위에 반투명 오버레이를 올리거나, 여러 비디오를 동시에 겹쳐서 보여주는 등의 복잡한 레이아웃에서는 TextureView가 훨씬 다루기 쉽다.
프레임 캡처 기능이 필요할 때 유용하다. 비디오에서 썸네일을 추출하거나, 현재 프레임을 이미지로 저장해야 하는 경우 TextureView의 getBitmap() 메서드를 활용하면 간단하게 구현할 수 있다.
SurfaceView와 TextureView는 각각의 장단점이 명확하다. SurfaceView는 성능과 효율에서 우위를 가지고, TextureView는 유연성과 통합성에서 강점을 보인다. 어떤 것이 더 좋다고 단정 짓기보다는, 구현하려는 기능의 요구사항을 먼저 파악하고 그에 맞는 View를 선택하는 것이 중요하다.
최근에는 Jetpack Compose 환경에서 AndroidView를 통해 이들을 사용하거나, ExoPlayer의 PlayerView가 내부적으로 적절한 View를 선택해주기도 한다. 하지만 커스텀 구현이 필요하거나 성능 튜닝이 필요한 상황에서는 여전히 이 두 View의 차이를 이해하고 있어야 올바른 선택을 할 수 있다.