안녕하세요 지금까지 플러터(Flutter)에서 화면 간 데이터 전달을 구현하여 입력한 데이터를 표시하는 기능을 만들어보았습니다. 더 나아가 앱을 재실행해도 그 데이터가 유지되도록 플러터 데이터베이스 사용방법에 대해서 작성합니다.
플러터 데이터베이스 사용법 목차
패키지 설치
Flutter 앱에서 데이터를 영구적으로 저장하기 위해서는 sqflite와 날짜를 표시해줄 intl 패키지가 필요합니다. 이 패키지들을 프로젝트에 추가하려면, pubspec.yaml 파일에 다음과 같이 의존성을 추가해야 합니다
dependencies: flutter: sdk: flutter path: ^1.8.3 sqflite: ^2.0.0 intl: ^0.18.1
데이터베이스
데이터베이스는 다양한 유형의 애플리케이션에서 필수적으로 사용되는 중요한 구성요소입니다. 앱을 개발하기 위해서 데이터를 CRUD: Create(생성), Read(읽기), Update(갱신), Delete(삭제) 하는 쿼리에 대해서는 반드시 알아야됩니다. 아래글에서 간단한 사용법을 참고하세요
데이터 모델 생성
데이터를 효율적으로 관리하기 위해, 먼저 메모 데이터를 위한 모델을 생성해야 합니다. MemoData 클래스는 메모의 내용, 생성 날짜 및 시간, 그리고 고유 ID를 포함합니다
// MemoData 클래스 정의: 메모 데이터를 위한 모델 class MemoData { int? id; // 메모의 고유 ID, nullable 타입으로 선언되어 있어서 null일 수 있음 String content; // 메모의 내용을 저장하는 변수, 필수 입력 필드 final DateTime createAt; // 메모가 생성된 시간을 저장하는 변수, final로 선언되어 생성 후 변경 불가 // 생성자: id(옵션), content, createAt(필수)를 받아 객체를 초기화함 MemoData({this.id, required this.content, required this.createAt}); // toMap 메서드: 객체를 Map<String, dynamic>으로 변환해주는 메서드 // Firestore 등의 데이터베이스에 저장하기 위한 준비 과정에서 사용될 수 있음 Map<String, dynamic> toMap() { return { 'id': id, // id를 Map에 추가, null일 수 있음 'content': content, // content를 Map에 추가 'createAt': createAt.toIso8601String(), // createAt을 ISO8601 문자열 형식으로 변환하여 Map에 추가 }; } }
데이터베이스 헬퍼 클래스
데이터를 저장하고 관리하기 위해 DatabaseHelper 클래스를 생성합니다. 이 클래스는 데이터베이스 초기화, 메모 목록 조회, 메모 추가 및 삭제 기능을 담당합니다.
import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; import '../models/memo_data.dart'; // DatabaseHelper 클래스 정의: 데이터베이스 관련 작업을 도와주는 유틸리티 클래스 class DatabaseHelper { static Database? _database; // 데이터베이스 인스턴스를 저장하는 private static 변수, nullable // initDatabase 메서드: 데이터베이스 초기화 및 생성 Future<void> initDatabase() async { if (_database == null) { // _database가 null인 경우에만 실행 var databasesPath = await getDatabasesPath(); // 데이터베이스 경로를 가져옴 String path = join(databasesPath, 'memos.db'); // 'memos.db' 파일로 경로를 조합 // 데이터베이스 열기 또는 생성 _database = await openDatabase(path, version: 1, onCreate: (Database db, int version) async { // 데이터베이스를 처음 생성할 때 호출됨, 메모 테이블 생성 await db.execute(''' CREATE TABLE memos( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, createAt TEXT ) '''); }); } } // getMemos 메서드: 모든 메모를 가져오는 메서드 Future<List<MemoData>> getMemos() async { await initDatabase(); // 데이터베이스 초기화 List<Map<String, dynamic>> maps = await _database!.query('memos'); // 'memos' 테이블의 모든 데이터를 조회 // 조회한 데이터를 MemoData 객체 리스트로 변환 return List.generate(maps.length, (index) { return MemoData( id: maps[index]['id'], // id 값 content: maps[index]['content'], // content 값 createAt: DateTime.parse(maps[index]['createAt'])); // createAt 값을 DateTime 객체로 변환 }); } // insertMemo 메서드: 새로운 메모를 데이터베이스에 추가 Future<int> insertMemo(MemoData memo) async { await initDatabase(); // 데이터베이스 초기화 return await _database!.insert('memos', memo.toMap()); // 'memos' 테이블에 메모 데이터 삽입 } // deleteMemo 메서드: 특정 id를 가진 메모를 데이터베이스에서 삭제 Future<void> deleteMemo(int id) async { await initDatabase(); // 데이터베이스 초기화 await _database!.delete( 'memos', where: 'id = ?', // id가 일치하는 레코드를 찾음 whereArgs: [id], // 삭제할 메모의 id ); } }
앱 초기화 및 메모 관리
앱의 메인 페이지에서 DatabaseHelper를 사용하여 메모를 관리합니다. 사용자가 앱을 사용하여 메모를 생성하고, 조회하고, 삭제할 수 있도록 합니다
// MyMemoAppPage 위젯의 상태 클래스 정의 class _MyMemoAppPageState extends State<MyMemoAppPage> { DatabaseHelper dbHelper = DatabaseHelper(); // DatabaseHelper 인스턴스 생성 late Future<List<MemoData>> memos; // 비동기적으로 메모 데이터를 불러올 Future 변수 선언 @override void initState() { // initState 메서드: 위젯의 상태 객체가 생성될 때 호출됨 super.initState(); // 부모 클래스의 initState 호출 memos = dbHelper.getMemos(); // DatabaseHelper를 통해 메모 데이터를 비동기적으로 불러옴 } // 이하 코드 생략... }
메모 생성버튼
사용자가 버튼을 클릭하면 MemoInputPage 화면으로 이동합니다. 사용자가 MemoInputPage에서 메모 작성 후 돌아오면, then 콜백이 실행되며, 새로 작성된 메모가 있을 경우 (value != null), 상태 업데이트를 통해 새 메모를 데이터베이스에 추가하고 메모 목록을 갱신합니다.
// 아이콘 버튼 위젯: 사용자가 새 메모를 작성할 수 있게 하는 버튼 IconButton( onPressed: () { // 버튼 클릭 시, MemoInputPage로 화면 전환 Navigator.push( context, MaterialPageRoute(builder: (context) => MemoInputPage()), ).then((value) { // MemoInputPage에서 돌아올 때 실행되는 콜백 if (value != null) { // 사용자가 새 메모 입력 후 돌아왔을 경우 setState(() { // 새로 입력된 메모를 데이터베이스에 추가하고, 메모 리스트를 다시 불러옴 dbHelper.insertMemo( MemoData(content: value, createAt: DateTime.now())); memos = dbHelper.getMemos(); }); } }); }, style: IconButton.styleFrom(foregroundColor: Colors.white), // 버튼 스타일 지정 icon: Icon(Icons.create), // 버튼 아이콘 지정 ),
메모 삭제버튼
이 버튼을 클릭하면, 해당 메모의 id를 사용하여 DatabaseHelper 클래스의 deleteMemo 메소드를 호출하여 데이터베이스에서 메모를 삭제합니다.
// ListTile 위젯 반환: 각 메모를 나타내는 UI 구성요소 return ListTile( title: Text(memo.content), // 메모의 내용을 제목으로 표시 subtitle: Text(DateFormat('yy/MM/dd').format(memo.createAt)), // 메모 생성 날짜를 부제목으로 표시, 'yy/MM/dd' 형식으로 날짜 포맷 trailing: IconButton( icon: Icon(Icons.delete), // 삭제 아이콘 버튼 onPressed: () async { // 아이콘 버튼 클릭 시 비동기로 실행되는 콜백 함수 await dbHelper.deleteMemo(memo.id!); // dbHelper를 통해 해당 메모 삭제, '!'를 사용하여 null이 아님을 보증 setState(() { // 메모 삭제 후 상태 업데이트 memos = dbHelper.getMemos(); // 메모 리스트를 다시 불러와서 갱신, 삭제된 메모 반영 }); }, ), );
마무리
사용자가 메모를 추가하거나 삭제할 때마다, 메모 목록이 최신 상태로 유지되도록 합니다. 이렇게 함으로써 사용자는 자신이 작성한 메모를 쉽게 관리할 수 있습니다. 결론 Flutter에서 sqflite패키지를 활용해 데이터를 영구적으로 저장하고 관리하는 방법을 살펴보았습니다. 이를 통해 사용자가 앱을 종료한 후에도 데이터가 유지되는 메모장 앱을 만들 수 있습니다. Flutter와 이러한 패키지들을 사용함으로써, 개발자는 효율적으로 데이터를 관리하고, 사용자에게 더 나은 경험을 제공할 수 있습니다. Flutter로 앱 개발을 시작하는 분들에게 이 글이 도움이 되기를 바랍니다. 읽어주셔서 감사합니다.