[flutter] Firebase Firestore를 사용한 게시판 애플리케이션 만들기

이번 기술 블로그에서는 Flutter와 Firebase의 Firestore 서비스를 이용하여 간단한 게시판 애플리케이션을 만드는 방법에 대해 알아보겠습니다.

1. Firebase 프로젝트 설정

먼저 Firebase 콘솔에 접속하여 새로운 프로젝트를 생성해야 합니다. Firebase 프로젝트를 생성하고 Firebase Firestore를 활성화하십시오. 그런 다음 Firebase 프로젝트의 구성 파일(google-services.json 또는 GoogleService-Info.plist)을 프로젝트 디렉토리에 추가하십시오.

2. Flutter 프로젝트 생성

Flutter SDK를 설치하고 Flutter 프로젝트를 생성합니다.

$ flutter create 게시판
$ cd 게시판

3. Firebase Firestore 라이브러리 추가

pubspec.yaml 파일을 열고 Firebase Firestore 라이브러리를 추가합니다.

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^0.7.0
  cloud_firestore: ^0.16.0

라이브러리를 추가한 후에는 터미널에서 다음 명령어를 실행하여 종속성을 업데이트합니다.

$ flutter pub get

4. Firestore 인증 설정

Firebase Firestore에 연결하기 위해 인증 정보를 설정해야 합니다. main.dart 파일을 열고 다음 코드를 추가합니다.

import 'package:firebase_core/firebase_core.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

MyApp 클래스 안에 Firebase Firestore를 초기화하는 코드를 추가합니다.

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '게시판 앱',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: '게시판'),
    );
  }
}

5. Firebase Firestore 데이터 읽기

Firestore에서 게시글 데이터를 읽어와 보여주는 기능을 구현해 보겠습니다. MyHomePage 클래스의 build 메서드 안에 다음 코드를 추가합니다.

class MyHomePage extends StatelessWidget {
  final String title;

  MyHomePage({required this.title});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: StreamBuilder<QuerySnapshot>(
        stream: FirebaseFirestore.instance.collection('posts').snapshots(),
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          }
          if (snapshot.hasError) {
            return Center(child: Text('데이터를 가져올 수 없습니다.'));
          }
          final List<DocumentSnapshot> documents = snapshot.data!.docs;
          return ListView.builder(
            itemCount: documents.length,
            itemBuilder: (BuildContext context, int index) {
              final data = documents[index].data();
              return ListTile(
                title: Text(data['title']),
                subtitle: Text(data['body']),
              );
            },
          );
        },
      ),
    );
  }
}

위 코드에서 FirebaseFirestore.instance.collection('posts').snapshots()'posts' 컬렉션의 데이터를 스트림으로 받아오는 코드입니다. 그 후 ListView.builder를 이용하여 게시글을 화면에 표시합니다.

6. Firebase Firestore 데이터 추가

새로운 게시글을 작성하고 Firebase Firestore에 추가하는 기능을 구현해 보겠습니다. MyHomePage 클래스의 build 메서드 안에 Floating Action Button을 추가하고, 눌렀을 때 새로운 게시글을 작성할 수 있는 화면으로 이동하도록 구현합니다.

class MyHomePage extends StatelessWidget {
  final String title;

  MyHomePage({required this.title});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: StreamBuilder<QuerySnapshot>(
        stream: FirebaseFirestore.instance.collection('posts').snapshots(),
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
          // 데이터 로딩 및 에러 처리 코드 생략
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => AddPostPage()),
          );
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

7. Firebase Firestore 데이터 쓰기

새로운 게시글을 작성하는 화면을 추가하고, 작성한 게시글을 Firebase Firestore에 추가하는 기능을 구현해 보겠습니다. lib 폴더에 add_post_page.dart 파일을 생성하고 다음 코드를 추가합니다.

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

class AddPostPage extends StatelessWidget {
  final TextEditingController _titleController = TextEditingController();
  final TextEditingController _bodyController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('새 게시글 작성'),
      ),
      body: Column(
        children: [
          Padding(
            padding: EdgeInsets.all(16),
            child: TextField(
              controller: _titleController,
              decoration: InputDecoration(
                labelText: '제목',
              ),
            ),
          ),
          Padding(
            padding: EdgeInsets.all(16),
            child: TextField(
              controller: _bodyController,
              decoration: InputDecoration(
                labelText: '내용',
              ),
            ),
          ),
          ElevatedButton(
            onPressed: () {
              addPost();
              Navigator.pop(context);
            },
            child: Text('작성'),
          ),
        ],
      ),
    );
  }

  void addPost() {
    FirebaseFirestore.instance.collection('posts').add({
      'title': _titleController.text,
      'body': _bodyController.text,
    });
  }
}

위 코드에서 ElevatedButton이 클릭되면 addPost() 함수가 호출되고, titlebody 필드에 해당하는 값을 Firebase Firestore에 추가합니다.

8. 앱 실행 및 테스트

이제 앱을 실행하여 게시판 기능을 테스트해 보세요. flutter run 명령어를 사용하여 앱을 실행하고, 게시글을 작성하고 읽어오는지 확인하세요.

마치며

이번 기술 블로그에서는 Flutter와 Firebase Firestore를 이용하여 간단한 게시판 애플리케이션을 만드는 방법을 살펴보았습니다. Firebase Firestore를 사용하면 실시간으로 데이터를 동기화하고, 손쉽게 데이터를 추가, 읽기, 수정, 삭제할 수 있습니다. Flutter와 Firebase의 조합은 다양한 애플리케이션을 빠르게 개발할 수 있는 강력한 도구입니다.

더 자세한 내용은 Firebase Firestore 문서를 참조하세요.

Happy coding!