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

iOS 전력 최적화

iOS 전력 및 성능 관리는 앱인토스 미니앱에서 Unity 게임이 배터리를 효율적으로 사용하고, 발열을 줄이면서 안정적인 성능을 유지하도록 돕는 핵심 시스템이에요.
iOS의 엄격한 전력 관리 정책과 앱인토스의 WebGL 환경을 함께 고려해, 지속적이고 부드러운 게임 경험을 제공합니다.


앱인토스 플랫폼 특화 iOS 최적화

1. iOS 배터리 상태 모니터링

c#
// Unity C# - iOS 배터리 및 성능 모니터
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;

public class AITiOSPowerManager : MonoBehaviour
{
    private static AITiOSPowerManager instance;
    public static AITiOSPowerManager Instance => instance;
    
    #if UNITY_IOS && !UNITY_EDITOR
    [DllImport("__Internal")]
    private static extern float GetBatteryLevel();
    
    [DllImport("__Internal")]
    private static extern int GetBatteryState(); // 0: Unknown, 1: Unplugged, 2: Charging, 3: Full
    
    [DllImport("__Internal")]
    private static extern bool IsLowPowerModeEnabled();
    
    [DllImport("__Internal")]
    private static extern float GetThermalState(); // 0: Nominal, 1: Fair, 2: Serious, 3: Critical
    
    [DllImport("__Internal")]
    private static extern void SetPreferredFrameRate(int frameRate);
    
    [DllImport("__Internal")]
    private static extern void EnableMetalPerformanceShaders(bool enabled);
    
    [DllImport("__Internal")]
    private static extern float GetProcessorUsage();
    
    [DllImport("__Internal")]
    private static extern float GetGPUUsage();
    #endif
    
    [System.Serializable]
    public class iOSPowerState
    {
        public float batteryLevel;          // 0.0 ~ 1.0
        public BatteryState batteryState;
        public bool isLowPowerMode;
        public ThermalState thermalState;
        public float cpuUsage;              // 0.0 ~ 1.0
        public float gpuUsage;              // 0.0 ~ 1.0
        public int currentFrameRate;
        public float powerConsumption;      // 추정 전력 소모량 (mW)
        public bool isBackgrounded;
    }
    
    public enum BatteryState
    {
        Unknown = 0,
        Unplugged = 1,
        Charging = 2,
        Full = 3
    }
    
    public enum ThermalState
    {
        Nominal = 0,    // 정상
        Fair = 1,       // 양호
        Serious = 2,    // 심각
        Critical = 3    // 위험
    }
    
    public enum PowerMode
    {
        HighPerformance,    // 고성능 모드
        Balanced,           // 균형 모드
        PowerSaving,        // 절전 모드
        UltraPowerSaving   // 극한 절전 모드
    }
    
    [Header("전력 관리 설정")]
    public PowerMode currentPowerMode = PowerMode.Balanced;
    public bool enableAdaptivePowerManagement = true;
    public bool enableThermalManagement = true;
    public bool enableLowPowerModeDetection = true;
    public float powerMonitoringInterval = 2f;
    
    [Header("성능 임계값")]
    public float batteryLowThreshold = 0.2f;        // 20% 이하 저배터리
    public float batteryCriticalThreshold = 0.1f;   // 10% 이하 위험
    public float thermalThrottleThreshold = 2f;     // 열 제한 임계값
    public float cpuUsageThreshold = 0.8f;          // CPU 사용률 임계값
    public float gpuUsageThreshold = 0.85f;         // GPU 사용률 임계값
    
    private iOSPowerState currentPowerState;
    private PowerMode previousPowerMode;
    private Coroutine powerMonitoringCoroutine;
    
    // 성능 설정 백업
    private struct PerformanceBackup
    {
        public int originalTargetFrameRate;
        public bool originalVSyncEnabled;
        public int originalQualityLevel;
        public float originalTimeScale;
    }
    private PerformanceBackup performanceBackup;
    
