앱인토스 개발자센터 로고
Skip to content

iOS 최적화

앱인토스 Unity 게임을 iOS 환경에서 최적의 성능으로 실행하기 위한 특화된 최적화 기법과 설정을 제공해요.

1. iOS 성능 특성 이해

iOS vs Android 성능 차이점

🍎 iOS 성능 특성
├── 메모리 관리
│   ├── 더 엄격한 메모리 제한
│   ├── ARC (Automatic Reference Counting)
│   └── 메모리 압박 시 강제 종료
├── GPU 성능  
│   ├── Metal API 최적화
│   ├── 타일 기반 렌더링
│   └── A-시리즈 칩셋 특성
├── 배터리 관리
│   ├── iOS 전력 관리 시스템
│   ├── 백그라운드 앱 제한
│   └── 열 관리 (Thermal Management)
└── 앱 스토어 가이드라인
    ├── 64비트 필수
    ├── 메모리 사용량 제한
    └── 성능 기준 준수

iOS 기기별 성능 분류

c#
public enum iOSDeviceTier
{
    HighEnd,    // iPhone 13+ (A15 Bionic+)
    MidHigh,    // iPhone 11-12 (A13-A14 Bionic)  
    MidRange,   // iPhone X-XS (A11-A12 Bionic)
    LowEnd      // iPhone 8 이하 (A10 이하)
}

public class iOSDeviceDetector : MonoBehaviour
{
    public static iOSDeviceTier GetCurrentDeviceTier()
    {
        #if UNITY_IOS
        string deviceModel = SystemInfo.deviceModel;
        
        // A15+ (iPhone 13+)
        if (deviceModel.Contains("iPhone14") || deviceModel.Contains("iPhone15"))
        {
            return iOSDeviceTier.HighEnd;
        }
        // A13-A14 (iPhone 11-12)
        else if (deviceModel.Contains("iPhone12") || deviceModel.Contains("iPhone13"))
        {
            return iOSDeviceTier.MidHigh;
        }
        // A11-A12 (iPhone X-XS)
        else if (deviceModel.Contains("iPhone10") || deviceModel.Contains("iPhone11"))
        {
            return iOSDeviceTier.MidRange;
        }
        // A10 이하
        else
        {
            return iOSDeviceTier.LowEnd;
        }
        #else
        return iOSDeviceTier.MidRange;
        #endif
    }
}

2. Metal 렌더링 최적화

Metal API 활용

c#
public class iOSMetalOptimizer : MonoBehaviour
{
    [Header("Metal 설정")]
    public bool enableMetalOptimization = true;
    public bool useMetalPerformanceShaders = true;
    public bool enableGPUInstancing = true;
    
    [Header("렌더링 최적화")]
    public bool useTiledRendering = true;
    public bool enableOcclusionCulling = true;
    public int maxRenderTargets = 4;
    
    void Start()
    {
        #if UNITY_IOS
        if (enableMetalOptimization)
        {
            OptimizeForMetal();
        }
        #endif
    }
    
