Mac이 열로 인해 성능 저하(thermal throttling) 상태인지 알려주는 macOS 앱 개발기

1 month ago 9

  • MacThrottle은 Mac이 과열로 인해 성능을 제한할 때 이를 메뉴 막대에서 시각적으로 알려주는 SwiftUI 기반 앱
  • macOS의 ProcessInfo.thermalState API와 powermetrics 명령어를 비교하며, 시스템의 실제 열 상태를 정확히 감지하기 위한 방법을 탐색
  • 최종적으로 thermald가 Darwin의 notifyd 시스템에 게시하는 알림을 활용해 루트 권한 없이 열 상태를 읽는 방식 구현
  • 앱은 온도·팬 속도 그래프, 상태별 색상 아이콘, macOS 알림 기능을 포함하며, 로그인 시 자동 실행도 지원
  • Apple Silicon Mac의 열 관리 상태를 실시간으로 파악할 수 있는 도구로, 개발자와 파워유저에게 유용한 진단 수단 제공

Mac의 열 스로틀링 문제 인식

  • M2 MacBook Air에서 외부 4K 120Hz 디스플레이 사용 시 성능 저하와 반응 지연이 발생
    • 팬이 없어 소음을 감지할 수 없지만, CPU 사용률이 100%인 상태에서 전력 사용량이 감소함
  • iStat Menus와 MX Power Gadget을 통해 CPU 주파수와 전력 하락을 확인하며 열 스로틀링을 진단
  • M4 Max MacBook Pro에서도 동일 현상 발생, 14인치 모델의 열 설계 한계로 인한 문제로 언급
  • Apple Silicon의 전력 효율은 여전히 높지만, 열 상태를 직접 감지할 방법을 찾고자 함

macOS에서 열 상태를 프로그래밍적으로 확인하기

  • macOS는 여러 방식으로 열 상태를 노출하지만 일관성이 부족
  • Apple이 권장하는 방법은 Foundation의 ProcessInfo.thermalState 사용
    • 출력 예시: nominal, fair, serious, critical
  • 루트 권한이 필요한 powermetrics -s thermal 명령어도 동일한 정보를 제공하지만,
    두 방식의 상태 구분 단위가 다름
    • 예: fair는 powermetrics의 moderate와 heavy 두 상태를 모두 포함
  • 실제 스로틀링 시점은 powermetrics에서 heavy로 표시되지만, ProcessInfo에서는 구분 불가

thermald와 Darwin 알림 시스템 활용

  • powermetrics의 데이터는 thermald 데몬에서 가져오며,
    thermald는 현재 열 압력 상태를 notifyd 시스템 이벤트로 게시
  • notifyutil -g com.apple.system.thermalpressurelevel 명령으로 상태 확인 가능
  • OSThermalNotification.h 헤더에서 정의된 열 압력 수준:
    • nominal, moderate, heavy, trapping, sleeping
  • Swift 코드로 notify_register_check와 notify_get_state를 호출해
    루트 권한 없이 실시간 열 상태를 읽는 기능 구현

MacThrottle 앱 개발

  • SwiftUI와 MenuBarExtra를 사용해 메뉴 막대 전용 앱 제작
    • 온도계 아이콘 색상으로 상태 표시 (녹색→적색)
    • Info.plist의 LSUIElement를 true로 설정해 Dock 아이콘 비활성화

초기 접근: powermetrics 루트 헬퍼

  • 초기에 루트 권한이 필요한 powermetrics를 사용하기 위해
    LaunchDaemon과 bash 스크립트로 헬퍼 프로세스 구성
    • /usr/local/bin/mac-throttle-thermal-monitor가 10초마다 상태를 /tmp 파일에 기록
    • 앱은 해당 파일을 주기적으로 읽어 표시

개선: thermald IPC 알림 사용

  • notifyd 이벤트를 직접 구독하는 방식으로 전환
    • 루트 권한 불필요, 코드 단순화

온도 및 팬 속도 표시

  • CPU/GPU 온도와 팬 속도를 그래프로 표시
  • 초기에는 IOKit 비공개 API 사용 시 온도가 실제보다 낮게 표시됨 (~80°C)
  • 오픈소스 Stats 프로젝트를 참고해 SMC 인터페이스로 전환
    • SoC 세대별로 다른 키(Tp0D, Tf0E 등)를 사용해야 함
  • SMC가 작동하지 않을 경우 IOKit으로 폴백

메뉴 막대 그래프 구현

  • 그래프는 3가지 정보를 동시에 표시
    • 배경 색상: 열 상태 (녹색~적색)
    • 실선: CPU 온도
    • 점선: 팬 속도 비율
  • 2초 간격으로 데이터 수집, 10분 단위 히스토리 유지
  • onContinuousHover로 툴팁 제공,
    .drawingGroup을 추가해 GPU 렌더링으로 120Hz 디스플레이에서도 부드럽게 표시

macOS 알림 및 자동 실행

  • 열 상태 변화 시 알림 전송 기능 추가
    • 특정 상태 전환이나 복구 시 알림 가능
  • SMAppService API로 로그인 시 자동 실행 설정 지원
    • register() / unregister() / status 메서드로 제어

배포 및 사용

  • Apple Developer 계정이 없어 공식 공증(notarization) 불가
    • GitHub 릴리스에서 설치 시 Privacy and Security에서 수동 승인 필요
    • 일부 Mac에서는 Xcode로 직접 빌드해야 실행 가능
  • 설치 및 빌드 방법은 GitHub README에 명시

결론

  • MacThrottle은 Apple Silicon Mac의 열 스로틀링 상태를 실시간 감시할 수 있는 경량 도구
  • 루트 권한 없이 동작하며, 시각적 피드백·알림·그래프 기능을 통해
    개발자와 고성능 작업 사용자에게 시스템 열 상태 인식을 제공

Read Entire Article