60fps는 초당 60프레임의 프레임 속도로, 각 프레임이 정확히 16.7ms가 소요되어 시각적으로 부드러운 움직임을 제공합니다. Android Game Optimization Guide에 따르면 안정적인 60 FPS는 모바일 애플리케이션에서 편안한 애니메이션의 최소 표준으로 간주됩니다. 16.7ms는 개발자가 60 FPS를 달성하기 위해 한 프레임을 렌더링하는 데 사용할 수 있는 시간 예산입니다.
핵심 요점
60fps(초당 60프레임, frames per second)는 디스플레이가 1초에 60번 이미지를 갱신하는 프레임 속도 측정값입니다. 인간의 눈은 잔상 효과로 인해 약 50~60Hz에서 개별 프레임을 구분하지 못하게 되며, 따라서 60fps는 대부분의 사용자에게 자연스러운 부드러움의 임계값이 됩니다.
60fps의 각 프레임에는 고정 시간 예산 16.67ms가 있습니다. 이 예산에는 사용자 입력 처리부터 렌더링 및 화면 출력까지 모든 것이 포함됩니다. 물리, 애니메이션, 복잡한 장면 렌더링 등 어떤 작업이 이 한계를 초과하면 프레임 속도는 30fps 이하로 떨어지며, 이는 시각적으로 스터터로 인식됩니다.
모바일 개발에서 60fps는 하드웨어 제약으로 인해 오랫동안 한계점이었습니다. 2017년 이전의 대부분 디스플레이는 60Hz로 작동했습니다. 90Hz 및 120Hz 화면의 등장으로 60fps는 상한 목표가 아닌 하한 표준이 되었습니다. 그러나 UI 애플리케이션, 비디오 및 대부분의 캐주얼 게임에서 60fps는 여전히 성능의 목표 지표로 남아 있습니다.
60Hz는 미국과 일본의 전력망에서 교류 주파수이며, 이는 역사적으로 최초의 NTSC 텔레비전 표준의 주사율을 결정했습니다. PAL 표준은 유럽의 50Hz 전력망으로 인해 50Hz를 사용했습니다. 이러한 역사적 관성이 컴퓨터 모니터와 이후 모바일 디스플레이로 이어졌습니다.
잔상 효과는 자극이 사라진 후에도 약 30~50ms 동안 망막에 이미지를 유지하는 인간 시각의 특성입니다. 60fps에서는 이전 프레임의 잔상이 사라지기 전에 16.7ms마다 새 프레임이 도착하여 연속적인 움직임의 착각을 만들어냅니다. 카디프 대학교(2023) 연구에 따르면 전투기 조종사는 220Hz에서 개별 프레임을 식별할 수 있지만, 일반 사용자의 경우 60Hz와 120Hz의 차이는 30Hz와 60Hz의 차이보다 훨씬 덜 두드러집니다.
Apple은 2007년 첫 iPhone으로 iOS의 표준으로 60fps를 설정했으며 iPhone 13 Pro(2021)까지 유지했습니다. Android는 역사적으로 동일한 표준을 따랐지만, 90Hz(OnePlus 7 Pro, 2019) 및 120Hz(Razer Phone, 2017)를 탑재한 최초의 기기는 더 일찍 등장했습니다. 오늘날 60fps는 애니메이션이 있는 애플리케이션이 App Store 및 Google Play 리뷰를 통과하기 위한 최소 임계값이지만, 공식적인 요구 사항으로 문서화되지는 않았습니다.
FPS 측정은 최적화의 첫 단계입니다. 객관적인 지표 없이는 성능이 어디에서 저하되는지 파악하는 것이 불가능합니다. 모바일 플랫폼은 실시간으로 프레임 속도를 측정하기 위한 내장 프로파일링 도구와 소프트웨어 API를 제공합니다.
Android Studio Profiler와 Xcode Instruments는 FPS 분석을 위한 주요 도구입니다. Android Profiler는 GPU 렌더링 시간, 프레임 속도 및 Jank(드롭된 프레임 수)를 표시합니다. Xcode Instruments에는 Core Animation 템플릿이 포함되어 있어 프레임 속도, 렌더링 시간 및 draw call 수를 표시합니다. 게임 엔진의 경우 Unity Profiler와 Unreal Insights가 모듈별로 상세한 시간 분석을 제공합니다.
// Android — FrameMetrics를 통한 FPS 측정
window.addOnFrameMetricsAvailableListener(
{ _, frameMetrics ->
val duration = frameMetrics[FrameMetrics.TOTAL_DURATION]
val fps = 1000f / (duration / 1_000_000f)
Log.d("FPS", "Frame duration: ${duration / 1_000_000} ms, FPS: $fps")
},
Handler(Looper.getMainLooper())
)
iOS의 CADisplayLink와 Android의 Choreographer는 디스플레이 재생률에 렌더링을 동기화하는 시스템 메커니즘입니다. CADisplayLink는 새 프레임마다 메서드를 호출하여 지연 계산용 타임스탬프를 전달합니다. Android의 Choreographer도 동일한 작업을 수행하지만 입력, 애니메이션, 순회, 렌더링 등 다양한 프레임 단계에 대한 콜백을 지원합니다. 개발자는 Choreographer.FrameCallback을 구독하고 프레임 간 시간을 측정할 수 있습니다.
안정적인 60fps는 어떤 프레임도 16.7ms 예산을 초과하지 않음을 의미합니다. 초당 하나의 긴 프레임이라도 눈에 띄는 스터터를 만듭니다. 최적화는 CPU, GPU 및 메모리의 세 가지 수준으로 나뉩니다. 각각이 병목 현상이 될 수 있습니다.
레이아웃 패스는 Android 및 iOS에서 CPU 시간의 주요 소비자 중 하나입니다. 복잡한 View 계층 구조, 중첩된 ConstraintLayout, 무거운 drawable은 긴 측정 및 레이아웃 체인을 만듭니다. UI 애플리케이션의 경우 평면 View 계층 구조(깊이 3~4단계 이하)를 사용하고, 중첩된 RecyclerView는 ConcatAdapter로 대체하며, iOS의 목록에는 프리페칭이 포함된 compositional layout을 사용하세요.
| 작업 | 일반 시간 | 초과 시 영향 |
|---|---|---|
| 레이아웃 | 1~3ms | 복잡한 화면에서 스터터 |
| 그리기 | 2~8ms | 다시 그리기, 프레임 드롭 |
| GPU 렌더링 | 3~10ms | FPS 절반 감소 |
| GC(가비지 수집) | 2~50ms | 눈에 보이는 미세 스터터 |
오버드로우는 동일한 픽셀이 반복적으로 렌더링되는 것입니다. 각 View 레이어, 배경, 투명 요소 아래의 이미지는 픽셀 연산 수를 증가시킵니다. Android에서는 개발자 옵션의 Debug GPU Overdraw를, iOS에서는 Xcode Debug View Hierarchy를 사용하세요. 불필요한 배경을 제거하고 불투명 플래그를 사용하여 오버드로우를 줄이세요. Android에서는 android:opaque가 있는 @drawable, iOS에서는 UIKit.View의 isOpaque = true를 사용합니다.
드로우 콜은 GPU로 전송되는 렌더링 명령의 수입니다. 최신 모바일 GPU는 60fps에서 프레임당 200~400개의 드로우 콜을 처리합니다. 이 숫자를 초과하면 성능이 저하됩니다. 스프라이트를 텍스처 아틀라스로 결합하고, 배칭을 사용하며, 개별 드로우 콜을 통한 각 요소의 개별 렌더링을 피하세요.
GC 프리즈는 JVM 및 Kotlin 애플리케이션에서 불안정한 FPS의 주요 원인 중 하나입니다. Android의 가비지 수집은 최대 30~50ms가 소요되어 연속으로 2~3개의 프레임이 건너뛰어질 수 있습니다. 애니메이션 루프에서 할당을 피하고, 객체 풀을 사용하며, 메모리를 사전 할당하세요. iOS에서는 ARC로 인해 문제가 덜 심각하지만, 순환 참조와 autorelease pool 오버플로도 미세 스터터를 만듭니다.
게임에서 60fps는 단순한 표준이 아니라 경쟁 우위입니다. Newzoo(2024) 연구에 따르면 60 미만의 불안정한 FPS를 가진 게임은 Google Play에서 40% 더 많은 부정적인 리뷰를 받습니다. Unity와 Unreal Engine은 렌더링 시간 모니터링을 위한 내장 프로파일러를 제공합니다. Unity에서는 Frame Debugger, Unreal에서는 GPU Visualizer가 각 드로우 콜과 셰이더의 정확한 시간을 보여줍니다. 안정적인 60fps는 액션 게임에서 특히 중요하며, 드롭된 프레임 하나가 사용자의 레벨 클리어 실패로 이어질 수 있습니다.
90Hz 및 120Hz 디스플레이는 목표 성능 기준을 변화시키고 있습니다. ProMotion 기기에서 실행되는 애플리케이션의 목표 FPS는 120이 될 수 있으며, 프레임 예산은 8.3ms로 줄어듭니다. 이는 특히 드로우 콜과 GPU 렌더링에서 두 배 더 효율적인 코드가 필요합니다.
높은 주사율의 장점은 부드러움뿐만이 아닙니다. 120fps는 인지 가능한 입력 지연을 8~10ms 줄여주며, 이는 게임 및 대화형 애플리케이션에 중요합니다. 그러나 60fps와 120fps의 차이에는 개별적인 접근 방식이 필요합니다. UI 애플리케이션(스크롤, 애니메이션)의 경우 90fps가 부드러움과 전력 소비 사이의 최적의 절충안이 될 수 있습니다. 120프레임/초를 렌더링하면 60프레임/초보다 30~40% 더 많은 전력을 소비하기 때문입니다.
Apple은 선호 프레임 속도를 선택하기 위한 API를 제공합니다: CADisplayLink의 preferredFramesPerSecond. Android는 API 30 이전에는 주사율을 직접 제어할 수 없었지만, Android 12부터 개발자는 WindowManager를 통해 RefreshRate를 설정하고 콘텐츠 유형에 따라 60, 90 또는 120Hz를 요청할 수 있습니다.
자주 묻는 질문
30fps는 각 프레임이 33.3ms 동안 지속되어 스크롤링 및 애니메이션 중 끊김으로 인식되며, 눈이 불연속성을 알아차리게 됩니다. 60fps는 16.7ms마다 프레임을 제공하여 대부분의 사용자의 잔상 임계값 아래에 있습니다.
프로파일러(Android Profiler, Xcode Instruments)를 사용하여 프레임 시간 히스토그램을 확인하세요. 프레임의 90% 이상이 스파이크 없이 16.7ms 이내에 들어오면 FPS가 안정적인 것입니다. 30~50ms까지의 고립된 스파이크는 눈에 띄는 스터터를 만듭니다.
네, 하지만 적극적인 최적화가 필요합니다. 낮은 렌더링 해상도, 단순한 셰이더, 최소한의 드로우 콜, 투명도 및 복잡한 그림자 회피 등이 필요합니다. 저사양 기기에서 테스트하면 실제 성능을 확인할 수 있습니다.
VSync 메커니즘 때문입니다. GPU가 16.7ms 내에 프레임을 완료하지 못하면 VBlank를 놓치고 현재 프레임을 추가로 16.7ms 동안 유지합니다. 사실상 하나의 프레임이 두 번의 재생 주기 동안 표시되며 FPS는 정확히 절반으로 떨어집니다.
네. 단순한 목록 스크롤 및 전환 애니메이션조차 편안한 경험을 위해 60fps가 필요합니다. 사용자는 스와이프 시 끊김을 즉시 알아차리며, 이는 주관적 테스트에서 애플리케이션 평점을 2~3배 낮춥니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.