    void OptimizeForMetal()
    {
        // Metal 전용 설정 적용
        if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Metal)
        {
            // GPU 인스턴싱 활성화
            if (enableGPUInstancing)
            {
                EnableGPUInstancing();
            }
            
            // 타일 기반 렌더링 최적화
            if (useTiledRendering)
            {
                OptimizeTiledRendering();
            }
            
            // Metal Performance Shaders 사용
            if (useMetalPerformanceShaders)
            {
                EnableMetalPerformanceShaders();
            }
            
            Debug.Log("iOS Metal 최적화 적용 완료");
        }
    }
    
    void EnableGPUInstancing()
    {
        // GPU 인스턴싱을 통한 드로우콜 감소
        var renderers = FindObjectsOfType<MeshRenderer>();
        
        foreach (var renderer in renderers)
        {
            var materials = renderer.materials;
            foreach (var material in materials)
            {
                if (material.shader.name.Contains("Standard"))
                {
                    material.EnableKeyword("_GPU_INSTANCING");
                }
            }
        }
    }
    
    void OptimizeTiledRendering()
    {
        // iOS 타일 기반 렌더링에 최적화
        QualitySettings.antiAliasing = 0; // MSAA 비활성화 (타일 렌더링과 충돌)
        
        // 렌더 타겟 크기 최적화
        Screen.SetResolution(Screen.width, Screen.height, true);
        
        // 후처리 효과 최적화
        var postProcessVolumes = FindObjectsOfType<UnityEngine.Rendering.PostProcessing.PostProcessVolume>();
        foreach (var volume in postProcessVolumes)
        {
            OptimizePostProcessProfile(volume);
        }
    }
    
    void OptimizePostProcessProfile(UnityEngine.Rendering.PostProcessing.PostProcessVolume volume)
    {
        if (volume.profile == null) return;
        
        var deviceTier = iOSDeviceDetector.GetCurrentDeviceTier();
        
        // 기기 등급에 따른 후처리 설정 조정
        switch (deviceTier)
        {
            case iOSDeviceTier.HighEnd:
                // 고사양: 모든 효과 활성화
                break;
                
            case iOSDeviceTier.MidHigh:
                // 중고사양: 일부 효과 품질 조정
                DisableExpensiveEffects(volume, false);
                break;
                
            case iOSDeviceTier.MidRange:
                // 중사양: 기본 효과만 유지
                DisableExpensiveEffects(volume, true);
                break;
                
            case iOSDeviceTier.LowEnd:
                // 저사양: 후처리 비활성화
                volume.enabled = false;
                break;
        }
    }
    
    void DisableExpensiveEffects(UnityEngine.Rendering.PostProcessing.PostProcessVolume volume, bool aggressive)
    {
        var profile = volume.profile;
        
        // 비용이 높은 효과들 비활성화
        if (profile.TryGetSettings(out UnityEngine.Rendering.PostProcessing.Bloom bloom))
        {
            bloom.enabled.value = !aggressive;
        }
        
        if (profile.TryGetSettings(out UnityEngine.Rendering.PostProcessing.DepthOfField dof))
        {
            dof.enabled.value = false; // iOS에서 성능 영향 큰 효과
        }
        
        if (profile.TryGetSettings(out UnityEngine.Rendering.PostProcessing.MotionBlur motionBlur))
        {
            motionBlur.enabled.value = false;
        }
        
        if (profile.TryGetSettings(out UnityEngine.Rendering.PostProcessing.ScreenSpaceReflections ssr))
        {
            ssr.enabled.value = false;
        }
    }
    
    void EnableMetalPerformanceShaders()
    {
        // Metal Performance Shaders 활용
        // 이미지 처리, 머신러닝 등에 GPU 가속 사용
        Debug.Log("Metal Performance Shaders 활성화");
        
        // 앱인토스에 Metal 최적화 적용 알림
        AppsInToss.ReportOptimizationApplied("metal_performance_shaders", "iOS Metal API 최적화");
    }
}

3. iOS 메모리 관리

ARC 호환 메모리 관리

c#
public class iOSMemoryManager : MonoBehaviour
{
    [Header("iOS 메모리 설정")]
    public long maxMemoryUsageMB = 180; // iOS 권장 제한 (Android보다 낮음)
    public bool enableAutoMemoryCleanup = true;
    public float memoryCheckInterval = 5f;
    
    [Header("메모리 압박 대응")]
    public bool enableMemoryWarningResponse = true;
    public bool autoReduceQualityOnWarning = true;
    
    private long lastMemoryUsage = 0;
    private int memoryWarningCount = 0;
    
    void Start()
    {
        #if UNITY_IOS
        InitializeiOSMemoryManagement();
        #endif
    }
    
