1. 개요
Flutter에서 상태 관리를 위해 널리 사용되는 두 가지 라이브러리는 Provider와 Riverpod입니다. 이번 포스팅에서는 기존에 사용하던 Provider를 Riverpod으로 마이그레이션하면서 얻은 이점, 두 상태 관리 라이브러리의 주요 차이점, 그리고 마이그레이션 과정에서 직면했던 문제와 해결 과정을 공유하고자 합니다.
2. Provider와 Riverpod의 차이점
- 의존성 주입과 범위:
- Provider는 위젯 트리에 의존성을 주입하여 하위 위젯에서 데이터를 공유할 수 있게 해줍니다. 하지만 복잡한 애플리케이션에서는 의존성의 범위(scope)를 관리하기 어려울 수 있습니다.
- 반면, Riverpod은 ProviderContainer를 사용하여 보다 명확하게 의존성의 범위를 지정할 수 있으며, 위젯 트리와 독립적으로 동작할 수 있습니다. 이로 인해 테스트와 코드 재사용이 훨씬 용이해집니다.
- 코드 유지보수성:
- Provider는 여러 파일에서 동일한 로직이 중복될 수 있어 코드 유지보수가 어려울 수 있습니다.
- Riverpod은 훨씬 더 명확하고 간결한 API를 제공하며, 상태를 선언적으로 정의할 수 있어 코드의 가독성과 유지보수성이 크게 향상됩니다.
- 퍼포먼스:
- Riverpod은 상태를 변경할 때 불필요한 위젯 리빌드를 방지하는 최적화를 기본적으로 제공합니다.
- Provider는 경우에 따라 필요 이상으로 많은 리빌드를 발생시킬 수 있으며, 이를 방지하기 위한 추가적인 코드 작성이 필요합니다.
3. 마이그레이션을 통해 얻은 이점
- 더 나은 가독성:
- Riverpod의 간결한 API 덕분에 코드가 더 명확해지고 읽기 쉬워졌습니다. 특히 의존성을 관리하고 상태를 조작하는 부분에서 직관적이고 선언적인 코드를 작성할 수 있었습니다.
- 유연한 상태 관리:
- Riverpod은 전역 상태 관리뿐만 아니라 지역 상태 관리에서도 뛰어난 유연성을 제공합니다. 이로 인해 상태를 관리하는 방식이 더 명확해지고, 불필요한 리빌드를 방지할 수 있었습니다.
- 테스트 용이성:
- Provider에서 상태를 테스트하려면 일부 설정이 필요했지만, Riverpod에서는 ProviderContainer를 사용하여 손쉽게 상태를 테스트할 수 있습니다. 이는 상태 관리 로직의 단위 테스트를 작성하는 데 큰 도움이 되었습니다.
4. 문제 해결 경험
마이그레이션 과정에서 여러 문제를 직면했는데, 그중 가장 흥미로웠던 경험은 의존성 관리와 관련된 것이었습니다.
문제:Riverpod으로 마이그레이션한 후, 특정 의존성이 올바르게 주입되지 않아 예상치 못한 Null 값이 발생했습니다. 이는 특히 복잡한 상태 관리와 비동기 로직이 결합된 코드에서 발생할 수 있는 문제였습니다.
해결:Riverpod의 ProviderScope와 ProviderContainer를 사용하여 의존성을 보다 명확하게 관리하고, 테스트를 통해 문제가 발생하는 부분을 식별했습니다. 이 과정에서 Riverpod의 강력한 의존성 주입 시스템이 큰 도움이 되었습니다.
5. 변경된 실제 코드
아래는 실제로 Riverpod으로 마이그레이션한 후, 심박수 측정을 시작하는 코드의 일부입니다.
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:smart_device/services/smart_device_service.dart';
import 'package:smart_device/providers/ble_sensor_provider.dart';
class SportsModeService {
SportsModeService(this.sportsMode, this.ref); // ref를 생성자 인자로 추가
final SportsMode sportsMode;
final WidgetRef ref; // ref를 WidgetRef로 수정
Future<void> startHeartRateMonitoring() async {
final sensorState = ref.read(sensorProvider.notifier); // ref 사용
try {
await SmartDeviceService.instance.setHeartRateMode(true);
} catch (e) {
print('심박수 측정 중 오류 발생: $e');
}
}
}
6. 결론
Provider에서 Riverpod으로 마이그레이션한 결과, 코드의 가독성과 유지보수성이 크게 향상되었으며, 복잡한 상태 관리 로직을 보다 효율적으로 관리할 수 있게 되었습니다. 또한 Riverpod의 명확한 의존성 관리와 뛰어난 테스트 용이성 덕분에 개발 생산성도 함께 향상되었습니다.