본문으로 이동

플러터:데이터 저장(간단한 데이터): 두 판 사이의 차이

학교의 모든 지식. SMwiki
 
(같은 사용자의 중간 판 5개는 보이지 않습니다)
4번째 줄: 4번째 줄:
Flutter에서 화면을 이동하거나 앱을 재시작해도 데이터를 유지하려면 상태 관리와 로컬 저장 방법을 이해해야 한다.
Flutter에서 화면을 이동하거나 앱을 재시작해도 데이터를 유지하려면 상태 관리와 로컬 저장 방법을 이해해야 한다.


SharedPreferences를 사용하여 간단한 key에 값을 저장하는 방법에 대해 다룬다. 대량 데이터 저장엔 적합하지 않음.
이 문서에선 Hive를 이용한 로컬 DB 기반 데이터 저장에 대해 다룬다.


=== 저장위치 ===
SharedPreferences 등 '키:값' 방식의 간단한 저장방식도 있지만, 규모가 조금만 커져도 DB 저장방식에 밀린다.
 
=== Hive의 특징 ===
* 매우 빠름 (binary 기반)
* 리스트, Map, 객체까지 저장 가능(클래스 형태도 저장)
* 오프라인 DB 역할 수행
* iOS/Android 모두 지원
* 수백~수천 개 데이터 저장해도 빠름
 
=== Hive 저장 위치 ===
{| class="wikitable"
{| class="wikitable"
|+
|+
13번째 줄: 22번째 줄:
!비고
!비고
|-
|-
|안드로이
|안드로이드
|/data/data/<패키지명>/shared_prefs/<파일명>.xml
|/data/data/'''<패키지명>'''/files/hive/
|
|
* 이 경로는 앱만 접근 가능
* 앱만 접근 가능
* 사용자가 파일 앱으로 볼 수 없음
* 파일 앱에서 보이지 않음
* 앱을 삭제하면 같이 삭제됨
* 앱 삭제 시 데이터도 삭제됨
* 앱을 종료하거나 재부팅해도 파일은 그대로 있음
* 앱 종료/재부팅해도 유지됨
|-
|-
|iOS
|iOS
|Library/Preferences/<bundle_identifier>.plist
|Application/<UUID>/Documents/hive/
(앱 UUID는 설치할 때마다 달라짐)
|
|
* 앱 내부 전용 저장 공간
* 앱 내부 전용 저장 공간
28번째 줄: 38번째 줄:
* 앱 삭제 시 같이 삭제
* 앱 삭제 시 같이 삭제
|-
|-
|
|Windows
|
|%APPDATA%\<앱폴더>\hive
|
|예시: C:\Users\<사용자>\AppData\Roaming\com.example.myapp\hive\
|-
|브라우저
|파일이 아닌, IndexedDB 내부에 저장됨.
(Chrome 기준: 개발자도구 → Application → IndexedDB)
F5 눌러도 저장된 값이 그대로 유지된다.
|(dart에서 작성한 <code>box</code>, <code>decibelBox</code> 등이 그대로 DB 이름이 됨)
|}
|}


== 앱 재시작 후에도 데이터 유지(SharedPreferences) ==
== Hive로 데이터 유지하기 ==
간단한 숫자, 문자열, bool 저장 가능.
=== 준비 ===
pubspec.yaml 설정<syntaxhighlight lang="yaml">dependencies:
  hive: ^2.2.3
  hive_flutter: ^1.1.0</syntaxhighlight>파일 변경 이후 flutter pub get
 
=== 전체 코드 ===
가장 기본 예제인 카운팅 앱을 변형한 것.


=== 준비 ===
참고: 브라우저로 실행하면 켤 때마다 다른 port로 실행되는데, 이는 전혀 다른 웹페이지를 연 것으로 인식되어 저장된 데이터를 사용하지 못한다. 다만, f5로 초기화 하면 기존 코드에선 카운팅이 0부터 시작되었던 반면, Hive를 쓴 경우 저장되어 있던 숫자 그대로 활용할 수 있다.<syntaxhighlight lang="dart">import 'package:flutter/material.dart';
<syntaxhighlight lang="yaml">
import 'package:hive_flutter/hive_flutter.dart';
dependencies:
 
   shared_preferences: ^2.1.1
void main() async {
</syntaxhighlight>
   WidgetsFlutterBinding.ensureInitialized();
  await Hive.initFlutter();
  await Hive.openBox('box');  // 'box'라는 이름으로 열기. Hive의 Box는 작은 데이터베이스 하나라고 생각하면 됨.
  runApp(MyApp());
}
 
class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
  final box = Hive.box('box');
  int count = 0;
 
  @override
  void initState() {  // 앱 시작 시 초기화
    super.initState();
    count = box.get('count', defaultValue: 0); // 저장된 값 불러오기
  }


=== 저장하기 ===
  void increase() {
<syntaxhighlight lang="dart">
    setState(() {
final prefs = await SharedPreferences.getInstance();
      count++;
await prefs.setDouble('decibel', 85);
      box.put('count', count); // 저장
</syntaxhighlight>
    });
* `'decibel'` key에 85 저장
  }
* “기본값 85” 의미가 아니라, 지금 저장하는 값


=== 불러오기 ===
  @override