    void InitializeiOSMemoryManagement()
    {
        // iOS 메모리 경고 이벤트 등록
        Application.lowMemory += OnLowMemoryWarning;
        
        // 정기적인 메모리 체크
        if (enableAutoMemoryCleanup)
        {
            InvokeRepeating(nameof(CheckMemoryUsage), memoryCheckInterval, memoryCheckInterval);
        }
        
        Debug.Log("iOS 메모리 관리 시스템 초기화");
    }
    
    void CheckMemoryUsage()
    {
        long currentMemory = UnityEngine.Profiling.Profiler.GetTotalAllocatedMemory(false);
        long currentMemoryMB = currentMemory / (1024 * 1024);
        
        // 메모리 사용량 급증 감지
        if (lastMemoryUsage > 0)
        {
            long memoryDelta = currentMemory - lastMemoryUsage;
            long deltaMB = memoryDelta / (1024 * 1024);
            
            if (deltaMB > 10) // 10MB 이상 급증
            {
                Debug.LogWarning($"메모리 사용량 급증 감지: +{deltaMB}MB");
                TriggerMemoryCleanup();
            }
        }
        
        lastMemoryUsage = currentMemory;
        
        // iOS 메모리 제한 체크
        if (currentMemoryMB > maxMemoryUsageMB)
        {
            Debug.LogWarning($"iOS 메모리 사용량 초과: {currentMemoryMB}MB > {maxMemoryUsageMB}MB");
            TriggerAggressiveMemoryCleanup();
        }
        
        // 앱인토스에 메모리 사용량 리포트
        AppsInToss.ReportMemoryUsage(currentMemoryMB, "iOS");
    }
    
    void OnLowMemoryWarning()
    {
        memoryWarningCount++;
        Debug.LogWarning($"iOS 메모리 경고 #{memoryWarningCount}");
        
        if (enableMemoryWarningResponse)
        {
            RespondToMemoryWarning();
        }
        
        // 앱인토스에 메모리 경고 리포트
        AppsInToss.ReportPerformanceIssue("ios_memory_warning", memoryWarningCount);
    }
    
    void RespondToMemoryWarning()
    {
        // 즉시 메모리 정리
        TriggerAggressiveMemoryCleanup();
        
        // 품질 설정 자동 조정
        if (autoReduceQualityOnWarning)
        {
            ReduceQualitySettings();
        }
        
        // 백그라운드 작업 중단
        StopBackgroundTasks();
    }
    
    void TriggerMemoryCleanup()
    {
        // 가벼운 메모리 정리
        System.GC.Collect();
        
        // 사용하지 않는 에셋 언로드
        Resources.UnloadUnusedAssets();
        
        Debug.Log("iOS 메모리 정리 수행");
    }
    
    void TriggerAggressiveMemoryCleanup()
    {
        // 적극적인 메모리 정리
        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();
        System.GC.Collect();
        
        // 모든 사용하지 않는 에셋 언로드
        Resources.UnloadUnusedAssets();
        
        // 에셋 번들 캐시 정리
        if (AppsInTossAssetBundleManager.Instance != null)
        {
            AppsInTossAssetBundleManager.Instance.UnloadUnusedBundles();
        }
        
        // 텍스처 캐시 정리
        Caching.ClearCache();
        
        Debug.Log("iOS 적극적 메모리 정리 수행");
    }
    
    void ReduceQualitySettings()
    {
        var deviceTier = iOSDeviceDetector.GetCurrentDeviceTier();
        
        // 기기 등급을 한 단계 낮춤
        switch (deviceTier)
        {
            case iOSDeviceTier.HighEnd:
                ApplyQualitySettings(iOSDeviceTier.MidHigh);
                break;
            case iOSDeviceTier.MidHigh:
                ApplyQualitySettings(iOSDeviceTier.MidRange);
                break;
            case iOSDeviceTier.MidRange:
                ApplyQualitySettings(iOSDeviceTier.LowEnd);
                break;
            case iOSDeviceTier.LowEnd:
                ApplyMinimalQualitySettings();
                break;
        }
        
        Debug.Log($"메모리 경고로 인한 품질 설정 하향: {deviceTier}");
    }
    