    // 이벤트
    public static event System.Action<iOSPowerState> OnPowerStateChanged;
    public static event System.Action<PowerMode> OnPowerModeChanged;
    public static event System.Action<ThermalState> OnThermalStateChanged;
    public static event System.Action OnLowPowerModeEnabled;
    public static event System.Action OnLowPowerModeDisabled;
    
    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
            InitializePowerManagement();
        }
        else
        {
            Destroy(gameObject);
        }
    }
    
    private void InitializePowerManagement()
    {
        // iOS에서만 실행
        #if !UNITY_IOS || UNITY_EDITOR
        Debug.LogWarning("[AIT iOS Power] iOS가 아닌 플랫폼에서는 시뮬레이션 모드로 실행");
        #endif
        
        currentPowerState = new iOSPowerState();
        previousPowerMode = currentPowerMode;
        
        // 초기 성능 설정 백업
        BackupPerformanceSettings();
        
        // 전력 모니터링 시작
        if (powerMonitoringCoroutine == null)
        {
            powerMonitoringCoroutine = StartCoroutine(PowerMonitoringLoop());
        }
        
        // 앱 생명주기 이벤트 등록
        RegisterApplicationEvents();
        
        Debug.Log("[AIT iOS Power] iOS 전력 관리 초기화 완료");
    }
    
    private void BackupPerformanceSettings()
    {
        performanceBackup.originalTargetFrameRate = Application.targetFrameRate;
        performanceBackup.originalVSyncEnabled = QualitySettings.vSyncCount > 0;
        performanceBackup.originalQualityLevel = QualitySettings.GetQualityLevel();
        performanceBackup.originalTimeScale = Time.timeScale;
    }
    
    private void RegisterApplicationEvents()
    {
        // 앱 포커스 변경 감지
        Application.focusChanged += OnApplicationFocusChanged;
        
        // iOS 시스템 알림 등록 (네이티브 코드에서 호출)
        #if UNITY_IOS && !UNITY_EDITOR
        RegisterForPowerNotifications();
        #endif
    }
    
    private IEnumerator PowerMonitoringLoop()
    {
        while (true)
        {
            UpdatePowerState();
            
            if (enableAdaptivePowerManagement)
            {
                UpdateAdaptivePowerMode();
            }
            
            if (enableThermalManagement)
            {
                HandleThermalManagement();
            }
            
            yield return new WaitForSeconds(powerMonitoringInterval);
        }
    }
    
    private void UpdatePowerState()
    {
        var previousState = currentPowerState;
        
        #if UNITY_IOS && !UNITY_EDITOR
        currentPowerState.batteryLevel = GetBatteryLevel();
        currentPowerState.batteryState = (BatteryState)GetBatteryState();
        currentPowerState.isLowPowerMode = IsLowPowerModeEnabled();
        currentPowerState.thermalState = (ThermalState)GetThermalState();
        currentPowerState.cpuUsage = GetProcessorUsage();
        currentPowerState.gpuUsage = GetGPUUsage();
        #else
        // 에디터나 다른 플랫폼에서는 시뮬레이션
        currentPowerState.batteryLevel = Mathf.Clamp01(SystemInfo.batteryLevel);
        currentPowerState.batteryState = SystemInfo.batteryStatus == BatteryStatus.Charging ? BatteryState.Charging : BatteryState.Unplugged;
        currentPowerState.isLowPowerMode = false;
        currentPowerState.thermalState = ThermalState.Nominal;
        currentPowerState.cpuUsage = UnityEngine.Random.Range(0.3f, 0.7f);
        currentPowerState.gpuUsage = UnityEngine.Random.Range(0.4f, 0.8f);
        #endif
        
        currentPowerState.currentFrameRate = Mathf.RoundToInt(1f / Time.deltaTime);
        currentPowerState.powerConsumption = EstimatePowerConsumption();
        currentPowerState.isBackgrounded = !Application.isFocused;
        
        // 상태 변경 감지 및 이벤트 발생
        DetectStateChanges(previousState, currentPowerState);
        
        OnPowerStateChanged?.Invoke(currentPowerState);
    }
    
    private float EstimatePowerConsumption()
    {
        // 전력 소모량 추정 (단위: mW)
        float basePower = 500f; // 기본 소모량
        
        // CPU 사용률에 따른 추가 소모
        basePower += currentPowerState.cpuUsage * 1000f;
        
        // GPU 사용률에 따른 추가 소모
        basePower += currentPowerState.gpuUsage * 1500f;
        
        // 프레임레이트에 따른 추가 소모
        float frameRateMultiplier = currentPowerState.currentFrameRate / 30f;
        basePower *= frameRateMultiplier;
        
        // 열 상태에 따른 보정
        switch (currentPowerState.thermalState)
        {
            case ThermalState.Fair:
                basePower *= 1.1f;
                break;
            case ThermalState.Serious:
                basePower *= 1.3f;
                break;
            case ThermalState.Critical:
                basePower *= 1.5f;
                break;
        }
        
        return basePower;
    }
    
    private void DetectStateChanges(iOSPowerState previous, iOSPowerState current)
    {
        // 저전력 모드 변경 감지
        if (enableLowPowerModeDetection && previous.isLowPowerMode != current.isLowPowerMode)
        {
            if (current.isLowPowerMode)
            {
                OnLowPowerModeEnabled?.Invoke();
                Debug.Log("[AIT iOS Power] 저전력 모드 활성화 감지");
            }
            else
            {
                OnLowPowerModeDisabled?.Invoke();
                Debug.Log("[AIT iOS Power] 저전력 모드 비활성화 감지");
            }
        }
        
        // 열 상태 변경 감지
        if (previous.thermalState != current.thermalState)
        {
            OnThermalStateChanged?.Invoke(current.thermalState);
            Debug.Log($"[AIT iOS Power] 열 상태 변경: {previous.thermalState} -> {current.thermalState}");
        }
        
        // 배터리 위험 수준 감지
        if (current.batteryLevel <= batteryCriticalThreshold && previous.batteryLevel > batteryCriticalThreshold)
        {
            Debug.LogWarning("[AIT iOS Power] 배터리 위험 수준 도달!");
            SetPowerMode(PowerMode.UltraPowerSaving);
        }
        else if (current.batteryLevel <= batteryLowThreshold && previous.batteryLevel > batteryLowThreshold)
        {
            Debug.LogWarning("[AIT iOS Power] 배터리 부족 감지");
            if (currentPowerMode == PowerMode.HighPerformance)
            {
                SetPowerMode(PowerMode.PowerSaving);
            }
        }
    }
    
    private void UpdateAdaptivePowerMode()
    {
        PowerMode recommendedMode = currentPowerMode;
        
        // 저전력 모드가 활성화되어 있으면 절전 모드
        if (currentPowerState.isLowPowerMode)
        {
            recommendedMode = PowerMode.PowerSaving;
        }
        // 배터리 위험 수준
        else if (currentPowerState.batteryLevel <= batteryCriticalThreshold)
        {
            recommendedMode = PowerMode.UltraPowerSaving;
        }
        // 배터리 부족
        else if (currentPowerState.batteryLevel <= batteryLowThreshold)
        {
            recommendedMode = PowerMode.PowerSaving;
        }
        // 열 문제
        else if (currentPowerState.thermalState >= ThermalState.Serious)
        {
            recommendedMode = PowerMode.PowerSaving;
        }
        // 높은 CPU/GPU 사용률
        else if (currentPowerState.cpuUsage > cpuUsageThreshold || currentPowerState.gpuUsage > gpuUsageThreshold)
        {
            recommendedMode = PowerMode.Balanced;
        }
        // 충전 중이고 배터리가 충분하면 고성능 모드 허용
        else if (currentPowerState.batteryState == BatteryState.Charging && currentPowerState.batteryLevel > 0.5f)
        {
            recommendedMode = PowerMode.HighPerformance;
        }
        // 일반적인 상황에서는 균형 모드
        else
        {
            recommendedMode = PowerMode.Balanced;
        }
        
        if (recommendedMode != currentPowerMode)
        {
            SetPowerMode(recommendedMode);
        }
    }
    
    private void HandleThermalManagement()
    {
        switch (currentPowerState.thermalState)
        {
            case ThermalState.Nominal:
                // 정상 상태 - 제한 없음
                break;
                
            case ThermalState.Fair:
                // 양호 - 경미한 최적화
                ApplyThermalOptimization(0.9f);
                break;
                
            case ThermalState.Serious:
                // 심각 - 적극적 최적화
                ApplyThermalOptimization(0.7f);
                Debug.LogWarning("[AIT iOS Power] 심각한 열 상태 - 성능 제한");
                break;
                
            case ThermalState.Critical:
                // 위험 - 극한 최적화
                ApplyThermalOptimization(0.5f);
                Debug.LogError("[AIT iOS Power] 위험한 열 상태 - 극한 성능 제한");
                break;
        }
    }
    
    private void ApplyThermalOptimization(float performanceMultiplier)
    {
        // 프레임레이트 제한
        int maxFrameRate = Mathf.RoundToInt(60f * performanceMultiplier);
        
        #if UNITY_IOS && !UNITY_EDITOR
        SetPreferredFrameRate(maxFrameRate);
        #endif
        
        Application.targetFrameRate = maxFrameRate;
        
        // 렌더링 품질 조정
        if (performanceMultiplier < 0.8f)
        {
            // 그림자 품질 낮춤
            QualitySettings.shadowResolution = ShadowResolution.Low;
            QualitySettings.shadowDistance = QualitySettings.shadowDistance * 0.7f;
            
            // 텍스처 품질 낮춤
            QualitySettings.masterTextureLimit = 1;
        }
        
        if (performanceMultiplier < 0.6f)
        {
            // 파티클 수 제한
            var particleBudgetManager = AITParticleBudgetManager.Instance;
            if (particleBudgetManager != null)
            {
                particleBudgetManager.SetGlobalQuality(AITParticleBudgetManager.ParticleSystemInfo.QualityLevel.Low);
            }
            
            // 안티 앨리어싱 비활성화
            QualitySettings.antiAliasing = 0;
        }
    }
    
    public void SetPowerMode(PowerMode mode)
    {
        if (currentPowerMode == mode) return;
        
        previousPowerMode = currentPowerMode;
        currentPowerMode = mode;
        
        ApplyPowerModeSettings(mode);
        OnPowerModeChanged?.Invoke(mode);
        
        Debug.Log($"[AIT iOS Power] 전력 모드 변경: {previousPowerMode} -> {mode}");
    }
    
    private void ApplyPowerModeSettings(PowerMode mode)
    {
        switch (mode)
        {
            case PowerMode.HighPerformance:
                ApplyHighPerformanceSettings();
                break;
                
            case PowerMode.Balanced:
                ApplyBalancedSettings();
                break;
                
            case PowerMode.PowerSaving:
                ApplyPowerSavingSettings();
                break;
                
            case PowerMode.UltraPowerSaving:
                ApplyUltraPowerSavingSettings();
                break;
        }
    }
    
    private void ApplyHighPerformanceSettings()
    {
        // 최고 성능 설정
        Application.targetFrameRate = 60;
        QualitySettings.vSyncCount = 1;
        QualitySettings.SetQualityLevel(QualitySettings.names.Length - 1); // 최고 품질
        
        #if UNITY_IOS && !UNITY_EDITOR
        SetPreferredFrameRate(60);
        EnableMetalPerformanceShaders(true);
        #endif
        
        // 파티클 고품질
        var particleBudgetManager = AITParticleBudgetManager.Instance;
        particleBudgetManager?.SetGlobalQuality(AITParticleBudgetManager.ParticleSystemInfo.QualityLevel.High);
        
        Debug.Log("[AIT iOS Power] 고성능 모드 적용");
    }
    
    private void ApplyBalancedSettings()
    {
        // 균형잡힌 설정
        Application.targetFrameRate = 45;
        QualitySettings.vSyncCount = 1;
        QualitySettings.SetQualityLevel(Mathf.RoundToInt(QualitySettings.names.Length * 0.6f));
        
        #if UNITY_IOS && !UNITY_EDITOR
        SetPreferredFrameRate(45);
        EnableMetalPerformanceShaders(true);
        #endif
        
        // 파티클 중품질
        var particleBudgetManager = AITParticleBudgetManager.Instance;
        particleBudgetManager?.SetGlobalQuality(AITParticleBudgetManager.ParticleSystemInfo.QualityLevel.Medium);
        
        Debug.Log("[AIT iOS Power] 균형 모드 적용");
    }
    
    private void ApplyPowerSavingSettings()
    {
        // 절전 설정
        Application.targetFrameRate = 30;
        QualitySettings.vSyncCount = 0;
        QualitySettings.SetQualityLevel(Mathf.RoundToInt(QualitySettings.names.Length * 0.4f));
        
        #if UNITY_IOS && !UNITY_EDITOR
        SetPreferredFrameRate(30);
        EnableMetalPerformanceShaders(false);
        #endif
        
        // 파티클 저품질
        var particleBudgetManager = AITParticleBudgetManager.Instance;
        particleBudgetManager?.SetGlobalQuality(AITParticleBudgetManager.ParticleSystemInfo.QualityLevel.Low);
        
        // 추가 최적화
        QualitySettings.shadowResolution = ShadowResolution.Low;
        QualitySettings.shadowDistance = 20f;
        QualitySettings.masterTextureLimit = 1;
        
        Debug.Log("[AIT iOS Power] 절전 모드 적용");
    }
    
    private void ApplyUltraPowerSavingSettings()
    {
        // 극한 절전 설정
        Application.targetFrameRate = 20;
        QualitySettings.vSyncCount = 0;
        QualitySettings.SetQualityLevel(0); // 최저 품질
        
        #if UNITY_IOS && !UNITY_EDITOR
        SetPreferredFrameRate(20);
        EnableMetalPerformanceShaders(false);
        #endif
        
        // 파티클 비활성화
        var particleBudgetManager = AITParticleBudgetManager.Instance;
        particleBudgetManager?.SetGlobalQuality(AITParticleBudgetManager.ParticleSystemInfo.QualityLevel.Low);
        
        // 극한 최적화
        QualitySettings.shadows = ShadowQuality.Disable;
        QualitySettings.masterTextureLimit = 2;
        QualitySettings.antiAliasing = 0;
        
        // 게임 속도 조정 (선택적)
        Time.timeScale = 0.8f;
        
        Debug.LogWarning("[AIT iOS Power] 극한 절전 모드 적용");
    }
    
    private void OnApplicationFocusChanged(bool hasFocus)
    {
        if (hasFocus)
        {
            // 포그라운드로 전환
            Debug.Log("[AIT iOS Power] 앱 포그라운드 전환");
            
            // 전력 상태 즉시 업데이트
            UpdatePowerState();
            
            // 이전 성능 모드 복원 (필요시)
            if (currentPowerState.batteryLevel > batteryLowThreshold && !currentPowerState.isLowPowerMode)
            {
                if (currentPowerMode == PowerMode.UltraPowerSaving)
                {
                    SetPowerMode(PowerMode.Balanced);
                }
            }
        }
        else
        {
            // 백그라운드로 전환
            Debug.Log("[AIT iOS Power] 앱 백그라운드 전환");
            
            // 백그라운드 절전 모드 적용
            ApplyBackgroundOptimizations();
        }
        
        currentPowerState.isBackgrounded = !hasFocus;
    }
    
    private void ApplyBackgroundOptimizations()
    {
        // 백그라운드에서 성능 최소화
        Application.targetFrameRate = 10; // 극저 프레임레이트
        
        #if UNITY_IOS && !UNITY_EDITOR
        SetPreferredFrameRate(10);
        #endif
        
        // 모든 파티클 일시정지
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        foreach (var ps in particleSystems)
        {
            if (ps.isPlaying)
            {
                ps.Pause();
            }
        }
        
        // 오디오 볼륨 최소화
        AudioListener.volume = 0.1f;
        
        Debug.Log("[AIT iOS Power] 백그라운드 최적화 적용");
    }
    
    // 네이티브 코드에서 호출되는 콜백 메서드들
    private void OnBatteryStateChanged(string state)
    {
        Debug.Log($"[AIT iOS Power] 배터리 상태 변경: {state}");
        UpdatePowerState();
    }
    
    private void OnThermalStateChangedNative(string thermalLevel)
    {
        Debug.Log($"[AIT iOS Power] 열 상태 변경: {thermalLevel}");
        UpdatePowerState();
    }
    
    private void OnLowPowerModeChangedNative(string enabled)
    {
        bool isEnabled = enabled.ToLower() == "true";
        Debug.Log($"[AIT iOS Power] 저전력 모드 변경: {isEnabled}");
        UpdatePowerState();
    }
    
    // 공개 API 메서드들
    public iOSPowerState GetCurrentPowerState()
    {
        return currentPowerState;
    }
    
    public void ForcePowerModeUpdate()
    {
        UpdatePowerState();
        UpdateAdaptivePowerMode();
    }
    
    public float GetEstimatedBatteryLife()
    {
        if (currentPowerState.batteryLevel <= 0 || currentPowerState.powerConsumption <= 0)
            return 0f;
        
        // 대략적인 배터리 용량 (mWh) - 기기별로 다르지만 평균적인 값 사용
        float averageBatteryCapacity = 2915f; // iPhone 평균 배터리 용량
        float remainingCapacity = averageBatteryCapacity * currentPowerState.batteryLevel;
        
        // 예상 사용 시간 (시간 단위)
        return remainingCapacity / currentPowerState.powerConsumption;
    }
    
    public void RestorePerformanceSettings()
    {
        Application.targetFrameRate = performanceBackup.originalTargetFrameRate;
        QualitySettings.vSyncCount = performanceBackup.originalVSyncEnabled ? 1 : 0;
        QualitySettings.SetQualityLevel(performanceBackup.originalQualityLevel);
        Time.timeScale = performanceBackup.originalTimeScale;
        
        Debug.Log("[AIT iOS Power] 성능 설정 복원 완료");
    }
    
    public PowerPerformanceStats GetPerformanceStats()
    {
        return new PowerPerformanceStats
        {
            currentPowerMode = currentPowerMode,
            batteryLevel = currentPowerState.batteryLevel,
            isLowPowerMode = currentPowerState.isLowPowerMode,
            thermalState = currentPowerState.thermalState,
            currentFPS = currentPowerState.currentFrameRate,
            cpuUsage = currentPowerState.cpuUsage,
            gpuUsage = currentPowerState.gpuUsage,
            estimatedPowerConsumption = currentPowerState.powerConsumption,
            estimatedBatteryLife = GetEstimatedBatteryLife()
        };
    }
    
    private void OnDestroy()
    {
        if (powerMonitoringCoroutine != null)
        {
            StopCoroutine(powerMonitoringCoroutine);
        }
        
        Application.focusChanged -= OnApplicationFocusChanged;
    }
    
    #if UNITY_IOS && !UNITY_EDITOR
    [DllImport("__Internal")]
    private static extern void RegisterForPowerNotifications();
    #endif
}

