플러터 파이어베이스 데이터베이스 (Firebase Database) – 일기장 앱 만들기 (9)

플러터(Flutter)와 파이어베이스(Firebase)는 앱 개발에 매우 효과적으로 사용될 수 있는 강력한 도구입니다. 지난 글에서는 파이어베이스 데이터베이스를 이용하기 위해서 플러터 프로젝트와 연동하였다면 이번 글에서는 플러터 파이어베이스 데이터베이스(Firebase Database)를 이용하여 CRUD(Create, Read, Update, Delete) 기능을 구현하는 방법에 대해서 작성하겠습니다.

파이어베이스(Firebase) 설정하기

Firebase.initializeApp()은 Firebase 서비스를 사용하기 전에 애플리케이션 초기화를 위해 호출되는 메서드로, Firebase와의 연결을 설정하고 필요한 서비스를 초기화한다.

# main.dart

import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

Firebase JSON Serializable (직렬화)

Firebase에서 JSON 직렬화는 데이터를 표준화된 형식으로 전송하고 저장하기 위해 사용된다. JSON은 간단하면서도 효과적이며, Firebase 서비스는 이를 활용하여 클라이언트와 서버 간의 데이터 교환을 용이하게 한다.

# models/diary_db_model.dart

import 'package:intl/intl.dart';

class DiaryModel {
  final String id;
  final DateTime date;
  final String content;
  final DateTime create;

  DiaryModel({
    required this.id,
    required this.content,
    required this.date,
    required this.create,
  });

  DiaryModel.fromJson({
    required Map<String, dynamic> json,
  })  : id = json['id'],
        content = json['content'],
        date = DateTime.parse(json['date']),
        create = DateTime.parse(json['create']);

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'content': content,
      'date': DateFormat('yyyy-MM-dd').format(create),
      'create': DateFormat('yyyy-MM-dd HH:mm:ss').format(create),
    };
  }
}

Firebase CRUD 기능 구현

Firebase CRUD (Create, Read, Update, Delete) 기능은 Firestore 또는 Realtime Database를 사용하여 데이터를 생성, 조회, 업데이트 및 삭제하는 것을 의미한다. 각각의 기능은 Firebase SDK에서 제공하는 API를 사용하여 데이터를 조작하며, 이를 통해 실시간 데이터 관리가 가능하다.

데이터 삽입

기존의 _saveDiaryEntry 함수에 Firebase Firestore에 저장할 수 있도록 수정한다.

# widgets/diary_sheet.dart

void _saveDiaryEntry(DateTime date) async {
  try {
    // 새로운 DiaryModel 인스턴스 생성
    var diary = DiaryModel(
      id: Uuid().v4(), // 고유한 ID를 생성하여 사용 (Uuid 라이브러리 활용)
      content: contentController.text, // 컨트롤러에서 콘텐츠 가져오기
      date: date, // 제공된 날짜 설정
      create: DateTime.now(), // 현재 날짜와 시간 설정
    );

    // DiaryModel 인스턴스를 Firestore에 저장
    await FirebaseFirestore.instance
        .collection('diary') // Firestore 컬렉션 이름
        .doc(diary.id) // Firestore 문서 ID (생성된 ID 사용)
        .set(diary.toJson()); // DiaryModel을 JSON으로 변환하여 Firestore에 설정

    print('Diary entry saved successfully.');
  } catch (e) {
    // 프로세스 중에 발생할 수 있는 오류 처리
    print('Failed to save diary entry: $e');
  }
}

데이터가 Firebase Firestore에 저장된 것을 확인한다.

플러터-파이어베이스-flutter-Firebase-데이터삽입

데이터 조회

기존의 _buildDiaryEntries 함수에 Firebase Firestore로 데이터를 조회할 수 있도록 수정한다. 해당 날짜의 데이터를 생성일로 sort하여 가장 최근에 데이터를 보여준다. 데이터의 무결성과 일관성을 유지하기 위해 업데이트는 하지 않았다.

# widgets/diary_sheet.dart