    void ApplyQualitySettings(iOSDeviceTier targetTier)
    {
        switch (targetTier)
        {
            case iOSDeviceTier.HighEnd:
                QualitySettings.masterTextureLimit = 0;
                QualitySettings.shadowDistance = 150f;
                Application.targetFrameRate = 60;
                break;
                
            case iOSDeviceTier.MidHigh:
                QualitySettings.masterTextureLimit = 1;
                QualitySettings.shadowDistance = 100f;
                Application.targetFrameRate = 60;
                break;
                
            case iOSDeviceTier.MidRange:
                QualitySettings.masterTextureLimit = 1;
                QualitySettings.shadowDistance = 50f;
                Application.targetFrameRate = 30;
                break;
                
            case iOSDeviceTier.LowEnd:
                QualitySettings.masterTextureLimit = 2;
                QualitySettings.shadowDistance = 25f;
                Application.targetFrameRate = 30;
                break;
        }
    }
    
    void ApplyMinimalQualitySettings()
    {
        // 최소 품질 설정 (생존 모드)
        QualitySettings.masterTextureLimit = 3;
        QualitySettings.shadowDistance = 0f;
        QualitySettings.shadows = ShadowQuality.Disable;
        QualitySettings.antiAliasing = 0;
        Application.targetFrameRate = 20;
        
        Debug.Log("최소 품질 설정 적용");
    }
    
    void StopBackgroundTasks()
    {
        // 백그라운드 로딩 중단
        if (AppsInTossLoadingManager.Instance != null)
        {
            AppsInTossLoadingManager.Instance.PauseBackgroundLoading();
        }
        
        // 불필요한 업데이트 중단
        var backgroundUpdaters = FindObjectsOfType<MonoBehaviour>()
            .Where(mb => mb.GetType().Name.Contains("Background") || 
                         mb.GetType().Name.Contains("Update"))
            .ToArray();
        
        foreach (var updater in backgroundUpdaters)
        {
            updater.enabled = false;
        }
        
        Debug.Log("백그라운드 작업 중단");
    }
    
    void OnApplicationPause(bool pauseStatus)
    {
        if (pauseStatus)
        {
            // 백그라운드 진입 시 메모리 정리
            TriggerMemoryCleanup();
            
            // iOS 백그라운드 제한에 대비한 최소화
            MinimizeMemoryFootprint();
        }
    }
    
    void MinimizeMemoryFootprint()
    {
        // 백그라운드에서 메모리 사용량 최소화
        
        // 오디오 중단
        AudioListener.pause = true;
        
        // 애니메이션 중단
        var animators = FindObjectsOfType<Animator>();
        foreach (var animator in animators)
        {
            animator.enabled = false;
        }
        
        // 파티클 시스템 중단
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        foreach (var ps in particleSystems)
        {
            ps.Pause();
        }
        
        Debug.Log("iOS 백그라운드 메모리 최소화 적용");
    }
    
    void OnApplicationFocus(bool hasFocus)
    {
        if (hasFocus)
        {
            // 포그라운드 복귀 시 시스템 복원
            RestoreFromBackground();
        }
    }
    
    void RestoreFromBackground()
    {
        // 백그라운드에서 복귀 시 시스템 복원
        AudioListener.pause = false;
        
        var animators = FindObjectsOfType<Animator>();
        foreach (var animator in animators)
        {
            animator.enabled = true;
        }
        
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        foreach (var ps in particleSystems)
        {
            ps.Play();
        }
        
        Debug.Log("iOS 포그라운드 복귀 - 시스템 복원");
    }
}

4. iOS 배터리 최적화

전력 효율성 개선

c#
public class iOSBatteryOptimizer : MonoBehaviour
{
    [Header("배터리 최적화 설정")]
    public bool enableBatteryOptimization = true;
    public bool adaptiveFrameRate = true;
    public bool thermalManagement = true;
    