[System.Serializable]
public class PowerPerformanceStats
{
    public AITiOSPowerManager.PowerMode currentPowerMode;
    public float batteryLevel;
    public bool isLowPowerMode;
    public AITiOSPowerManager.ThermalState thermalState;
    public int currentFPS;
    public float cpuUsage;
    public float gpuUsage;
    public float estimatedPowerConsumption; // mW
    public float estimatedBatteryLife;      // hours
    
    public string GetBatteryStatus()
    {
        if (batteryLevel <= 0.1f) return "위험";
        if (batteryLevel <= 0.2f) return "부족";
        if (batteryLevel <= 0.5f) return "보통";
        return "충분";
    }
    
    public string GetThermalStatus()
    {
        return thermalState switch
        {
            AITiOSPowerManager.ThermalState.Nominal => "정상",
            AITiOSPowerManager.ThermalState.Fair => "양호",
            AITiOSPowerManager.ThermalState.Serious => "주의",
            AITiOSPowerManager.ThermalState.Critical => "위험",
            _ => "알 수 없음"
        };
    }
    
    public string GetPerformanceGrade()
    {
        float score = (currentFPS / 60f) * 0.4f + (1f - cpuUsage) * 0.3f + (1f - gpuUsage) * 0.3f;
        
        if (score >= 0.8f) return "A";
        if (score >= 0.6f) return "B";
        if (score >= 0.4f) return "C";
        if (score >= 0.2f) return "D";
        return "F";
    }
}

2. Metal 성능 최적화 시스템

