1. 문제 상황
Flutter로 운동 모드를 개발하는 중, 스탑워치 기능을 구현하면서 한 가지 중요한 문제가 발생했습니다. 스탑워치가 화면 이동이나 앱이 백그라운드로 전환되었을 때에도 계속 작동해야 했지만, 기본적인 Stopwatch 클래스는 이 요구 사항을 충족하지 못했습니다. 특히, 앱이 백그라운드로 전환되면 스탑워치가 멈추고, 다시 포그라운드로 돌아왔을 때 경과 시간이 정확히 유지되지 않는 문제가 있었습니다.
2. 기존 코드와의 문제점
기존의 Stopwatch 클래스는 앱이 포그라운드에 있을 때는 잘 작동했지만, 백그라운드로 전환되면 상태를 저장하거나 복원할 수 있는 방법이 제공되지 않았습니다. 이는 다음과 같은 문제를 야기했습니다:
- 앱이 백그라운드로 전환되면: 스탑워치의 시간이 정지되어, 다시 포그라운드로 돌아왔을 때 사용자는 정확한 시간을 확인할 수 없었습니다.
- 앱이 재실행되면: 스탑워치의 상태가 초기화되어, 이전에 경과된 시간이 사라지고 처음부터 다시 시작되는 문제가 있었습니다.
3. 해결 방법
이 문제를 해결하기 위해 Stopwatch의 동작을 보완하고, 백그라운드에서 앱이 중단되더라도 스탑워치의 상태를 유지할 수 있도록 여러 가지 방법을 도입했습니다. 특히, SharedPreferences를 사용하여 스탑워치의 상태를 저장하고, 앱이 다시 포그라운드로 돌아왔을 때 해당 상태를 복원하는 방식을 채택했습니다.
4. 코드 변경 사항 및 원리 설명
변경된 주요 사항은 다음과 같습니다:
- 상태 저장을 위한 변수 추가:
- _storedElapsedMilliseconds라는 변수를 추가하여, 백그라운드로 전환되기 전까지의 경과 시간을 저장하도록 했습니다.
- 이 변수는 Stopwatch가 멈추더라도 앱이 다시 시작되었을 때 정확한 경과 시간을 계산할 수 있도록 도와줍니다.
- SharedPreferences를 통한 상태 저장 및 복원:
- _saveState() 메서드를 통해 앱이 백그라운드로 전환되거나 종료되기 전에 스탑워치의 상태(경과 시간과 실행 여부)를 SharedPreferences에 저장합니다.
- _loadState() 메서드를 통해 앱이 다시 시작되었을 때 이전에 저장된 상태를 불러오고, 필요에 따라 스탑워치를 재시작합니다.
- 백그라운드에서도 시간 정확도 유지:
- Stopwatch가 실행 중일 때는 경과 시간을 _storedElapsedMilliseconds에 계속 누적합니다.
- 앱이 다시 활성화되었을 때는 저장된 경과 시간에 현재 시간을 더해 정확한 경과 시간을 계산합니다.
void _saveState() async {
final prefs = await SharedPreferences.getInstance();
prefs.setInt('stopwatch_elapsed', _stopwatch.elapsedMilliseconds + _storedElapsedMilliseconds);
prefs.setBool('isRunning', _stopwatch.isRunning);
if (_stopwatch.isRunning) {
prefs.setString('startTime', DateTime.now().toIso8601String());
}
}
void _loadState() async {
final prefs = await SharedPreferences.getInstance();
final isRunning = prefs.getBool('isRunning') ?? false;
final elapsed = prefs.getInt('stopwatch_elapsed') ?? 0;
setState(() {
_storedElapsedMilliseconds = elapsed;
_stopwatchText = _formatTime(_storedElapsedMilliseconds);
if (isRunning) {
final startTimeString = prefs.getString('startTime');
if (startTimeString != null) {
final startTime = DateTime.parse(startTimeString);
final now = DateTime.now();
final additionalTime = now.difference(startTime).inMilliseconds;
_storedElapsedMilliseconds += additionalTime;
}
_stopwatch.start();
}
});
}
5. 해결 결과
이 코드를 통해 다음과 같은 문제를 해결할 수 있었습니다:
- 정확한 시간 유지: 앱이 백그라운드로 전환되거나 종료되더라도 스탑워치의 경과 시간이 정확히 유지됩니다.
- 재실행 시 상태 복원: 앱이 다시 실행되었을 때, 이전에 멈춘 위치에서 스탑워치가 다시 시작될 수 있습니다.
- 사용자 경험 향상: 사용자는 앱이 백그라운드로 전환되었을 때도 스탑워치가 정확히 작동한다고 느낄 수 있습니다.
6. 결론
Flutter에서 스탑워치와 같은 시간 기반 기능을 구현할 때, 백그라운드 상태에서도 정확하게 동작하게 만드는 것은 중요한 도전 과제입니다. 기본 제공되는 Stopwatch 클래스를 그대로 사용하는 경우, 앱이 백그라운드로 전환될 때 시간 상태를 유지하지 못하는 문제가 발생할 수 있습니다. 이 문제를 해결하기 위해 SharedPreferences를 사용해 상태를 저장하고 복원하는 방법을 채택했으며, 이를 통해 앱이 포그라운드와 백그라운드를 오가는 동안에도 정확한 경과 시간을 유지할 수 있었습니다.
이 방법은 운동 모드와 같은 기능이 필요한 앱에서 특히 유용하며, 비슷한 문제를 겪고 있는 다른 개발자들에게도 좋은 해결책이 될 수 있습니다.