[flutter] 플러터에서의 bloc 패턴으로 Firebase 연동하기

개요

이번 글에서는 플러터(Flutter) 앱에서 상태 관리를 위한 bloc 패턴을 사용하여 Firebase와의 연동을 다룹니다. bloc 패턴을 사용함으로써 코드를 보다 구조적으로 유지하고, Firebase의 리액티브 기능을 활용할 수 있게 됩니다.

Firebase 설정

우선, Firebase에 프로젝트를 생성하고 Firebase Console에서 AuthenticationFirestore를 설정해야 합니다.

Firebase 패키지 추가

이제 프로젝트의 pubspec.yaml 파일에 Firebase 관련 패키지들을 추가합니다.

dependencies:
  flutter_bloc: ^7.0.0
  firebase_core: ^1.10.0
  firebase_auth: ^3.3.0
  cloud_firestore: ^3.1.0

pubspec.yaml 파일을 수정한 후에는 터미널에서 flutter pub get 명령어를 실행하여 패키지를 가져와야 합니다.

Firebase 초기화

Firebase를 사용하기 위해 항상 main.dart 파일에서 Firebase를 초기화해야 합니다.

import 'package:firebase_core/firebase_core.dart';

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

인증 bloc 생성

이제 Firebase와 상호작용하는 AuthBloc을 생성합니다. 이 AuthBloc은 사용자 로그인, 로그아웃 및 인증 상태 감지를 위한 여러 메서드를 포함하게 됩니다.

class AuthBloc {
  final _auth = FirebaseAuth.instance;

  Stream<User?> get user => _auth.authStateChanges();

  Future<void> signIn(String email, String password) async {
    await _auth.signInWithEmailAndPassword(email: email, password: password);
  }

  Future<void> signOut() async {
    await _auth.signOut();
  }
}

bloc provider 추가하기

이제 bloc을 위젯 트리에 주입하기 위해 bloc을 제공하는 BlocProvider 위젯을 만들어야 합니다.

class BlocProvider extends InheritedWidget {
  final AuthBloc authBloc;

  BlocProvider({Key? key, required Widget child, required this.authBloc})
      : super(key: key, child: child);

  static BlocProvider of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<BlocProvider>()!;
  }

  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) => true;
}

인증 화면 만들기

이제 AuthBlocBlocProvider를 사용하여 로그인로그아웃 버튼을 포함하는 인증 화면을 만들 수 있습니다.

class AuthScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final authBloc = BlocProvider.of(context).authBloc;

    return Scaffold(
      appBar: AppBar(title: Text('인증')),
      body: StreamBuilder<User?>(
        stream: authBloc.user,
        builder: (BuildContext context, AsyncSnapshot<User?> snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            if (snapshot.hasData) {
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text('로그인 되었습니다.'),
                    TextButton(
                      onPressed: () {
                        authBloc.signOut();
                      },
                      child: Text('로그아웃'),
                    )
                  ],
                ),
              );
            } else {
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text('로그인이 필요합니다.'),
                    TextButton(
                      onPressed: () {
                        // 로그인 화면으로 이동
                      },
                      child: Text('로그인'),
                    )
                  ],
                ),
              );
            }
          } else {
            return Container();
          }
        },
      ),
    );
  }
}

결론

이제, 앞선 단계를 거쳐 플러터 앱에서 bloc 패턴을 사용하여 Firebase와의 연동이 가능해졌습니다.

본 포스트에서는 Flutter, bloc 패턴, Firebase를 사용하여 앱을 구현하는 방법을 알아보았습니다. 본 포스트를 참조하여 더 나은 앱을 개발하시길 바랍니다.

참고 자료