c#
// Unity C# - Metal 렌더링 최적화
using UnityEngine;
using UnityEngine.Rendering;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public class AITMetalOptimizer : MonoBehaviour
{
    #if UNITY_IOS && !UNITY_EDITOR
    [DllImport("__Internal")]
    private static extern void EnableMetalFX(bool enabled);
    
    [DllImport("__Internal")]
    private static extern void SetMetalMemoryBudget(int megabytes);
    
    [DllImport("__Internal")]
    private static extern int GetMetalMemoryUsage();
    
    [DllImport("__Internal")]
    private static extern void EnableMetalGPUCapture(bool enabled);
    
    [DllImport("__Internal")]
    private static extern void OptimizeMetalPipelines();
    
    [DllImport("__Internal")]
    private static extern float GetGPUFrameTime();
    
    [DllImport("__Internal")]
    private static extern int GetActiveDrawCalls();
    #endif
    
    [System.Serializable]
    public class MetalPerformanceSettings
    {
        [Header("메모리 관리")]
        public int maxMetalMemoryMB = 512;      // Metal 메모리 예산
        public bool enableMemoryPressureOptimization = true;
        
        [Header("렌더링 최적화")]
        public bool enableMetalFX = true;        // MetalFX 업스케일링
        public bool enablePipelineOptimization = true;
        public bool enableCommandBufferReuse = true;
        
        [Header("드로우콜 최적화")]
        public int maxDrawCallsPerFrame = 300;
        public bool enableInstancing = true;
        public bool enableSRPBatcher = true;
        
        [Header("텍스처 최적화")]
        public bool enableTextureStreaming = true;
        public int maxTextureSize = 1024;
        public bool useCompressedTextures = true;
    }
    
    private AITiOSPowerManager powerManager;
    private MetalPerformanceSettings currentSettings;
    private MetalPerformanceSettings defaultSettings;
    
    [Header("Metal 최적화 설정")]
    public MetalPerformanceSettings metalSettings;
    public bool enableDynamicOptimization = true;
    public float optimizationCheckInterval = 1f;
    
    // 성능 메트릭
    private float currentGPUFrameTime;
    private int currentDrawCalls;
    private int currentMetalMemoryUsage;
    private Queue<float> frameTimeHistory;
    private const int FRAME_TIME_HISTORY_SIZE = 60;
    
    private void Start()
    {
        powerManager = AITiOSPowerManager.Instance;
        currentSettings = metalSettings;
        defaultSettings = JsonUtility.FromJson<MetalPerformanceSettings>(JsonUtility.ToJson(metalSettings));
        
        frameTimeHistory = new Queue<float>();
        
        InitializeMetalOptimization();
        
        if (enableDynamicOptimization)
        {
            InvokeRepeating(nameof(UpdateMetalOptimization), optimizationCheckInterval, optimizationCheckInterval);
        }
        
        // 전력 모드 변경 이벤트 구독
        if (powerManager != null)
        {
            AITiOSPowerManager.OnPowerModeChanged += OnPowerModeChanged;
            AITiOSPowerManager.OnThermalStateChanged += OnThermalStateChanged;
        }
    }
    
    private void InitializeMetalOptimization()
    {
        #if UNITY_IOS && !UNITY_EDITOR
        // Metal 메모리 예산 설정
        SetMetalMemoryBudget(currentSettings.maxMetalMemoryMB);
        
        // MetalFX 설정
        EnableMetalFX(currentSettings.enableMetalFX);
        
        // 파이프라인 최적화
        if (currentSettings.enablePipelineOptimization)
        {
            OptimizeMetalPipelines();
        }
        #endif
        
        // SRP Batcher 설정
        if (currentSettings.enableSRPBatcher)
        {
            GraphicsSettings.useScriptableRenderPipelineBatching = true;
        }
        
        // GPU 인스턴싱 설정
        if (currentSettings.enableInstancing)
        {
            EnableGPUInstancing();
        }
        
        Debug.Log("[AIT Metal] Metal 최적화 초기화 완료");
    }
    
    private void UpdateMetalOptimization()
    {
        // 성능 메트릭 업데이트
        UpdatePerformanceMetrics();
        
        // 동적 최적화 적용
        if (enableDynamicOptimization)
        {
            ApplyDynamicOptimizations();
        }
        
        // 메모리 압박 상황 처리
        if (currentSettings.enableMemoryPressureOptimization)
        {
            HandleMemoryPressure();
        }
    }
    
    private void UpdatePerformanceMetrics()
    {
        #if UNITY_IOS && !UNITY_EDITOR
        currentGPUFrameTime = GetGPUFrameTime();
        currentDrawCalls = GetActiveDrawCalls();
        currentMetalMemoryUsage = GetMetalMemoryUsage();
        #else
        // 시뮬레이션 데이터
        currentGPUFrameTime = Time.deltaTime;
        currentDrawCalls = UnityEngine.Random.Range(100, 400);
        currentMetalMemoryUsage = UnityEngine.Random.Range(200, 600);
        #endif
        
        // 프레임 시간 히스토리 업데이트
        frameTimeHistory.Enqueue(currentGPUFrameTime);
        if (frameTimeHistory.Count > FRAME_TIME_HISTORY_SIZE)
        {
            frameTimeHistory.Dequeue();
        }
    }
    
    private void ApplyDynamicOptimizations()
    {
        float averageFrameTime = GetAverageFrameTime();
        
        // GPU 성능이 부족한 경우
        if (averageFrameTime > 20f) // 50 FPS 이하
        {
            ApplyPerformanceOptimizations();
        }
        // 드로우콜이 많은 경우
        else if (currentDrawCalls > currentSettings.maxDrawCallsPerFrame)
        {
            OptimizeDrawCalls();
        }
        // 메모리 사용량이 높은 경우
        else if (currentMetalMemoryUsage > currentSettings.maxMetalMemoryMB * 0.85f)
        {
            OptimizeMemoryUsage();
        }
    }
    
    private float GetAverageFrameTime()
    {
        if (frameTimeHistory.Count == 0) return 0f;
        
        float total = 0f;
        foreach (float frameTime in frameTimeHistory)
        {
            total += frameTime;
        }
        
        return (total / frameTimeHistory.Count) * 1000f; // ms 단위
    }
    
    private void ApplyPerformanceOptimizations()
    {
        Debug.Log("[AIT Metal] GPU 성능 최적화 적용");
        
        // 텍스처 해상도 감소
        if (currentSettings.maxTextureSize > 512)
        {
            currentSettings.maxTextureSize = Mathf.Max(512, currentSettings.maxTextureSize / 2);
            ApplyTextureOptimizations();
        }
        
        // 렌더링 스케일 감소
        if (UnityEngine.XR.XRSettings.enabled == false) // VR이 아닌 경우에만
        {
            UnityEngine.XR.XRSettings.renderViewportScale = Mathf.Max(0.7f, UnityEngine.XR.XRSettings.renderViewportScale * 0.9f);
        }
        
        // 쉐이더 LOD 감소
        Shader.globalMaximumLOD = 200;
        
        #if UNITY_IOS && !UNITY_EDITOR
        // MetalFX 비활성화로 성능 확보
        EnableMetalFX(false);
        #endif
    }
    
    private void OptimizeDrawCalls()
    {
        Debug.Log("[AIT Metal] 드로우콜 최적화 적용");
        
        // 동적 배칭 강화
        var renderers = FindObjectsOfType<Renderer>();
        foreach (var renderer in renderers)
        {
            if (renderer.gameObject.isStatic == false && renderer.bounds.size.magnitude < 10f)
            {
                renderer.gameObject.isStatic = true; // 정적 배칭 가능하도록
            }
        }
        
        // 파티클 시스템 최적화
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        foreach (var ps in particleSystems)
        {
            var renderer = ps.GetComponent<ParticleSystemRenderer>();
            if (renderer != null && renderer.sortMode == ParticleSystemSortMode.Distance)
            {
                renderer.sortMode = ParticleSystemSortMode.None; // 정렬 비활성화
            }
        }
    }
    
    private void OptimizeMemoryUsage()
    {
        Debug.Log("[AIT Metal] Metal 메모리 최적화 적용");
        
        // 텍스처 메모리 해제
        Resources.UnloadUnusedAssets();
        
        // 메모리 예산 감소
        currentSettings.maxMetalMemoryMB = Mathf.Max(256, currentSettings.maxMetalMemoryMB - 64);
        
        #if UNITY_IOS && !UNITY_EDITOR
        SetMetalMemoryBudget(currentSettings.maxMetalMemoryMB);
        #endif
        
        // 텍스처 품질 감소
        QualitySettings.masterTextureLimit = Mathf.Min(2, QualitySettings.masterTextureLimit + 1);
    }
    
    private void HandleMemoryPressure()
    {
        float memoryUsageRatio = (float)currentMetalMemoryUsage / currentSettings.maxMetalMemoryMB;
        
        if (memoryUsageRatio > 0.9f) // 90% 이상 사용
        {
            Debug.LogWarning("[AIT Metal] Metal 메모리 압박 - 긴급 최적화");
            
            // 긴급 메모리 해제
            System.GC.Collect();
            Resources.UnloadUnusedAssets();
            
            // 텍스처 스트리밍 강화
            if (currentSettings.enableTextureStreaming)
            {
                QualitySettings.streamingMipmapsActive = true;
                QualitySettings.streamingMipmapsMemoryBudget = currentSettings.maxMetalMemoryMB / 4;
            }
            
            // 렌더 텍스처 해상도 감소
            var renderTextures = FindObjectsOfType<Camera>();
            foreach (var camera in renderTextures)
            {
                if (camera.targetTexture != null)
                {
                    var rt = camera.targetTexture;
                    camera.targetTexture = null;
                    
                    var newRT = new RenderTexture(rt.width / 2, rt.height / 2, rt.depth, rt.format);
                    camera.targetTexture = newRT;
                    
                    DestroyImmediate(rt);
                }
            }
        }
    }
    
    private void ApplyTextureOptimizations()
    {
        // 런타임에서 텍스처 최적화 적용
        var textures = Resources.FindObjectsOfTypeAll<Texture2D>();
        
        foreach (var texture in textures)
        {
            if (texture.width > currentSettings.maxTextureSize || texture.height > currentSettings.maxTextureSize)
            {
                // 텍스처 다운스케일 (런타임에서는 제한적)
                Debug.Log($"[AIT Metal] 큰 텍스처 감지: {texture.name} ({texture.width}x{texture.height})");
            }
        }
    }
    
    private void EnableGPUInstancing()
    {
        // GPU 인스턴싱 활성화
        var renderers = FindObjectsOfType<MeshRenderer>();
        
        foreach (var renderer in renderers)
        {
            var material = renderer.sharedMaterial;
            if (material != null && material.enableInstancing == false)
            {
                // 인스턴싱 가능한 쉐이더인지 확인
                if (material.shader.name.Contains("Standard") || material.shader.name.Contains("URP"))
                {
                    var newMaterial = new Material(material);
                    newMaterial.enableInstancing = true;
                    renderer.material = newMaterial;
                }
            }
        }
    }
    
    private void OnPowerModeChanged(AITiOSPowerManager.PowerMode newMode)
    {
        switch (newMode)
        {
            case AITiOSPowerManager.PowerMode.HighPerformance:
                RestoreDefaultSettings();
                break;
                
            case AITiOSPowerManager.PowerMode.Balanced:
                ApplyBalancedMetalSettings();
                break;
                
            case AITiOSPowerManager.PowerMode.PowerSaving:
                ApplyPowerSavingMetalSettings();
                break;
                
            case AITiOSPowerManager.PowerMode.UltraPowerSaving:
                ApplyUltraPowerSavingMetalSettings();
                break;
        }
    }
    
    private void OnThermalStateChanged(AITiOSPowerManager.ThermalState thermalState)
    {
        switch (thermalState)
        {
            case AITiOSPowerManager.ThermalState.Serious:
            case AITiOSPowerManager.ThermalState.Critical:
                ApplyThermalThrottling();
                break;
                
            case AITiOSPowerManager.ThermalState.Nominal:
            case AITiOSPowerManager.ThermalState.Fair:
                if (powerManager.GetCurrentPowerState().thermalState == AITiOSPowerManager.ThermalState.Nominal)
                {
                    RestoreFromThermalThrottling();
                }
                break;
        }
    }
    
    private void RestoreDefaultSettings()
    {
        currentSettings = JsonUtility.FromJson<MetalPerformanceSettings>(JsonUtility.ToJson(defaultSettings));
        
        #if UNITY_IOS && !UNITY_EDITOR
        EnableMetalFX(currentSettings.enableMetalFX);
        SetMetalMemoryBudget(currentSettings.maxMetalMemoryMB);
        #endif
        
        Debug.Log("[AIT Metal] 기본 Metal 설정 복원");
    }
    
    private void ApplyBalancedMetalSettings()
    {
        currentSettings.enableMetalFX = true;
        currentSettings.maxMetalMemoryMB = defaultSettings.maxMetalMemoryMB * 3 / 4;
        currentSettings.maxTextureSize = 1024;
        
        #if UNITY_IOS && !UNITY_EDITOR
        EnableMetalFX(currentSettings.enableMetalFX);
        SetMetalMemoryBudget(currentSettings.maxMetalMemoryMB);
        #endif
        
        Debug.Log("[AIT Metal] 균형 Metal 설정 적용");
    }
    
    private void ApplyPowerSavingMetalSettings()
    {
        currentSettings.enableMetalFX = false;
        currentSettings.maxMetalMemoryMB = defaultSettings.maxMetalMemoryMB / 2;
        currentSettings.maxTextureSize = 512;
        currentSettings.maxDrawCallsPerFrame = 200;
        
        #if UNITY_IOS && !UNITY_EDITOR
        EnableMetalFX(false);
        SetMetalMemoryBudget(currentSettings.maxMetalMemoryMB);
        #endif
        
        ApplyTextureOptimizations();
        
        Debug.Log("[AIT Metal] 절전 Metal 설정 적용");
    }
    
    private void ApplyUltraPowerSavingMetalSettings()
    {
        currentSettings.enableMetalFX = false;
        currentSettings.maxMetalMemoryMB = defaultSettings.maxMetalMemoryMB / 4;
        currentSettings.maxTextureSize = 256;
        currentSettings.maxDrawCallsPerFrame = 100;
        
        #if UNITY_IOS && !UNITY_EDITOR
        EnableMetalFX(false);
        SetMetalMemoryBudget(currentSettings.maxMetalMemoryMB);
        #endif
        
        // 극한 최적화
        QualitySettings.masterTextureLimit = 2;
        QualitySettings.shadows = ShadowQuality.Disable;
        Shader.globalMaximumLOD = 100;
        
        Debug.LogWarning("[AIT Metal] 극한 절전 Metal 설정 적용");
    }
    
    private void ApplyThermalThrottling()
    {
        Debug.LogWarning("[AIT Metal] 열 제한 적용");
        
        // 프레임레이트 강제 제한
        Application.targetFrameRate = 20;
        
        // Metal 메모리 대폭 감소
        currentSettings.maxMetalMemoryMB = Mathf.Max(128, currentSettings.maxMetalMemoryMB / 3);
        
        #if UNITY_IOS && !UNITY_EDITOR
        SetMetalMemoryBudget(currentSettings.maxMetalMemoryMB);
        EnableMetalFX(false);
        #endif
        
        // 렌더링 스케일 대폭 감소
        UnityEngine.XR.XRSettings.renderViewportScale = 0.5f;
    }
    
    private void RestoreFromThermalThrottling()
    {
        Debug.Log("[AIT Metal] 열 제한 해제");
        
        // 전력 모드에 맞는 설정으로 복원
        OnPowerModeChanged(powerManager.GetCurrentPowerState().isLowPowerMode ? 
            AITiOSPowerManager.PowerMode.PowerSaving : AITiOSPowerManager.PowerMode.Balanced);
    }
    
    // 공개 API 메서드들
    public MetalPerformanceStats GetMetalPerformanceStats()
    {
        return new MetalPerformanceStats
        {
            currentGPUFrameTime = currentGPUFrameTime,
            currentDrawCalls = currentDrawCalls,
            metalMemoryUsage = currentMetalMemoryUsage,
            maxMetalMemory = currentSettings.maxMetalMemoryMB,
            averageFrameTime = GetAverageFrameTime(),
            isMetalFXEnabled = currentSettings.enableMetalFX,
            memoryPressureLevel = GetMemoryPressureLevel()
        };
    }
    
    private int GetMemoryPressureLevel()
    {
        float ratio = (float)currentMetalMemoryUsage / currentSettings.maxMetalMemoryMB;
        
        if (ratio > 0.9f) return 3; // 높음
        if (ratio > 0.7f) return 2; // 보통
        if (ratio > 0.5f) return 1; // 낮음
        return 0; // 없음
    }
    
    public void ForceMetalOptimization()
    {
        Debug.Log("[AIT Metal] 강제 Metal 최적화 실행");
        
        ApplyPerformanceOptimizations();
        OptimizeDrawCalls();
        OptimizeMemoryUsage();
        
        System.GC.Collect();
        Resources.UnloadUnusedAssets();
    }
    
    private void OnDestroy()
    {
        if (powerManager != null)
        {
            AITiOSPowerManager.OnPowerModeChanged -= OnPowerModeChanged;
            AITiOSPowerManager.OnThermalStateChanged -= OnThermalStateChanged;
        }
    }
}

