backup recover 성공 ! 메모 square

icloud sync 백업 _ isle 성공!

new app 새로운 앱할때 항상 바꿔야 할 것

auto 항상 reinstall 재설치 자동 설치 /always launch / start publish rebuild

ver2 isle data save back up / sync

mac version : Sync Isle ver2

# Data Survival Blueprint — macOS 버전

## 업데이트·재설치 후에도 데이터·웹 로그인 유지하기

> **목적:** macOS 앱에서 사용자의 로컬 데이터와 웹 로그인 상태를 최대한 안전하게 유지하는 구조를 설명한다.
> Flutter macOS 앱, 네이티브 macOS 앱, Electron류 데스크톱 앱에도 비슷한 방식으로 적용할 수 있다.

---

## 1. 한 줄 요약

macOS에서는 앱 업데이트만으로는 보통 사용자 데이터가 지워지지 않는다.
하지만 앱 삭제, 캐시 초기화, DB 손상, 강제 종료에 대비하려면 다음 3층 구조가 필요하다.

> **① 앱 내부 저장소 + ② Documents 백업 폴더 + ③ Checkpoint 파일**

---

## 2. macOS 데이터 생존 구조

| 상황            | 사용자 데이터            | 웹 로그인        | 복구 방식                     |
| ------------- | ------------------ | ------------ | ------------------------- |
| 앱 업데이트        | 유지 가능              | 유지 가능        | 같은 Bundle ID와 같은 저장 경로 유지 |
| 앱 강제 종료 후 재실행 | 유지 가능              | 유지 가능        | Checkpoint로 보조            |
| 앱 삭제 후 재설치    | 앱 내부 데이터는 사라질 수 있음 | 보통 다시 로그인 필요 | Documents 백업 폴더에서 복구      |
| 다른 Mac으로 이동   | 자동 유지 안 됨          | 다시 로그인 필요    | 백업 JSON 파일로 수동 복원         |

---

## 3. macOS 전용 3계층 모델