    [Header("전력 임계값")]
    [Range(0f, 1f)]
    public float lowBatteryThreshold = 0.2f; // 20%
    [Range(0f, 1f)] 
    public float criticalBatteryThreshold = 0.1f; // 10%
    
    private float lastBatteryLevel = 1f;
    private bool isLowPowerMode = false;
    
    void Start()
    {
        #if UNITY_IOS
        InitializeBatteryOptimization();
        #endif
    }
    
    void InitializeBatteryOptimization()
    {
        if (enableBatteryOptimization)
        {
            InvokeRepeating(nameof(MonitorBatteryStatus), 30f, 30f); // 30초마다 체크
            
            if (thermalManagement)
            {
                InvokeRepeating(nameof(CheckThermalState), 60f, 60f); // 1분마다 체크
            }
        }
        
        Debug.Log("iOS 배터리 최적화 시스템 초기화");
    }
    
    void MonitorBatteryStatus()
    {
        float currentBattery = SystemInfo.batteryLevel;
        
        if (currentBattery < 0) return; // 배터리 정보 없음
        
        // 배터리 수준에 따른 최적화
        if (currentBattery <= criticalBatteryThreshold && !isLowPowerMode)
        {
            EnableCriticalPowerMode();
        }
        else if (currentBattery <= lowBatteryThreshold && !isLowPowerMode)
        {
            EnableLowPowerMode();
        }
        else if (currentBattery > lowBatteryThreshold + 0.1f && isLowPowerMode)
        {
            DisableLowPowerMode();
        }
        
        // 배터리 소모율 계산
        if (lastBatteryLevel > 0)
        {
            float batteryDrain = lastBatteryLevel - currentBattery;
            if (batteryDrain > 0.02f) // 2% 이상 급격한 소모
            {
                Debug.LogWarning($"배터리 급속 소모 감지: -{batteryDrain * 100:F1}%");
                OptimizePowerConsumption();
            }
        }
        
        lastBatteryLevel = currentBattery;
        
        // 앱인토스에 배터리 상태 리포트
        AppsInToss.ReportBatteryStatus(currentBattery, isLowPowerMode);
    }
    
    void EnableLowPowerMode()
    {
        isLowPowerMode = true;
        
        // 프레임레이트 제한
        Application.targetFrameRate = 20;
        
        // 품질 설정 하향
        QualitySettings.masterTextureLimit = 2;
        QualitySettings.shadowDistance = 25f;
        QualitySettings.shadows = ShadowQuality.HardOnly;
        
        // 파티클 효과 감소
        ReduceParticleEffects(0.5f);
        
        // 백그라운드 업데이트 빈도 감소
        ReduceUpdateFrequency();
        
        Debug.Log("iOS 저전력 모드 활성화");
        AppsInToss.ReportOptimizationApplied("low_power_mode", "iOS 배터리 절약 모드");
    }
    
    void EnableCriticalPowerMode()
    {
        isLowPowerMode = true;
        
        // 극도로 제한적인 설정
        Application.targetFrameRate = 15;
        
        // 최소 품질
        QualitySettings.masterTextureLimit = 3;
        QualitySettings.shadowDistance = 0f;
        QualitySettings.shadows = ShadowQuality.Disable;
        QualitySettings.antiAliasing = 0;
        
        // 효과 대부분 비활성화
        DisableNonEssentialEffects();
        
        Debug.LogWarning("iOS 긴급 절전 모드 활성화");
        AppsInToss.ReportOptimizationApplied("critical_power_mode", "iOS 긴급 배터리 절약");
    }
    
    void DisableLowPowerMode()
    {
        isLowPowerMode = false;
        
        // 정상 설정 복원
        var deviceTier = iOSDeviceDetector.GetCurrentDeviceTier();
        RestoreNormalSettings(deviceTier);
        
        Debug.Log("iOS 저전력 모드 해제");
    }
    