[System.Serializable]
public class MetalPerformanceStats
{
    public float currentGPUFrameTime;    // ms
    public int currentDrawCalls;
    public int metalMemoryUsage;         // MB
    public int maxMetalMemory;           // MB
    public float averageFrameTime;       // ms
    public bool isMetalFXEnabled;
    public int memoryPressureLevel;      // 0-3 (없음-높음)
    
    public float GetMemoryUsageRatio()
    {
        return maxMetalMemory > 0 ? (float)metalMemoryUsage / maxMetalMemory : 0f;
    }
    
    public string GetPerformanceRating()
    {
        if (averageFrameTime < 16.67f) return "Excellent"; // 60+ FPS
        if (averageFrameTime < 22.22f) return "Good";      // 45+ FPS
        if (averageFrameTime < 33.33f) return "Fair";      // 30+ FPS
        return "Poor";                                      // <30 FPS
    }
    
    public string GetMemoryPressureText()
    {
        return memoryPressureLevel switch
        {
            0 => "없음",
            1 => "낮음",
            2 => "보통",
            3 => "높음",
            _ => "알 수 없음"
        };
    }
}

3. 네이티브 iOS 통합 코드

objective-c
// iOS Native - AITiOSPowerBridge.mm
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <sys/sysctl.h>
#import <mach/mach.h>
#import <Metal/Metal.h>

extern "C" {
    // 배터리 관련 함수들
    float GetBatteryLevel() {
        UIDevice *device = [UIDevice currentDevice];
        device.batteryMonitoringEnabled = YES;
        return device.batteryLevel;
    }
    
    int GetBatteryState() {
        UIDevice *device = [UIDevice currentDevice];
        device.batteryMonitoringEnabled = YES;
        return (int)device.batteryState;
    }
    
    bool IsLowPowerModeEnabled() {
        NSProcessInfo *processInfo = [NSProcessInfo processInfo];
        return processInfo.isLowPowerModeEnabled;
    }
    
    // 열 상태 관련 함수들
    float GetThermalState() {
        NSProcessInfo *processInfo = [NSProcessInfo processInfo];
        return (float)processInfo.thermalState;
    }
    
    // 프레임레이트 설정
    void SetPreferredFrameRate(int frameRate) {
        if (@available(iOS 10.3, *)) {
            [UIScreen mainScreen].maximumFramesPerSecond = frameRate;
        }
    }
    
    // Metal 관련 함수들
    void EnableMetalPerformanceShaders(bool enabled) {
        // MetalPerformanceShaders 활성화/비활성화
        // 실제 구현은 렌더링 파이프라인에 따라 달라집니다
    }
    
    void EnableMetalFX(bool enabled) {
        if (@available(iOS 16.0, *)) {
            // MetalFX 업스케일링 설정
            // 실제 구현 필요
        }
    }
    
    void SetMetalMemoryBudget(int megabytes) {
        // Metal 메모리 예산 설정
        // 실제 구현 필요
    }
    
    int GetMetalMemoryUsage() {
        // 현재 Metal 메모리 사용량 반환
        // 실제 구현 필요
        return 0;
    }
    
    void OptimizeMetalPipelines() {
        // Metal 파이프라인 최적화
        // 실제 구현 필요
    }
    
    float GetGPUFrameTime() {
        // GPU 프레임 시간 측정
        // 실제 구현 필요
        return 16.67f; // 60 FPS 기본값
    }
    
    int GetActiveDrawCalls() {
        // 현재 드로우콜 수 반환
        // 실제 구현 필요
        return 100;
    }
    
    // CPU/GPU 사용률 측정
    float GetProcessorUsage() {
        host_cpu_load_info_data_t cpuinfo;
        mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
        
        if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, 
            (host_info_t)&cpuinfo, &count) == KERN_SUCCESS) {
            
            unsigned long totalTicks = cpuinfo.cpu_ticks[CPU_STATE_USER] + 
                                      cpuinfo.cpu_ticks[CPU_STATE_SYSTEM] + 
                                      cpuinfo.cpu_ticks[CPU_STATE_IDLE] + 
                                      cpuinfo.cpu_ticks[CPU_STATE_NICE];
            
            unsigned long usedTicks = totalTicks - cpuinfo.cpu_ticks[CPU_STATE_IDLE];
            
            return (float)usedTicks / totalTicks;
        }
        
        return 0.0f;
    }
    
    float GetGPUUsage() {
        // GPU 사용률 측정 (복잡한 구현 필요)
        // 간단한 추정값 반환
        return 0.5f;
    }
    
    // 시스템 알림 등록
    void RegisterForPowerNotifications() {
        // 배터리 상태 변경 알림
        [[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceBatteryStateDidChangeNotification
                                                          object:nil
                                                           queue:[NSOperationQueue mainQueue]
                                                      usingBlock:^(NSNotification *notification) {
            UnitySendMessage("AITiOSPowerManager", "OnBatteryStateChanged", "changed");
        }];
        
        // 저전력 모드 변경 알림
        [[NSNotificationCenter defaultCenter] addObserverForName:NSProcessInfoPowerStateDidChangeNotification
                                                          object:nil
                                                           queue:[NSOperationQueue mainQueue]
                                                      usingBlock:^(NSNotification *notification) {
            NSProcessInfo *processInfo = [NSProcessInfo processInfo];
            const char* enabled = processInfo.isLowPowerModeEnabled ? "true" : "false";
            UnitySendMessage("AITiOSPowerManager", "OnLowPowerModeChangedNative", enabled);
        }];
        
        // 열 상태 변경 알림 (iOS 11+)
        if (@available(iOS 11.0, *)) {
            [[NSNotificationCenter defaultCenter] addObserverForName:NSProcessInfoThermalStateDidChangeNotification
                                                              object:nil
                                                               queue:[NSOperationQueue mainQueue]
                                                          usingBlock:^(NSNotification *notification) {
                NSProcessInfo *processInfo = [NSProcessInfo processInfo];
                NSString *thermalState = @"";
                switch (processInfo.thermalState) {
                    case NSProcessInfoThermalStateNominal:
                        thermalState = @"nominal";
                        break;
                    case NSProcessInfoThermalStateFair:
                        thermalState = @"fair";
                        break;
                    case NSProcessInfoThermalStateSerious:
                        thermalState = @"serious";
                        break;
                    case NSProcessInfoThermalStateCritical:
                        thermalState = @"critical";
                        break;
                }
                UnitySendMessage("AITiOSPowerManager", "OnThermalStateChangedNative", 
                               [thermalState UTF8String]);
            }];
        }
    }
}

