앱인토스 개발자센터 로고
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 경험을 제공하세요.