본문 바로가기
Flutter/Study

Hive 데이터 포맷 변경으로 인한 크래시 방지 방법 (AppSetting, UserSetting 안전 마이그레이션)

by Maccrey Coding 2025. 5. 7.
반응형

문제 상황

앱을 개발하면서 가장 흔히 겪는 문제 중 하나는 데이터 모델의 변화입니다. 특히, 로컬 데이터 저장소로 Hive를 사용 중이라면 모델에 필드를 추가하거나 필드의 순서를 변경할 때 기존 데이터와의 충돌로 앱이 크래시하는 문제가 발생할 수 있습니다.

💥 크래시 상황 예시

  • 초기 버전: AppSetting 또는 UserSetting 모델에 country 필드가 없었습니다.
  • 새 버전: country와 같은 새로운 필드가 추가되거나 필드 순서가 변경되었습니다.
  • 결과: 앱이 실행될 때 _box.get(key)가 잘못된 바이너리 포맷을 읽어 HiveError를 발생시키며 크래시합니다.

이 문제는 앱 업데이트 후 데이터 모델이 변경될 때 특히 위험하며, 이를 방치하면 많은 사용자 이탈을 초래할 수 있습니다. 이번 글에서는 이런 문제를 쉽게 해결하는 방법을 소개하겠습니다.

해결 전략

1. 읽기 시 예외 방지

  • getAppSetting()getUserSetting() 메서드를 try/catch로 감싸서 데이터를 안전하게 읽습니다.

2. 충돌 시 기존 데이터 삭제

  • 포맷이 맞지 않는 데이터를 읽을 때는 박스에서 해당 키만 삭제하여 문제를 해결합니다.

3. 안정적인 기본값 반환

  • 예외가 발생하더라도 기본값을 반환하여 앱이 정상적으로 동작할 수 있도록 합니다.

이 방법을 사용하면 별도의 마이그레이션 스크립트를 작성하지 않고도 데이터 구조 변경 시 크래시를 방지할 수 있습니다.


코드 예시

📝 AppSettingLocalDatasource

class AppSettingLocalDatasource {
  final Box<AppSetting> _box;
  String get _key => 'appSetting';

  AppSettingLocalDatasource(this._box);

  AppSetting getAppSetting() {
    try {
      final saved = _box.get(_key);
      return saved ?? AppSetting();
    } catch (e) {
      // Hive 데이터 구조 변경 등으로 읽기 실패 시
      _box.delete(_key);
      return AppSetting();
    }
  }

  Future<void> updateAppSetting(AppSetting updated) async {
    await _box.put(_key, updated);
  }
}

코드 설명

  • try 블록: 기존 데이터를 읽고, null일 땐 기본 생성자(AppSetting())를 반환합니다.
  • catch 블록: 포맷이 맞지 않거나 필드가 변경된 데이터는 삭제하여 앱의 안정성을 유지합니다.

📝 UserSettingLocalDatasource

class UserSettingLocalDatasource {
  final Box<UserSetting> _box;
  String get key => 'userSetting';

  UserSettingLocalDatasource(this._box);

  UserSetting getUserSetting() {
    try {
      final saved = _box.get(key);
      return saved ??
          UserSetting(
            nickname: '유저 #${Random().nextInt(300).toString().padLeft(3, '0')} ',
          );
    } catch (e) {
      // Hive 포맷 충돌 시 안전 초기화
      _box.delete(key);
      return UserSetting(
        nickname: '유저 #${Random().nextInt(300).toString().padLeft(3, '0')} ',
      );
    }
  }

  Future<void> updateUserSetting(UserSetting updated) async {
    await _box.put(key, updated);
  }
}

코드 설명

  • try 블록: 기존 데이터를 읽고, 없으면 랜덤 닉네임을 생성하여 반환합니다.
  • catch 블록: 포맷이 맞지 않는 데이터를 삭제하고, 기본 닉네임을 생성하여 반환합니다.

적용 후 작업

  • flutter clean && flutter pub get
  • (Freezed/JsonSerializable 모델 수정 시) flutter pub run build_runner build --delete-conflicting-outputs
  • 앱 재설치 또는 업데이트 테스트

마치며

이제 Hive 데이터 구조가 변경되어도 크래시 없이 안전하게 마이그레이션할 수 있습니다. 이 방법을 로컬 설정뿐 아니라, 다른 Hive 기반 저장소에도 적용하여 앱의 안정성을 높여보세요. 

 

 

 

반응형