코드 예제 및 설정

1. 앱인토스 통합 전력 관리

c#
// Unity C# - 앱인토스 통합 전력 관리
using UnityEngine;

public class AITIntegratedPowerManager : MonoBehaviour
{
    private AITiOSPowerManager powerManager;
    private AITMetalOptimizer metalOptimizer;
    private AITParticleBudgetManager particleBudgetManager;
    
    [Header("앱인토스 통합 설정")]
    public bool enableTossAppIntegration = true;        // 토스 앱과의 통합
    public bool enableBackgroundOptimization = true;    // 백그라운드 최적화
    public bool enablePredictivePowerManagement = true; // 예측적 전력 관리
    
    private void Start()
    {
        powerManager = AITiOSPowerManager.Instance;
        metalOptimizer = FindObjectOfType<AITMetalOptimizer>();
        particleBudgetManager = AITParticleBudgetManager.Instance;
        
        InitializeIntegratedPowerManagement();
    }
    
    private void InitializeIntegratedPowerManagement()
    {
        if (powerManager != null)
        {
            // 전력 관리 이벤트 구독
            AITiOSPowerManager.OnPowerModeChanged += OnPowerModeChanged;
            AITiOSPowerManager.OnThermalStateChanged += OnThermalStateChanged;
            AITiOSPowerManager.OnLowPowerModeEnabled += OnLowPowerModeEnabled;
        }
        
        // 토스 앱과의 통합 설정
        if (enableTossAppIntegration)
        {
            ConfigureTossAppIntegration();
        }
        
        Debug.Log("[AIT Integrated] 통합 전력 관리 초기화 완료");
    }
    
    private void ConfigureTossAppIntegration()
    {
        // 토스 앱의 전력 정책에 맞춰 설정 조정
        #if UNITY_WEBGL && !UNITY_EDITOR
        // WebView 환경에서의 최적화
        Application.ExternalCall("configureTossAppPowerIntegration");
        #endif
        
        // 토스 앱의 백그라운드 정책에 맞춰 조정
        if (enableBackgroundOptimization)
        {
            Application.focusChanged += OnTossAppFocusChanged;
        }
    }
    
    private void OnPowerModeChanged(AITiOSPowerManager.PowerMode newMode)
    {
        Debug.Log($"[AIT Integrated] 전력 모드 변경: {newMode}");
        
        // 모든 시스템에 전력 모드 변경 전달
        ApplyIntegratedPowerSettings(newMode);
        
        // 토스 앱에 전력 상태 알림
        if (enableTossAppIntegration)
        {
            NotifyTossAppPowerChange(newMode);
        }
    }
    
    private void ApplyIntegratedPowerSettings(AITiOSPowerManager.PowerMode mode)
    {
        switch (mode)
        {
            case AITiOSPowerManager.PowerMode.HighPerformance:
                ApplyHighPerformanceIntegration();
                break;
                
            case AITiOSPowerManager.PowerMode.Balanced:
                ApplyBalancedIntegration();
                break;
                
            case AITiOSPowerManager.PowerMode.PowerSaving:
                ApplyPowerSavingIntegration();
                break;
                
            case AITiOSPowerManager.PowerMode.UltraPowerSaving:
                ApplyUltraPowerSavingIntegration();
                break;
        }
    }
    
    private void ApplyHighPerformanceIntegration()
    {
        // Unity 최고 품질 설정
        QualitySettings.SetQualityLevel(QualitySettings.names.Length - 1);
        
        // 파티클 시스템 고품질
        particleBudgetManager?.SetGlobalQuality(AITParticleBudgetManager.ParticleSystemInfo.QualityLevel.High);
        
        // Metal 최적화 해제 (최고 품질을 위해)
        // metalOptimizer는 자체적으로 전력 모드 변경을 감지하므로 별도 호출 불필요
        
        Debug.Log("[AIT Integrated] 고성능 통합 설정 적용");
    }
    
    private void ApplyBalancedIntegration()
    {
        // 균형잡힌 품질 설정
        int balancedQuality = Mathf.RoundToInt(QualitySettings.names.Length * 0.6f);
        QualitySettings.SetQualityLevel(balancedQuality);
        
        // 파티클 시스템 중품질
        particleBudgetManager?.SetGlobalQuality(AITParticleBudgetManager.ParticleSystemInfo.QualityLevel.Medium);
        
        Debug.Log("[AIT Integrated] 균형 통합 설정 적용");
    }
    
    private void ApplyPowerSavingIntegration()
    {
        // 절전 품질 설정
        int powerSavingQuality = Mathf.RoundToInt(QualitySettings.names.Length * 0.3f);
        QualitySettings.SetQualityLevel(powerSavingQuality);
        
        // 파티클 시스템 저품질
        particleBudgetManager?.SetGlobalQuality(AITParticleBudgetManager.ParticleSystemInfo.QualityLevel.Low);
        
        // 추가 절전 최적화
        AudioListener.volume = 0.7f;  // 오디오 볼륨 감소
        Screen.brightness = Mathf.Max(0.3f, Screen.brightness * 0.8f);  // 화면 밝기 감소
        
        Debug.Log("[AIT Integrated] 절전 통합 설정 적용");
    }
    
    private void ApplyUltraPowerSavingIntegration()
    {
        // 극한 절전 설정
        QualitySettings.SetQualityLevel(0);
        
        // 파티클 시스템 비활성화
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        foreach (var ps in particleSystems)
        {
            ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
        }
        
        // 오디오 최소화
        AudioListener.volume = 0.3f;
        AudioListener.pause = true;
        
        // 업데이트 빈도 감소
        Time.fixedDeltaTime = 0.1f;  // 물리 업데이트 10Hz로 감소
        
        Debug.LogWarning("[AIT Integrated] 극한 절전 통합 설정 적용");
    }
    
    private void OnThermalStateChanged(AITiOSPowerManager.ThermalState thermalState)
    {
        Debug.Log($"[AIT Integrated] 열 상태 변경: {thermalState}");
        
        // 심각한 열 상태에서는 즉시 절전 모드로 전환
        if (thermalState >= AITiOSPowerManager.ThermalState.Serious)
        {
            ApplyEmergencyThermalProtection();
        }
    }
    
    private void ApplyEmergencyThermalProtection()
    {
        Debug.LogWarning("[AIT Integrated] 긴급 열 보호 모드 활성화");
        
        // 즉시 최저 성능으로 전환
        Application.targetFrameRate = 15;  // 15 FPS로 제한
        
        // 모든 애니메이션 일시정지
        var animators = FindObjectsOfType<Animator>();
        foreach (var animator in animators)
        {
            animator.speed = 0.5f;  // 애니메이션 속도 50% 감소
        }
        
        // 렌더링 스케일 대폭 감소
        UnityEngine.XR.XRSettings.renderViewportScale = 0.4f;
        
        // 파티클 완전 중단
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        foreach (var ps in particleSystems)
        {
            ps.Pause();
        }
    }
    
