Swift/UIKit 개발 노트

[SwiftUI] 전역적인 햅틱 관리 HapticsManager 2.2.0

힛해 2025. 4. 29. 18:08
728x90

https://github.com/markbattistella/HapticsManager

 

GitHub - markbattistella/HapticsManager: HapticsManager is a Swift package that provides a modular and easy-to-use interface for

HapticsManager is a Swift package that provides a modular and easy-to-use interface for implementing haptic feedback in your applications. It integrates seamlessly with SwiftUI, enabling you to enh...

github.com

 

 

앱을 만들면서 전역적으로 햅틱(진동) 사용을 온/오프할 수 있는 기능이 필요했다. 

 

SwiftUI 5(iOS 17)부터는 .sensoryFeedback 같은 내장 API도 있지만, 

 

이 방식은 앱을 껐다 켜면 설정이 유지되지 않고, 전역 상태 관리도 불편하다. 

 

그래서 HapticsManager 라이브러리를 도입했다. 

 

1. 앱 시작 시 전역 설정값 등록 

공식 문서에는 아래처럼 등록하라고 안내되어 있다.

@main
struct MyAwesomeApp: App {

  init() {
    UserDefaults.haptic.register([
      HapticUserDefaultsKey.hapticEffectsEnabled : true
    ])
  }

  var body: some Scene {
    WindowGroup { ... }
  }
}

 

 

하지만 실제로는 위 코드가 동작하지 않는다. 

UserDefaults 내부 네이밍과 선언 방법이 바뀌어서 아래처럼 써야 정상적으로 동작한다.

 

UserDefaults.haptics.register(defaults: [
    HapticUserDefaultsKey.hapticEffectsEnabled.rawValue: true
])

 

라이브러리 업뎃이 멈췃는지 이렇게 해줘야한다.

 

전역적인 진동 설정 값 관리

@AppStorage(HapticUserDefaultsKey.hapticEffectsEnabled.rawValue, store: .haptics)
var isHapticsEnabled: Bool = true

Button("Turn haptics off") {
    UserDefaults.haptics.set(false, for: HapticUserDefaultsKey.hapticEffectsEnabled.rawValue)
}

Button("Turn haptics on") {
    UserDefaults.haptics.set(true, for: HapticUserDefaultsKey.hapticEffectsEnabled.rawValue)
}

 

 

버튼에서 햅틱 사용

HapticsManager는 SwiftUI의 View Modifier 방식으로 햅틱을 적용한다.

import HapticsManager

@State private var isSuccess: Bool = false

Button(action: { isSuccess.toggle() }) {
    Text("구르기")
}
.hapticFeedback(.impact(.medium), trigger: isSuccess)

 

트리거 방식의 아쉬움

햅틱 설정은 전역적으로 관리하면서, 실제 실행은 지역 변수 트리거를 통해 이루어지는 구조가 비효율적으로 느껴진다.

 

버튼을 누르는 행위 자체가 트리거가 될 수 있을 텐데, 굳이 별도의 상태 변수를 만들어서 토글해야 한다는 점이 아쉽다.

 

SwiftUI의 Modifier 시스템이 "값의 변화"에 반응하는 구조라 어쩔 수 없는 부분이지만,

 

페이지가 많아질수록 이 패턴을 반복하는 게 번거롭게 느껴진다. 

 

개선 방향

현 시점에서는 HapticsManager의 전역 설정값을 활용해 앱 전체 진동 온/오프를 안전하게 관리할 수 있다.

 

하지만, 버튼마다 별도의 트리거 변수를 만들어야 하는 구조는 대규모 프로젝트에서 불편할 수 있다.

 

임시로 이 구조를 사용하되, 추후에는 전역적으로 사용할 수 있는 햅틱 래퍼 함수나 커스텀 버튼 컴포넌트로 개선하는 방안을 적용해야겠다.

(그치만 버튼마다 디자인이 달라서...)