Widget _buildDiaryEntries() {
  return StreamBuilder<QuerySnapshot>(
    // Firestore에서 'diary' 컬렉션의 데이터를 스트림으로 가져오기
    stream: FirebaseFirestore.instance
        .collection('diary')
        .where('date',
            isEqualTo: DateFormat('yyyy-MM-dd').format(
                date)) // 가져올 데이터의 조건
        .snapshots(),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        // 로딩 중 상태
        return CircularProgressIndicator();
      } else if (snapshot.hasError) {
        // 오류 상태
        return Text('Error: ${snapshot.error}');
      } else {
        // 데이터가 성공적으로 로드됨
        final diaryDataList = snapshot.data!.docs
            .map(
              (QueryDocumentSnapshot e) => DiaryModel.fromJson(
                  json: (e.data() as Map<String, dynamic>)),
            )
            .toList();

        // 생성일자를 기준으로 리스트 정렬
        diaryDataList.sort((a, b) => a.create.compareTo(b.create));

        if (diaryDataList.isEmpty) {
          // 데이터가 없을 때
          return TextFormField(
            controller: contentController,
            keyboardType: TextInputType.multiline,
            maxLines: 25,
            decoration: InputDecoration(
              hintText: '입력해주세요.',
            ),
          );
        } else {
          // 데이터가 있을때 폼 채우기
          return TextFormField(
            controller: getControllerText(diaryDataList.last.content),
            keyboardType: TextInputType.multiline,
            maxLines: 25,
            decoration: InputDecoration(
              hintText: '입력해주세요.',
            ),
          );
        }
      }
    },
  );
}

추가 데이터가 Firebase Firestore에 저장된 것을 확인한다.

플러터-파이어베이스-flutter-Firebase-데이터업데이트

데이터 삭제

기존 TextButton에서 Firebase Firestore로 삭제할 수 있도록 수정한다. Dialog에서 확인을 누르면 해당 날짜의 데이터를 가져와 반복문을 돌면서 삭제한다.

데이터 삭제는 보존성과 기록을 유지하지 못하기 때문에 데이터를 비활성화 상태로 처리하여 보관하는 방법을 사용할 수 있다.

# widgets/diary_sheet.dart

Future<void> _showConfirmationDialog(
    BuildContext context, DateTime date) async {
  await showDialog<void>(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: Text('삭제 확인'),
        content: Text('일정을 삭제하시겠습니까?'),
        actions: [
          TextButton(
            onPressed: () {
              // 취소 버튼 클릭 시, 알림창 닫기만 수행
              Navigator.of(context).pop();
            },
            child: Text('취소'),
          ),
          TextButton(
            onPressed: () {
              // 확인 버튼 클릭 시, 데이터 삭제 후 알림창 닫기와 뒤로 가기 수행       
              deleteDiaryEntriesByDate(date);
              Navigator.of(context).pop();
              Navigator.of(context).pop();
            },
            child: Text('확인'),
          ),
        ],
      );
    },
  );
}
# widgets/diary_sheet.dart

Future<void> deleteDiaryEntriesByDate(DateTime date) async {
  try {
    // Firestore에서 특정 날짜에 해당하는 데이터들을 가져오는 쿼리
    QuerySnapshot querySnapshot = await FirebaseFirestore.instance
        .collection('diary')
        .where('date', isEqualTo: DateFormat('yyyy-MM-dd').format(date))
        .get();

    // 쿼리 결과에 대한 반복문
    for (QueryDocumentSnapshot document in querySnapshot.docs) {
      // 각 데이터를 삭제
      await document.reference.delete();
    }

    print('Diary entries deleted successfully.');
  } catch (e) {
    print('Failed to delete diary entries: $e');
  }
}

데이터들이 Firebase Firestore에서 삭제된 것을 확인한다.

플러터-파이어베이스-flutter-Firebase-데이터삭제

마무리

지금까지 Firebase를 활용하여 데이터를 CRUD하는 과정을 설명드렸습니다. 생성, 조회, 업데이트, 삭제를 통해 데이터를 조작하는 이러한 기능은 Firebase의 강력한 기능 중 하나로, Firestore 또는 Realtime Database를 통해 실시간으로 데이터를 관리할 수 있습니다. 이를 통해 안전하고 효율적인 데이터 조작이 가능하며, Firebase의 다양한 기능을 활용하여 애플리케이션을 더욱 강력하게 구축할 수 있습니다. 읽어주셔서 감사합니다!

전체 코드는 링크에서 확인할 수 있습니다.

Leave a Comment