<syntaxhighlight lang="dart">
  Widget build(BuildContext context) {
double decibel = prefs.getDouble('decibel') ?? 0;
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Hive 초간단 예제")),
        body: Center(child: Text("$count", style: TextStyle(fontSize: 40))),
        floatingActionButton: FloatingActionButton(
          onPressed: increase,
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}
</syntaxhighlight>
</syntaxhighlight>
* 저장된 값이 없으면 null 반환
* null일 경우 안전하게 0으로 사용 (`?? 0`)

2026년 1월 7일 (수) 02:58 기준 최신판

틀:플러터 Dart:개요 플러터에 대한 지식 분류

  1. 플러터:개요
    1. 플러터:VSCode
    2. 플러터:안드로이드 스튜디오
  2. 플러터:실행
  3. 플러터:개념 잡기
    1. 플러터:화면 하나 만들기
    2. 플러터:변하는 화면(StatefulWidget)
    3. 플러터:화면 전환(화면 쌓기, 하단 네비게이션 바)
    4. 플러터:화면 전환(Drawer)
    5. 플러터:입력 관련
      1. 플러터:버튼
      2. 플러터:키보드 입력
      3. 플러터:슬라이더
    6. 플러터:그래프 그리기(fl chart)
    7. 플러터:데이터 저장(간단한 데이터)
    8. 플러터:인증(Firebase 인증)(미완)
    9. 플러터:인증(OAuth2)(미완)
  4. 권한 사용
    1. 플러터:마이크 입력
  5. 위젯
    1. 플러터:아이콘
    2. 플러터:레이아웃 계열 위젯
    3. 플러터:네비게이션 계열 위젯
    4. 플러터:버튼
    5. 플러터:상태관리(미완)
  6. 플러터:DB연결
    1. 플러터:Firebase(미완)
    2. 플러터:MySQL(미완)
  7. 디자인
    1. 플러터:테마
    2. 플러터:앱바
  8. 플러터:배포
  9. 플러터:참고자료
  10. 플러터:위젯
    1. 플러터:공간배치용 위젯
  11. 플러터:라이브러리
    1. 플러터:logger

Flutter에서 화면을 이동하거나 앱을 재시작해도 데이터를 유지하려면 상태 관리와 로컬 저장 방법을 이해해야 한다.

이 문서에선 Hive를 이용한 로컬 DB 기반 데이터 저장에 대해 다룬다.

SharedPreferences 등 '키:값' 방식의 간단한 저장방식도 있지만, 규모가 조금만 커져도 DB 저장방식에 밀린다.

Hive의 특징

[편집 | 원본 편집]
  • 매우 빠름 (binary 기반)
  • 리스트, Map, 객체까지 저장 가능(클래스 형태도 저장)
  • 오프라인 DB 역할 수행
  • iOS/Android 모두 지원
  • 수백~수천 개 데이터 저장해도 빠름

Hive 저장 위치

[편집 | 원본 편집]
운영체제 설명 비고
안드로이드 /data/data/<패키지명>/files/hive/
  • 앱만 접근 가능
  • 파일 앱에서 보이지 않음
  • 앱 삭제 시 데이터도 삭제됨
  • 앱 종료/재부팅해도 유지됨
iOS Application/<UUID>/Documents/hive/

(앱 UUID는 설치할 때마다 달라짐)

  • 앱 내부 전용 저장 공간
  • 앱 종료 후에도 유지
  • 앱 삭제 시 같이 삭제
Windows %APPDATA%\<앱폴더>\hive 예시: C:\Users\<사용자>\AppData\Roaming\com.example.myapp\hive\
브라우저 파일이 아닌, IndexedDB 내부에 저장됨.

(Chrome 기준: 개발자도구 → Application → IndexedDB) F5 눌러도 저장된 값이 그대로 유지된다.

(dart에서 작성한 box, decibelBox 등이 그대로 DB 이름이 됨)

Hive로 데이터 유지하기

[편집 | 원본 편집]

pubspec.yaml 설정

dependencies:
  hive: ^2.2.3
  hive_flutter: ^1.1.0

파일 변경 이후 flutter pub get

전체 코드

[편집 | 원본 편집]

가장 기본 예제인 카운팅 앱을 변형한 것.

참고: 브라우저로 실행하면 켤 때마다 다른 port로 실행되는데, 이는 전혀 다른 웹페이지를 연 것으로 인식되어 저장된 데이터를 사용하지 못한다. 다만, f5로 초기화 하면 기존 코드에선 카운팅이 0부터 시작되었던 반면, Hive를 쓴 경우 저장되어 있던 숫자 그대로 활용할 수 있다.

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Hive.initFlutter();
  await Hive.openBox('box');  // 'box'라는 이름으로 열기. Hive의 Box는 작은 데이터베이스 하나라고 생각하면 됨.
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final box = Hive.box('box');
  int count = 0;

  @override
  void initState() {  // 앱 시작 시 초기화
    super.initState();
    count = box.get('count', defaultValue: 0); // 저장된 값 불러오기
  }

  void increase() {
    setState(() {
      count++;
      box.put('count', count); // 저장
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Hive 초간단 예제")),
        body: Center(child: Text("$count", style: TextStyle(fontSize: 40))),
        floatingActionButton: FloatingActionButton(
          onPressed: increase,
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}