    void RestoreNormalSettings(iOSDeviceTier deviceTier)
    {
        switch (deviceTier)
        {
            case iOSDeviceTier.HighEnd:
                Application.targetFrameRate = 60;
                QualitySettings.masterTextureLimit = 0;
                QualitySettings.shadowDistance = 150f;
                break;
                
            case iOSDeviceTier.MidHigh:
                Application.targetFrameRate = 60;
                QualitySettings.masterTextureLimit = 1;
                QualitySettings.shadowDistance = 100f;
                break;
                
            case iOSDeviceTier.MidRange:
                Application.targetFrameRate = 30;
                QualitySettings.masterTextureLimit = 1;
                QualitySettings.shadowDistance = 50f;
                break;
                
            case iOSDeviceTier.LowEnd:
                Application.targetFrameRate = 30;
                QualitySettings.masterTextureLimit = 2;
                QualitySettings.shadowDistance = 25f;
                break;
        }
        
        // 효과 복원
        RestoreEffects();
    }
    
    void CheckThermalState()
    {
        // iOS 열 상태 체크 (앱인토스 네이티브 API 사용)
        string thermalState = AppsInToss.GetThermalState();
        
        switch (thermalState.ToLower())
        {
            case "normal":
                // 정상 상태 - 추가 조치 불필요
                break;
                
            case "fair":
                // 약간 따뜻함 - 경미한 최적화
                OptimizeForThermal(ThermalLevel.Fair);
                break;
                
            case "serious":
                // 뜨거움 - 적극적 최적화
                OptimizeForThermal(ThermalLevel.Serious);
                break;
                
            case "critical":
                // 과열 - 긴급 최적화
                OptimizeForThermal(ThermalLevel.Critical);
                break;
        }
    }
    
    enum ThermalLevel
    {
        Normal,
        Fair, 
        Serious,
        Critical
    }
    
    void OptimizeForThermal(ThermalLevel level)
    {
        Debug.LogWarning($"iOS 열 관리 최적화 적용: {level}");
        
        switch (level)
        {
            case ThermalLevel.Fair:
                // 경미한 최적화
                Application.targetFrameRate = Mathf.Min(Application.targetFrameRate, 45);
                QualitySettings.lodBias = 0.8f;
                break;
                
            case ThermalLevel.Serious:
                // 적극적 최적화
                Application.targetFrameRate = 30;
                QualitySettings.masterTextureLimit = Mathf.Max(QualitySettings.masterTextureLimit, 1);
                QualitySettings.shadowDistance *= 0.7f;
                ReduceParticleEffects(0.7f);
                break;
                
            case ThermalLevel.Critical:
                // 긴급 최적화
                Application.targetFrameRate = 20;
                QualitySettings.masterTextureLimit = 2;
                QualitySettings.shadowDistance *= 0.5f;
                QualitySettings.shadows = ShadowQuality.Disable;
                DisableNonEssentialEffects();
                break;
        }
        
        AppsInToss.ReportPerformanceIssue($"thermal_{level.ToString().ToLower()}", level.ToString());
    }
    
    void OptimizePowerConsumption()
    {
        // 즉시 전력 소모 최적화
        
        // CPU 사용률 감소
        Time.fixedDeltaTime = 0.04f; // 물리 업데이트 빈도 감소
        
        // GPU 부하 감소
        QualitySettings.pixelLightCount = 1;
        QualitySettings.shadowCascades = 2;
        
        // 불필요한 업데이트 중단
        var inefficientComponents = FindObjectsOfType<MonoBehaviour>()
            .Where(mb => mb.enabled && IsInefficient(mb))
            .ToArray();
        
        foreach (var component in inefficientComponents)
        {
            component.enabled = false;
        }
        
        Debug.Log("전력 소모 최적화 적용");
    }
    
    bool IsInefficient(MonoBehaviour component)
    {
        // 전력 소모가 큰 컴포넌트 식별
        string typeName = component.GetType().Name;
        
        return typeName.Contains("Effect") || 
               typeName.Contains("Animation") || 
               typeName.Contains("Particle") ||
               typeName.Contains("Reflection");
    }
    
