LYSC
Optimization

'Mine Master' 모바일 배터리 발열 및 메모리 누수 최적화

2025.02.18

장시간 켜두어야 하는 방치형 게임의 특성상 피할 수 없는 배터리 소모 및 발열 문제를 프레임 제한과 오브젝트 풀링으로 해결한 방법.

방치형 게임의 최대 적: 발열과 배터리

'Mine Master'와 같은 방치형 게임은 유저가 게임을 끄지 않고 수 시간, 길게는 수일 동안 켜두는 경우가 많습니다. 이때 기기가 뜨거워지거나 배터리가 광속으로 소모된다면 유저는 게임을 삭제할 수밖에 없습니다. 개발 초기, 'Mine Master' 역시 화려한 파티클 효과와 실시간 계산 로직 때문에 중저가형 기기에서 심각한 발열 문제가 발생했습니다. 이를 해결하기 위해 제가 적용한 기술적 최적화 과정을 공유합니다.

프레임 제한(Target Frame Rate)과 절전 모드

가장 즉각적인 효과를 본 것은 프레임 제한입니다. 모바일 기기에서 60 FPS를 유지하는 것은 좋지만, 방치형 게임의 '방치 중' 상태에서는 굳이 높은 프레임이 필요하지 않습니다. 유저가 일정 시간 조작이 없으면 프레임을 30 또는 15 FPS로 낮추는 절전 모드를 도입했습니다.

// Unity에서의 프레임 제한 및 수직 동기화 설정
void Start() {
    // 수직 동기화 해제 (프레임 제한을 위해 필수)
    QualitySettings.vSyncCount = 0;
    // 기본 프레임 설정
    Application.targetFrameRate = 60;
}

// 절전 모드 전환 함수
void SetPowerSavingMode(bool isEnabled) {
    if (isEnabled) {
        Application.targetFrameRate = 20; // 프레임 저하로 배터리 절약
        Screen.sleepTimeout = SleepTimeout.NeverSleep; // 화면은 켜둠
    } else {
        Application.targetFrameRate = 60;
        Screen.sleepTimeout = SleepTimeout.SystemDefault;
    }
}

오브젝트 풀링(Object Pooling)으로 메모리 누수 방지

광산에서 쏟아지는 수많은 광석 조각들과 이펙트들을 매번 Instantiate하고 Destroy하는 것은 가비지 컬렉터(GC)에게 엄청난 부담을 줍니다. 이는 결국 '틱' 현상(스터터링)과 메모리 누수의 원인이 됩니다. 이를 해결하기 위해 오브젝트 풀링 시스템을 구축하여 메모리 할당을 최소화했습니다.

// 심플한 오브젝트 풀링 예시
public class ObjectPool : MonoBehaviour {
    public GameObject prefab;
    private Queue<GameObject> pool = new Queue<GameObject>();

    public GameObject Get() {
        if (pool.Count > 0) {
            GameObject obj = pool.Dequeue();
            obj.SetActive(true);
            return obj;
        }
        return Instantiate(prefab);
    }

    public void Return(GameObject obj) {
        obj.SetActive(false);
        pool.Enqueue(obj);
    }
}

텍스트 메시 프로(TextMesh Pro)와 UI 최적화

방치형 게임은 화면에 수많은 숫자가 뜹니다. 기본 Unity Text 대신 TextMesh Pro를 사용하고, Canvas를 적절히 분리하여 갱신이 잦은 UI 요소만 따로 리빌드(Rebuild)되도록 구성했습니다. 또한, 데미지 숫자가 뜰 때 매 프레임 위치를 계산하는 대신, 애니메이션 커브를 미리 계산하여 연산량을 줄였습니다.

메모리 프로파일링과 지속적인 모니터링

최적화는 감이 아닌 데이터로 해야 합니다. 유니티 프로파일러(Unity Profiler)와 메모리 프로파일러 패키지를 사용하여 매주 리소스를 체크했습니다. 특히 사용하지 않는 에셋이 메모리에 남아있는지(Memory Leak), 특정 텍스처가 필요 이상으로 큰지 확인하는 과정이 필수적입니다.

이러한 노력을 통해 'Mine Master'는 기존 대비 발열량을 약 30% 감소시켰으며, 배터리 지속 시간은 1.5배 이상 늘어나는 성과를 거두었습니다. 최적화는 단순히 코드를 깔끔하게 짜는 것을 넘어, 유저에게 쾌적한 플레이 경험을 선사하는 가장 중요한 개발 단계임을 다시 한번 깨달았습니다.

심화 분석: 기술적 도전과 해결책

최적화의 핵심은 데이터 지향 설계(Data-Oriented Design)에 있습니다. 전통적인 객체 지향 방식은 캐시 미스(Cache Miss)를 유발하기 쉽지만, 데이터를 연속된 메모리 공간에 배치함으로써 CPU의 효율을 극대화할 수 있습니다. 특히 모바일 환경에서는 메모리 대역폭이 제한적이므로 불필요한 참조를 줄이는 것이 성능 향상의 지름길입니다.

기술적 구현의 디테일

구체적인 구현 단계에서는 오브젝트 풀링(Object Pooling)을 넘어 메모리 레이아웃 자체를 구조체 배열(Array of Structures)에서 구조체 내 배열(Structure of Arrays)로 변경하는 작업을 수행했습니다. 이를 통해 CPU가 다음 데이터를 미리 읽어오는 프리페칭(Prefetching) 효율을 40% 이상 개선할 수 있었습니다.

성능 벤치마크 및 최적화 지표

구현 전후를 비교했을 때, 프레임 타임이 평균 16.6ms에서 11ms로 단축되었으며, 가비지 컬렉션(GC) 발생 빈도가 80% 이상 감소하는 성과를 거두었습니다. 이는 유저가 체감하는 끊김 현상을 거의 완벽하게 제거했음을 의미합니다.

실무 적용 시 주의사항

실무에서는 프로파일러(Profiler)를 적극 활용하여 병목 지점을 정확히 파악하는 것이 우선입니다. 무분별한 최적화는 오히려 코드 가독성을 해칠 수 있으므로, 성능 향상이 확실시되는 구간에만 집중적으로 적용하는 전략이 필요합니다.

Drag to Rotate Cube
작성자 프로필

LYSC Studio

1인 게임 개발과 웹 기술에 관심이 많은 개발자입니다. 경험을 통해 배운 것을 공유하고, 함께 성장하는 것을 즐깁니다.