[flutter] Firebase Firestore와 플러터를 이용한 독서 기록 애플리케이션 만들기

Flutter

목차

  1. 소개
  2. Firebase Firestore란?
  3. 플러터란?
  4. 독서 기록 애플리케이션
  5. 결론

소개

이번 포스트에서는 플러터(Flutter)와 Firebase Firestore를 이용하여 독서 기록 애플리케이션을 만드는 방법에 대해 알아보겠습니다. 플러터는 Google에서 개발한 모바일 애플리케이션 개발 프레임워크로, 단일 코드베이스로 안드로이드와 iOS 애플리케이션을 개발할 수 있습니다. Firebase Firestore는 Google의 클라우드 기반 NoSQL 데이터베이스로, 실시간 데이터베이스로서 효과적인 데이터 관리를 지원합니다.

Firebase Firestore란?

Firebase Firestore는 Firebase의 실시간 데이터베이스 서비스 중 하나로, NoSQL 데이터베이스입니다. 기존의 Firebase Realtime Database와 비교하여 더 효율적이고 강력한 쿼리 및 검색 기능을 제공합니다. Firestore는 클라이언트-서버 형태로 데이터를 동기화하며, 모바일 애플리케이션과의 통신에 최적화되어 있습니다.

플러터란?

플러터는 Google에서 개발한 오픈 소스 모바일 애플리케이션 개발 프레임워크입니다. Dart 언어를 기반으로 하며, 하나의 코드베이스로 안드로이드 및 iOS 애플리케이션을 개발할 수 있습니다. 플러터는 UI 구성 요소를 위젯으로 제공하며, 화면 레이아웃 및 상태 관리를 쉽고 빠르게 할 수 있는 기능을 제공합니다.

독서 기록 애플리케이션

이제 firebase와 플러터를 이용하여 독서 기록을 작성하고 조회하는 간단한 애플리케이션을 만들어보겠습니다.

프로젝트 설정

먼저, 플러터 개발 환경을 설정합니다. 플러터 개발을 위해서는 Dart SDK와 Flutter SDK를 설치해야 합니다. 플러터 공식 사이트에서 SDK 설치 및 관련된 개발 환경 설정 가이드를 확인할 수 있습니다.

Firebase Firestore 설정

Firebase Firestore를 사용하기 위해서는 먼저 Firebase 프로젝트를 생성해야 합니다. Firebase 콘솔에 로그인하여 새 프로젝트를 생성하고, Firebase Firestore를 활성화합니다.

UI 디자인

플러터의 UI 디자인은 위젯을 사용하여 구성합니다. 독서 기록 애플리케이션에서는 책의 제목과 작가 이름, 읽은 날짜를 입력할 수 있는 폼을 구성합니다.

class BookForm extends StatefulWidget {
  @override
  _BookFormState createState() => _BookFormState();
}

class _BookFormState extends State<BookForm> {
  final _formKey = GlobalKey<FormState>();
  final _titleController = TextEditingController();
  final _authorController = TextEditingController();

  DateTime? _selectedDate;

  @override
  void dispose() {
    _titleController.dispose();
    _authorController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          TextFormField(
            controller: _titleController,
            decoration: InputDecoration(labelText: '책 제목'),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return '책 제목을 입력해주세요.';
              }
              return null;
            },
          ),
          TextFormField(
            controller: _authorController,
            decoration: InputDecoration(labelText: '작가 이름'),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return '작가 이름을 입력해주세요.';
              }
              return null;
            },
          ),
          TextButton(
            onPressed: () {
              _selectDate(context);
            },
            child: Text(_selectedDate == null
                ? '읽은 날짜 선택'
                : '읽은 날짜: ${DateFormat('yyyy-MM-dd').format(_selectedDate!)}'),
          ),
          ElevatedButton(
            onPressed: () {
              if (_formKey.currentState!.validate()) {
                // 독서 기록을 Firebase Firestore에 저장하는 코드 추가
              }
            },
            child: Text('저장하기'),
          ),
        ],
      ),
    );
  }

  Future<void> _selectDate(BuildContext context) async {
    final initialDate = _selectedDate ?? DateTime.now();
    final pickedDate = await showDatePicker(
      context: context,
      initialDate: initialDate,
      firstDate: DateTime(2000),
      lastDate: DateTime(2100),
    );
    if (pickedDate != null) {
      setState(() {
        _selectedDate = pickedDate;
      });
    }
  }
}

Firebase Firestore와 통신

Firebase Firestore와의 통신을 위해서는 cloud_firestore 패키지를 사용해야 합니다. 해당 패키지를 pubspec.yaml 파일에 추가한 후, pub get 명령어를 실행하여 종속성을 설치합니다. 통신을 위한 코드는 다음과 같습니다.

final firestoreInstance = FirebaseFirestore.instance;

Future<void> addBookRecord(BookRecord bookRecord) {
  return firestoreInstance.collection('books').add(bookRecord.toMap());
}

Stream<List<BookRecord>> getBookRecords() {
  return firestoreInstance.collection('books').snapshots().map((snapshot) {
    return snapshot.docs.map((doc) => BookRecord.fromMap(doc.data())).toList();
  });
}

독서 기록 추가

독서 기록 추가 버튼을 누르면, 입력한 독서 기록이 Firebase Firestore에 저장되도록 구현합니다.

onPressed: () {
  if (_formKey.currentState!.validate()) {
    BookRecord bookRecord = BookRecord(
      title: _titleController.text,
      author: _authorController.text,
      date: _selectedDate ?? DateTime.now(),
    );
    addBookRecord(bookRecord).then((_) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: Text('독서 기록이 추가되었습니다.'),
      ));
    }).catchError((error) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: Text('독서 기록 추가에 실패했습니다.'),
      ));
    });
  }
}

독서 기록 조회

독서 기록을 조회하기 위해서는 StreamBuilder 위젯을 사용하여 Firebase Firestore의 변화를 감지하도록 설정합니다.

class BookList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<List<BookRecord>>(
      stream: getBookRecords(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          final bookRecords = snapshot.data;
          return ListView.builder(
            itemCount: bookRecords.length,
            itemBuilder: (context, index) {
              final bookRecord = bookRecords[index];
              return ListTile(
                title: Text(bookRecord.title),
                subtitle: Text(bookRecord.author),
                trailing: Text(DateFormat('yyyy-MM-dd').format(bookRecord.date)),
              );
            },
          );
        } else if (snapshot.hasError) {
          return Text('독서 기록을 불러오는데 실패했습니다.');
        } else {
          return CircularProgressIndicator();
        }
      },
    );
  }
}

결론

이렇게 Firebase Firestore와 플러터를 이용하여 독서 기록 애플리케이션을 만들어보았습니다. Firebase Firestore는 데이터 관리에 용이한 기능들을 제공하여 효율적인 애플리케이션 개발을 지원합니다. 플러터를 사용하면 쉽고 빠르게 멋진 UI를 구성할 수 있습니다. 독서 기록 애플리케이션을 통해 이러한 기술들을 응용해보는 것은 개발자로서의 스킬과 경험을 향상시키는 좋은 방법입니다.