    void ReduceParticleEffects(float intensity)
    {
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        
        foreach (var ps in particleSystems)
        {
            var emission = ps.emission;
            var rateOverTime = emission.rateOverTime;
            rateOverTime.constant *= intensity;
            emission.rateOverTime = rateOverTime;
            
            var main = ps.main;
            main.maxParticles = Mathf.RoundToInt(main.maxParticles * intensity);
        }
    }
    
    void ReduceUpdateFrequency()
    {
        // 업데이트 빈도가 높은 컴포넌트들의 빈도 감소
        var frequentUpdaters = FindObjectsOfType<MonoBehaviour>()
            .Where(mb => HasFrequentUpdate(mb))
            .ToArray();
        
        foreach (var updater in frequentUpdaters)
        {
            // 업데이트 간격 조정 (구체적 구현은 컴포넌트별로 다름)
            AdjustUpdateFrequency(updater);
        }
    }
    
    bool HasFrequentUpdate(MonoBehaviour component)
    {
        // 빈번한 업데이트를 하는 컴포넌트 식별
        return component.GetType().GetMethod("Update") != null ||
               component.GetType().GetMethod("LateUpdate") != null ||
               component.GetType().GetMethod("FixedUpdate") != null;
    }
    
    void AdjustUpdateFrequency(MonoBehaviour component)
    {
        // 컴포넌트별 업데이트 빈도 조정
        // 실제 구현은 각 컴포넌트의 특성에 따라 다름
    }
    
    void DisableNonEssentialEffects()
    {
        // 필수적이지 않은 효과들 비활성화
        var effects = FindObjectsOfType<ParticleSystem>();
        foreach (var effect in effects)
        {
            if (!IsEssentialEffect(effect))
            {
                effect.gameObject.SetActive(false);
            }
        }
        
        var audioSources = FindObjectsOfType<AudioSource>();
        foreach (var audio in audioSources)
        {
            if (!IsEssentialAudio(audio))
            {
                audio.enabled = false;
            }
        }
    }
    
    bool IsEssentialEffect(ParticleSystem effect)
    {
        // 필수 효과인지 판단
        return effect.name.Contains("Essential") || 
               effect.name.Contains("UI") ||
               effect.transform.parent?.name.Contains("Critical") == true;
    }
    
    bool IsEssentialAudio(AudioSource audio)
    {
        // 필수 오디오인지 판단
        return audio.name.Contains("UI") || 
               audio.name.Contains("Critical") ||
               audio.name.Contains("Toss"); // 앱인토스 관련 사운드
    }
    
    void RestoreEffects()
    {
        // 비활성화된 효과들 복원
        var disabledEffects = FindObjectsOfType<ParticleSystem>(true)
            .Where(ps => !ps.gameObject.activeInHierarchy)
            .ToArray();
        
        foreach (var effect in disabledEffects)
        {
            effect.gameObject.SetActive(true);
        }
        
        var disabledAudio = FindObjectsOfType<AudioSource>(true)
            .Where(audio => !audio.enabled)
            .ToArray();
        
        foreach (var audio in disabledAudio)
        {
            audio.enabled = true;
        }
    }
    
    // 공개 API
    public bool IsInLowPowerMode()
    {
        return isLowPowerMode;
    }
    
    public float GetBatteryLevel()
    {
        return SystemInfo.batteryLevel;
    }
    
    public void ForceLowPowerMode(bool enable)
    {
        if (enable && !isLowPowerMode)
        {
            EnableLowPowerMode();
        }
        else if (!enable && isLowPowerMode)
        {
            DisableLowPowerMode();
        }
    }
}

iOS는 엄격한 메모리 관리와 전력 효율성이 요구돼요.
Metal API 활용과 ARC 호환 메모리 관리, 적응적 품질 조정을 통해 최적의 iOS 경험을 제공하세요.