```mermaid
flowchart TB
  subgraph L1["Layer 1 — Primary Store"]
    Hive["Hive boxes\nApplication Support / Documents"]
    WebView["WebView Cookie Store\nOS-managed"]
  end

  subgraph L2["Layer 2 — Survival Backup"]
    Backup["~/Documents/{AppName} Backup/current.json"]
    Sync["notifyLocalDataChanged()\n800ms debounce"]
  end

  subgraph L3["Layer 3 — Checkpoint"]
    Checkpoint["isle_state_checkpoint.b64\n25초 주기 저장"]
  end

  UI["UI / Stores"] --> Hive
  UI --> WebView
  Hive --> Sync --> Backup
  Hive --> Checkpoint
  Backup --> Bootstrap["앱 부팅 시 복구"]
  Checkpoint --> Bootstrap

4. Layer 1 — Primary Store

역할

앱이 평소에 직접 읽고 쓰는 기본 저장소다.

macOS Flutter 앱에서는 보통 다음을 사용한다.

핵심 원칙

앱 업데이트 시 데이터가 유지되려면 다음 조건이 필요하다.

  1. Bundle ID가 같아야 한다.
  2. 앱 데이터 저장 경로가 바뀌면 안 된다.
  3. 앱 업데이트 과정에서 DB 초기화 코드를 실행하면 안 된다.
  4. WebView 쿠키/캐시를 앱 시작 때마다 삭제하면 안 된다.

5. Layer 2 — Survival Backup

역할

앱 내부 데이터가 비거나 손상되었을 때 복구하기 위한 외부 백업이다.

macOS 기본 백업 위치:

~/Documents/{AppName} Backup/current.json

예시:

~/Documents/Isle Backup/current.json

저장 방식

Store에서 데이터가 저장될 때마다 즉시 백업하지 말고, debounce를 둔다.

Store.save()
→ notifyLocalDataChanged()
→ 800ms debounce
→ current.json atomic write

atomic write 원칙

백업 파일을 바로 덮어쓰지 않는다.

current.json.tmp 작성
→ 성공하면 current.json으로 rename

이렇게 해야 저장 중 앱이 죽어도 백업 파일이 망가지지 않는다.


6. Layer 3 — Checkpoint

역할

Survival Backup이 실행되기 전에 앱이 강제 종료되거나, 일부 Hive box만 손상된 경우를 대비한다.

기본 파일:

Application Documents/isle_state_checkpoint.b64

저장 주기:

25초마다 1회
앱 종료 또는 paused 시 1회

Checkpoint는 백업의 주 저장소가 아니다. 크래시 대비용 임시 스냅샷이다.


7. macOS 부팅 순서

runApp() 전에 아래 순서를 지킨다.

1. WidgetsFlutterBinding.ensureInitialized()
2. Hive.initFlutter()
3. 모든 Hive box open
4. 캐시성 플래그 복구
5. SurvivalBackupService.bootstrapOnLaunch()
6. CheckpointService.restoreFromCheckpointIfLocalEmpty()
7. CheckpointService.startPeriodicCheckpoint()
8. runApp()

중요한 점:

복구는 로컬 데이터가 비어 있을 때만 해야 한다.

이미 사용자의 정상 데이터가 있는데 백업 파일을 덮어씌우면 오히려 최신 데이터가 날아간다.


8. localLooksFresh() 기준

앱이 “새로 설치된 상태처럼 비어 있는지” 판단하는 함수가 필요하다.

예시 기준:

차단 목록 empty
스케줄 empty
라이브러리 empty
사용자 설정 empty
피드 데이터 empty

전부 비어 있으면:

localLooksFresh() == true

이때만 Survival Backup 또는 Checkpoint 복구를 시도한다.

반대로 하나라도 의미 있는 사용자 데이터가 있으면:

localLooksFresh() == false

이 경우에는 백업으로 덮어쓰지 않는다.


9. macOS WebView 로그인 유지

업데이트 시 유지되는 이유

macOS WebView는 OS가 관리하는 쿠키 저장소를 사용한다. 같은 앱, 같은 Bundle ID, 같은 WebView 저장소를 유지하면 업데이트 후에도 로그인 상태가 유지될 수 있다.

지켜야 할 규칙

규칙 이유
앱 시작 시 쿠키 삭제 금지 로그인 유지
화면 이동마다 WebView clearCache 금지 세션 유지
로그아웃 버튼에서만 쿠키 삭제 사용자 의도 존중
User-Agent를 갑자기 바꾸지 않기 웹 서비스 보안 감지 회피
백업 JSON에 쿠키를 넣지 않기 보안 및 정책 리스크 방지

중요한 제한

앱을 삭제하면 WebView 쿠키도 사라질 수 있다. 따라서 앱 재설치 후 웹 로그인은 사용자가 다시 해야 한다.

Survival Backup은 앱 데이터 복구용이고, 웹 로그인 쿠키 복구용이 아니다.


10. macOS Store 패턴

각 Store는 저장 후 반드시 변경 알림을 호출한다.

class ExampleStore {
  static const _boxName = 'my_app_example';
  static Box<String>? _box;

  static Future<void> ensureOpen() async {
    if (_box != null && _box!.isOpen) return;
    _box = await Hive.openBox<String>(_boxName);
  }

  static Future<void> saveAll(List<ExampleModel> items) async {
    await ensureOpen();

    await _box!.put(
      'items_v1',
      jsonEncode(items.map((e) => e.toJson()).toList()),
    );

    notifyLocalDataChanged();
  }
}

핵심:

Store 저장
→ notifyLocalDataChanged()
→ Survival Backup 동기화

이 호출이 빠지면 백업이 갱신되지 않는다.


11. macOS Survival Backup 구현 체크리스트


12. macOS Checkpoint 구현 체크리스트


13. 사용자가 알아야 할 안내 문구

macOS 설정 화면에는 이런 문구를 넣으면 좋다.

앱 업데이트만으로는 보통 데이터가 유지됩니다.
다만 앱 삭제, 디스크 정리, 데이터 손상에 대비하려면
Documents 폴더의 백업 파일을 유지해 주세요.

백업 폴더 안내:

기본 백업 위치:
~/Documents/Isle Backup/current.json

웹 로그인 안내:

YouTube, Instagram 등 웹 로그인은 앱 업데이트 후에는 유지될 수 있지만,
앱 삭제 후 재설치하면 다시 로그인해야 할 수 있습니다.
보안을 위해 쿠키는 백업 JSON에 포함하지 않습니다.

14. macOS에서 특히 조심할 안티패턴

하지 말아야 할 것:


15. macOS 테스트 시나리오

테스트 1. 일반 업데이트 시뮬레이션

  1. 앱 실행
  2. 데이터 저장
  3. 앱 종료
  4. 새 빌드로 덮어 설치
  5. 데이터 유지 확인
  6. WebView 로그인 유지 확인

테스트 2. 강제 종료 복구

  1. 데이터 저장
  2. 앱 강제 종료
  3. 앱 재실행
  4. Checkpoint 또는 Hive 데이터 유지 확인

테스트 3. Survival Backup 복구

  1. 데이터 저장
  2. ~/Documents/Isle Backup/current.json 생성 확인
  3. 앱 내부 데이터 삭제 또는 fresh 상태 시뮬레이션
  4. 앱 재실행
  5. current.json에서 복구되는지 확인

테스트 4. 웹 로그인 정책 확인

  1. WebView에서 로그인
  2. 앱 종료 후 재실행
  3. 로그인 유지 확인
  4. 앱 삭제 후 재설치
  5. 다시 로그인이 필요한지 확인

16. macOS 버전 최종 요약

macOS 앱의 데이터 생존 전략은 다음과 같다.

  1. 업데이트 유지: 같은 Bundle ID와 같은 저장 경로를 유지하면 앱 내부 데이터와 WebView 세션은 보통 유지된다.
  2. 외부 백업: 앱 삭제나 데이터 손상에 대비해 ~/Documents/{AppName} Backup/current.json에 Survival Backup을 둔다.
  3. 크래시 대비: 25초마다 Checkpoint를 만들어 Survival Backup 전 강제 종료에 대비한다.
  4. 복구 조건: 로컬 데이터가 비어 있을 때만 백업이나 Checkpoint를 복구한다.
  5. 웹 로그인: WebView 쿠키는 백업하지 않고, 앱 업데이트 시에는 유지되게 하되 재설치 후에는 다시 로그인하게 한다.

초압축

macOS 데이터 생존 = 앱 내부 저장소 + Documents 백업 + Checkpoint
업데이트 = 유지
삭제 후 재설치 = 백업에서 복구
웹 로그인 = 업데이트는 유지 가능, 재설치는 다시 로그인
쿠키는 백업하지 않음
복구는 localLooksFresh()일 때만

[auto 항상 reinstall 재설치 자동 설치 /always launch / start publish rebuild](<https://vivid-wave.notion.site/auto-reinstall-always-launch-start-publish-rebuild-35b6d6203eea804a8938def66494da76>)

[new app 새로운 앱할때 항상 바꿔야 할 것](<https://vivid-wave.notion.site/new-app-35c6d6203eea80b8be17c27cf9ae8cb6>)

[backup recover 성공 ! 메모 square](<https://vivid-wave.notion.site/backup-recover-square-3666d6203eea80fca98afb4af6bd1e3e>)