    private void OnLowPowerModeEnabled()
    {
        Debug.Log("[AIT Integrated] iOS 저전력 모드 감지 - 즉시 절전 모드 전환");
        
        // 저전력 모드가 활성화되면 즉시 절전 설정 적용
        powerManager?.SetPowerMode(AITiOSPowerManager.PowerMode.PowerSaving);
    }
    
    private void OnTossAppFocusChanged(bool hasFocus)
    {
        if (hasFocus)
        {
            // 토스 앱 포그라운드 - 정상 성능 복원
            Debug.Log("[AIT Integrated] 토스 앱 포그라운드 - 성능 복원");
            RestoreNormalPerformance();
        }
        else
        {
            // 토스 앱 백그라운드 - 최소 성능으로 전환
            Debug.Log("[AIT Integrated] 토스 앱 백그라운드 - 최소 성능 전환");
            ApplyBackgroundMinimization();
        }
    }
    
    private void RestoreNormalPerformance()
    {
        // 현재 전력 상태에 맞는 설정으로 복원
        if (powerManager != null)
        {
            var currentState = powerManager.GetCurrentPowerState();
            
            if (currentState.isLowPowerMode)
            {
                ApplyPowerSavingIntegration();
            }
            else if (currentState.batteryLevel > 0.5f)
            {
                ApplyBalancedIntegration();
            }
            else
            {
                ApplyPowerSavingIntegration();
            }
        }
        
        // 오디오 복원
        AudioListener.pause = false;
        AudioListener.volume = 1f;
        
        // 애니메이션 속도 복원
        var animators = FindObjectsOfType<Animator>();
        foreach (var animator in animators)
        {
            animator.speed = 1f;
        }
    }
    
    private void ApplyBackgroundMinimization()
    {
        // 백그라운드에서 최소 성능 유지
        Application.targetFrameRate = 5;  // 5 FPS로 극도로 제한
        
        // 모든 파티클 일시정지
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        foreach (var ps in particleSystems)
        {
            ps.Pause();
        }
        
        // 오디오 일시정지
        AudioListener.pause = true;
        AudioListener.volume = 0f;
        
        // 물리 업데이트 최소화
        Time.fixedDeltaTime = 0.2f;  // 5Hz 물리 업데이트
    }
    
    private void NotifyTossAppPowerChange(AITiOSPowerManager.PowerMode mode)
    {
        #if UNITY_WEBGL && !UNITY_EDITOR
        string modeString = mode.ToString();
        Application.ExternalCall("onUnityPowerModeChanged", modeString);
        #endif
    }
    
    // 공개 API 메서드들
    public PowerPerformanceStats GetIntegratedStats()
    {
        var stats = powerManager?.GetPerformanceStats();
        if (stats == null)
        {
            return new PowerPerformanceStats();
        }
        
        // Metal 통계 추가
        if (metalOptimizer != null)
        {
            var metalStats = metalOptimizer.GetMetalPerformanceStats();
            // 통합 통계 생성 (구현 필요)
        }
        
        return stats;
    }
    
    public void ForceOptimization()
    {
        Debug.Log("[AIT Integrated] 강제 통합 최적화 실행");
        
        // 모든 시스템 최적화
        powerManager?.ForcePowerModeUpdate();
        metalOptimizer?.ForceMetalOptimization();
        particleBudgetManager?.ForceCleanup();
        
        // 메모리 정리
        System.GC.Collect();
        Resources.UnloadUnusedAssets();
    }
    
    private void OnDestroy()
    {
        if (powerManager != null)
        {
            AITiOSPowerManager.OnPowerModeChanged -= OnPowerModeChanged;
            AITiOSPowerManager.OnThermalStateChanged -= OnThermalStateChanged;
            AITiOSPowerManager.OnLowPowerModeEnabled -= OnLowPowerModeEnabled;
        }
        
        if (enableBackgroundOptimization)
        {
            Application.focusChanged -= OnTossAppFocusChanged;
        }
    }
}

문제 해결 및 디버깅

1. iOS 전력 문제 진단 도구

c#
// Unity C# - iOS 전력 문제 진단기
public class AITiOSPowerDiagnostic : MonoBehaviour
{
    private AITiOSPowerManager powerManager;
    
    [ContextMenu("배터리 상태 진단")]
    public void DiagnoseBatteryIssues()
    {
        if (powerManager == null)
        {
            powerManager = AITiOSPowerManager.Instance;
        }
        
        var powerStats = powerManager?.GetPerformanceStats();
        if (powerStats == null)
        {
            Debug.LogError("[AIT Diagnostic] 전력 관리자를 찾을 수 없음");
            return;
        }
        
        Debug.Log("=== iOS 전력 진단 결과 ===");
        Debug.Log($"배터리 수준: {powerStats.batteryLevel:P0} ({powerStats.GetBatteryStatus()})");
        Debug.Log($"저전력 모드: {(powerStats.isLowPowerMode ? "활성화" : "비활성화")}");
        Debug.Log($"열 상태: {powerStats.GetThermalStatus()}");
        Debug.Log($"현재 FPS: {powerStats.currentFPS}");
        Debug.Log($"CPU 사용률: {powerStats.cpuUsage:P1}");
        Debug.Log($"GPU 사용률: {powerStats.gpuUsage:P1}");
        Debug.Log($"예상 전력 소모: {powerStats.estimatedPowerConsumption:F0} mW");
        Debug.Log($"예상 배터리 수명: {powerStats.estimatedBatteryLife:F1} 시간");
        Debug.Log($"성능 등급: {powerStats.GetPerformanceGrade()}");
        
        // 문제 상황 감지
        DetectPowerIssues(powerStats);
    }
    
    private void DetectPowerIssues(PowerPerformanceStats stats)
    {
        Debug.Log("\n=== 감지된 문제점 ===");
        
        if (stats.batteryLevel <= 0.1f)
        {
            Debug.LogError("위험: 배터리 수준이 매우 낮음 (10% 이하)");
            Debug.LogError("권장사항: 즉시 극한 절전 모드 적용 필요");
        }
        else if (stats.batteryLevel <= 0.2f)
        {
            Debug.LogWarning("경고: 배터리 수준이 낮음 (20% 이하)");
            Debug.LogWarning("권장사항: 절전 모드 적용 권장");
        }
        
        if (stats.thermalState >= AITiOSPowerManager.ThermalState.Serious)
        {
            Debug.LogError($"위험: 심각한 열 상태 ({stats.GetThermalStatus()})");
            Debug.LogError("권장사항: 즉시 성능 제한 필요");
        }
        
        if (stats.currentFPS < 20)
        {
            Debug.LogWarning($"성능: 낮은 프레임레이트 ({stats.currentFPS} FPS)");
            Debug.LogWarning("권장사항: 그래픽 설정 최적화 필요");
        }
        
        if (stats.cpuUsage > 0.8f)
        {
            Debug.LogWarning($"성능: 높은 CPU 사용률 ({stats.cpuUsage:P0})");
            Debug.LogWarning("권장사항: CPU 집약적 작업 최적화 필요");
        }
        
        if (stats.gpuUsage > 0.85f)
        {
            Debug.LogWarning($"성능: 높은 GPU 사용률 ({stats.gpuUsage:P0})");
            Debug.LogWarning("권장사항: 렌더링 최적화 필요");
        }
        
        if (stats.estimatedBatteryLife < 1f)
        {
            Debug.LogError($"위험: 예상 배터리 수명이 매우 짧음 ({stats.estimatedBatteryLife:F1} 시간)");
            Debug.LogError("권장사항: 전력 소모 대폭 감소 필요");
        }
    }
    
    [ContextMenu("성능 최적화 권장사항")]
    public void SuggestOptimizations()
    {
        Debug.Log("=== 성능 최적화 권장사항 ===");
        
        // 현재 Unity 설정 분석
        AnalyzeUnitySettings();
        
        // 프로젝트별 최적화 제안
        AnalyzeProjectOptimizations();
    }
    
    private void AnalyzeUnitySettings()
    {
        Debug.Log("\n--- Unity 설정 분석 ---");
        
        Debug.Log($"현재 품질 레벨: {QualitySettings.names[QualitySettings.GetQualityLevel()]}");
        Debug.Log($"목표 프레임레이트: {Application.targetFrameRate}");
        Debug.Log($"V-Sync: {(QualitySettings.vSyncCount > 0 ? "활성화" : "비활성화")}");
        Debug.Log($"그림자 품질: {QualitySettings.shadows}");
        Debug.Log($"안티앨리어싱: {QualitySettings.antiAliasing}");
        Debug.Log($"텍스처 제한: {QualitySettings.masterTextureLimit}");
        
        // 권장사항 제시
        if (QualitySettings.GetQualityLevel() > 3)
        {
            Debug.LogWarning("권장사항: 모바일에서는 중간 품질 레벨 사용 권장");
        }
        
        if (Application.targetFrameRate > 30)
        {
            Debug.LogWarning("권장사항: 배터리 절약을 위해 30 FPS 제한 고려");
        }
        
        if (QualitySettings.vSyncCount > 0)
        {
            Debug.LogWarning("권장사항: 모바일에서 V-Sync 비활성화로 성능 향상");
        }
    }
    
