Flutter

[Flutter] 기기에 데이터 저장 (shared_preferences)

sinw212 2023. 7. 19. 14:02

단순 CRUD(Create, Read, Update, Delete) 기능만을 구현했다면, 데이터가 RAM(휘발성 메모리)에 저장되기 때문에 앱을 재시작하면 데이터가 전부 사라진다.

이를 해결하기 위한 방법 중, shared_preferences 패키지에 대해 알아보자.

shared_preferences 패키지는 별도의 데이터베이스 없이 기기에 파일 형태로 데이터를 저장하고 앱을 재시작할 때 파일을 읽어오는 방식으로 사용된다.

 

1. 먼저 터미널 창에 아래 명령어를 입력하여 패키지를 설치한다.

(참고: https://pub.dev/packages/shared_preferences/install)

$ flutter pub add shared_preferences //작성일 기준 버전 2.2.0

설치 후 pubspec.yaml 파일에 아래와 같이 보인다면 정상적으로 설치에 성공한 것이다.

/* pubspec.yaml */
...
dependencies:
    ...
    shared_preferences: ^2.2.0 //버전명

2. shared_preferences 패키지를 사용하기 위해서는 SharedPreferences 인스턴스를 가져와야한다.

이때, 기기에 저장된 파일을 읽어오는 시간이 다소 걸리더라도 완료될때까지 기다리라는 의미의 await 키워드를 붙여줘야한다.

import 'package:shared_preferences/shared_preferences.dart';

void main() async { //await키워드를 쓰려면 async를 붙여줘야함
    SharedPreferences prefs = await SharedPreferences.getInstance();
    ...
}

3. SharedPreferences에 값을 저장할때는 Map 형태(Key와 Value로 구성)로 데이터를 저장하고, 값을 불러올 때는 저장할 때 사용한 Key를 이용하여 데이터를 불러올 수 있다.

//값 저장하기
prefs.setString("keyName", "valueExample");

//값 불러오기
String? value = prefs.getString("keyName");

단, shared_preferences 패키지는 String, List<String>, int, double, boolean 타입의 데이터만 저장이 가능하다.

이 중에 해당되지 않는 타입이라면 Key, Value 구성의 Map 형태로 변환 후 저장 가능한 타입으로 다시 변환하여 저장할 수 있다.

(불러올 때는 저장하는 과정의 역순으로 불러와야한다.)

 

아래 예시는 Memo 타입의 값을 SharedPreferences에 저장하고 불러오는 코드이다.

/* memo_service.dart */
import library 'dart:convert'

class Memo {
    String content;
    Memo({
        required this.content,
    });
    Map toJson() { //Memo 객체를 Map 자료형으로 바꿔주는 함수
        return {'content': content};
    }
    factory Memo.fromJson(json) { //Map 자료형에서 다시 Memo 객체로 복원하는 함수
        return Memo(content: json['content']);
    }
}

class MemoService extends ChangeNotifier {
    List<Memo> memoList = [
        Memo(content: 'New Memo'), //더미 데이터
    ];
    ...
    saveMemoList() { //값 저장하기
        //List<Memo> -> (toJson) -> List<Map> -> (jsonEncode) -> String
        List memoJsonList = memoList.map((memo) => memo.toJson()).toList();
        String jsonString = jsonEncode(memoJsonList);
        prefs.setString('memoList', jsonString);
    }
    loadMemoList() { //값 복원하기
        //String -> (jsonDecode) -> List<Map> -> (fromJson) -> List<Memo>
        String? jsonString = prefs.getString('memoList');
        if(jsonString == null) return; //null이면 로드하지 않음
        List memoJsonList = jsonDecode(jsonString);
        memoList = memoJsonList.map((json) => Memo.fromJson(json)).toList();
    }
}