    private void AnalyzeProjectOptimizations()
    {
        Debug.Log("\n--- 프로젝트 최적화 분석 ---");
        
        // 오브젝트 수 분석
        int totalGameObjects = FindObjectsOfType<GameObject>().Length;
        Debug.Log($"총 GameObject 수: {totalGameObjects}");
        if (totalGameObjects > 1000)
        {
            Debug.LogWarning("권장사항: GameObject 수가 많음, 오브젝트 풀링 고려");
        }
        
        // 렌더러 분석
        var renderers = FindObjectsOfType<Renderer>();
        Debug.Log($"총 Renderer 수: {renderers.Length}");
        
        int shadowCastingRenderers = 0;
        foreach (var renderer in renderers)
        {
            if (renderer.shadowCastingMode != UnityEngine.Rendering.ShadowCastingMode.Off)
            {
                shadowCastingRenderers++;
            }
        }
        
        if (shadowCastingRenderers > 100)
        {
            Debug.LogWarning($"권장사항: 그림자 생성 오브젝트가 많음 ({shadowCastingRenderers}개)");
        }
        
        // 라이트 분석
        var lights = FindObjectsOfType<Light>();
        Debug.Log($"총 Light 수: {lights.Length}");
        if (lights.Length > 5)
        {
            Debug.LogWarning("권장사항: 라이트 수가 많음, 베이크드 라이팅 고려");
        }
        
        // 파티클 시스템 분석
        var particleSystems = FindObjectsOfType<ParticleSystem>();
        int activeParticles = 0;
        foreach (var ps in particleSystems)
        {
            activeParticles += ps.particleCount;
        }
        
        Debug.Log($"총 ParticleSystem 수: {particleSystems.Length}");
        Debug.Log($"활성 파티클 수: {activeParticles}");
        
        if (activeParticles > 1000)
        {
            Debug.LogWarning("권장사항: 활성 파티클 수가 많음, 파티클 예산 관리 적용");
        }
    }
    
    [ContextMenu("메모리 사용량 분석")]
    public void AnalyzeMemoryUsage()
    {
        Debug.Log("=== 메모리 사용량 분석 ===");
        
        // Unity 메모리 분석
        long totalMemory = UnityEngine.Profiling.Profiler.GetTotalAllocatedMemory(UnityEngine.Profiling.Profiler.Area.Total);
        long managedMemory = System.GC.GetTotalMemory(false);
        
        Debug.Log($"총 할당 메모리: {totalMemory / 1024 / 1024} MB");
        Debug.Log($"관리 메모리: {managedMemory / 1024 / 1024} MB");
        
        // 텍스처 메모리 분석
        var textures = Resources.FindObjectsOfTypeAll<Texture>();
        long textureMemory = 0;
        int largeTextures = 0;
        
        foreach (var texture in textures)
        {
            if (texture is Texture2D tex2D)
            {
                // 대략적인 텍스처 메모리 계산
                int texSize = tex2D.width * tex2D.height * 4; // RGBA 가정
                textureMemory += texSize;
                
                if (tex2D.width > 1024 || tex2D.height > 1024)
                {
                    largeTextures++;
                }
            }
        }
        
        Debug.Log($"텍스처 메모리 (추정): {textureMemory / 1024 / 1024} MB");
        Debug.Log($"대형 텍스처 (1024x1024 이상): {largeTextures}개");
        
        if (textureMemory / 1024 / 1024 > 100)
        {
            Debug.LogWarning("권장사항: 텍스처 메모리 사용량이 높음, 압축 또는 다운스케일 고려");
        }
        
        if (largeTextures > 10)
        {
            Debug.LogWarning("권장사항: 대형 텍스처가 많음, 아틀라싱 또는 크기 최적화 권장");
        }
    }
}

관련 도구 및 리소스

1. Xcode Instruments 통합

objective-c
// iOS Native - Instruments 통합을 위한 코드
#import <os/log.h>
#import <os/signpost.h>

// 성능 측정을 위한 Signpost
static os_log_t ait_performance_log;
static os_signpost_id_t ait_frame_signpost;

void InitializeInstrumentsIntegration() {
    ait_performance_log = os_log_create("com.appintoss.unity", "Performance");
    ait_frame_signpost = os_signpost_id_generate(ait_performance_log);
}

void BeginFrameSignpost() {
    os_signpost_interval_begin(ait_performance_log, ait_frame_signpost, "Frame");
}

void EndFrameSignpost() {
    os_signpost_interval_end(ait_performance_log, ait_frame_signpost, "Frame");
}

void LogPowerEvent(const char* event, const char* details) {
    os_log_with_type(ait_performance_log, OS_LOG_TYPE_INFO, 
                     "Power Event: %{public}s - %{public}s", event, details);
}

2. 자동화된 성능 테스트 도구

c#
// Unity C# - 자동화된 성능 테스트
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;

public class AITiOSPerformanceTestSuite : EditorWindow
{
    private bool isTestRunning = false;
    private float testProgress = 0f;
    private string testStatus = "준비";
    
    [MenuItem("앱인토스/iOS 성능 테스트 도구")]
    public static void ShowWindow()
    {
        GetWindow<AITiOSPerformanceTestSuite>("iOS 성능 테스트");
    }
    
    private void OnGUI()
    {
        GUILayout.Label("iOS 성능 테스트 도구", EditorStyles.boldLabel);
        
        EditorGUILayout.Space();
        
        // 테스트 상태
        EditorGUILayout.LabelField("상태", testStatus);
        
        if (isTestRunning)
        {
            EditorGUILayout.Slider(testProgress, 0f, 1f);
        }
        
        EditorGUILayout.Space();
        
        // 테스트 실행 버튼들
        EditorGUI.BeginDisabledGroup(isTestRunning);
        
        if (GUILayout.Button("배터리 소모 테스트"))
        {
            StartBatteryDrainTest();
        }
        
        if (GUILayout.Button("열 성능 테스트"))
        {
            StartThermalPerformanceTest();
        }
        
        if (GUILayout.Button("메모리 사용량 테스트"))
        {
            StartMemoryUsageTest();
        }
        
        if (GUILayout.Button("종합 성능 테스트"))
        {
            StartComprehensiveTest();
        }
        
        EditorGUI.EndDisabledGroup();
        
        if (isTestRunning && GUILayout.Button("테스트 중단"))
        {
            StopCurrentTest();
        }
    }
    
    private void StartBatteryDrainTest()
    {
        Debug.Log("[AIT Test] 배터리 소모 테스트 시작");
        testStatus = "배터리 테스트 실행 중...";
        isTestRunning = true;
        
        // 실제 배터리 테스트 로직 구현
        EditorApplication.delayCall += () => {
            // 테스트 완료 후
            testStatus = "배터리 테스트 완료";
            isTestRunning = false;
        };
    }
    
    private void StartThermalPerformanceTest()
    {
        Debug.Log("[AIT Test] 열 성능 테스트 시작");
        testStatus = "열 성능 테스트 실행 중...";
        isTestRunning = true;
        
        // GPU 집약적 작업을 통한 열 테스트
    }
    
    private void StartMemoryUsageTest()
    {
        Debug.Log("[AIT Test] 메모리 사용량 테스트 시작");
        testStatus = "메모리 테스트 실행 중...";
        isTestRunning = true;
        
        // 메모리 할당/해제를 통한 메모리 테스트
    }
    
    private void StartComprehensiveTest()
    {
        Debug.Log("[AIT Test] 종합 성능 테스트 시작");
        testStatus = "종합 테스트 실행 중...";
        isTestRunning = true;
        
        // 모든 테스트를 순차적으로 실행
    }
    
    private void StopCurrentTest()
    {
        testStatus = "테스트 중단됨";
        isTestRunning = false;
        testProgress = 0f;
    }
}
#endif

모범 사례

1. iOS 전력 최적화 체크리스트

배터리 최적화

  • 저전력 모드 감지 및 자동 적응
  • 배터리 수준별 성능 조정
  • 백그라운드에서 최소 동작
  • 불필요한 센서 사용 중단

열 관리

  • 열 상태 모니터링
  • CPU/GPU 사용률 제한
  • 동적 품질 조정
  • 긴급 성능 제한

메모리 관리

  • Metal 메모리 예산 설정
  • 텍스처 크기 최적화
  • 정기적 메모리 정리
  • 메모리 압박 상황 대응

성능 최적화

  • 적응형 프레임레이트
  • LOD 시스템 적용
  • 드로우콜 최소화
  • 파티클 예산 관리

2. 토스 앱 통합 고려사항

1. 토스 앱의 전력 정책 준수

  • 토스 앱의 백그라운드 정책에 맞춰 동작
  • 다른 토스 서비스와의 리소스 공유 고려

2. 사용자 경험 최적화

  • 배터리 부족 시 자동 절전 모드
  • 성능 저하 시 적절한 사용자 알림

3. 모니터링 및 분석

  • 실사용 환경에서의 전력 소모 데이터 수집
  • A/B 테스트를 통한 최적화 효과 검증

이러한 iOS 전력 및 성능 관리 시스템을 통해 앱인토스 플랫폼에서 배터리 효율성과 사용자 경험을 동시에 최적화할 수 있어요.