Flutter와 Firebase를 이용해 채팅앱을 만들고 있습니다.
구현할 기능은
로그인 - 전화번호 인증
메인 - 접속중인 유저 목록
갤러리 - 사용자들이 게시한 사진
채팅방 - 대화중인 채팅방 목록
내 정보 + 설정
위의 기능들 정도입니다.
먼저 코딩셰프님의 강의를 따라 만들고 코드 리팩터링을 통해 제가 만들 채팅앱에 맞게 코드를 변경 후, 나머지 기능을 구현할 계획입니다.
오늘은 이에 앞서 코딩 셰프님의 강의를 보며 구현한 채팅앱을 분석하는 시간을 가져보겠습니다.
Reference
아래 영상을 보고 따라 만들었습니다.
main.dart
import 'package:chatapp/screens/chat_screen.dart';
import 'package:chatapp/screens/main_screen.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Chatting Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return const ChatScreen();
}
return const LoginSignupScreen();
},
)
);
}
}
제가 생각하는 main.dart 파일에서 기억하면 좋을 내용들을 정리해보겠습니다.
1. Firebase 초기화
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
main 함수 내부에서 runApp을 실행하기 전에
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
이렇게 2줄을 실행시켜 주었습니다.
Firebase.initializeApp(); 은 플러터에서 Firebase를 사용하기 위해 최초로 불러와야하는 메소드입니다.
Firebase.initializeApp(); 메소드는 Flutter와 통신하길 바라지만, runApp 메소드가 호출되기 전에는 플러터 엔진이 초기화되지 않아 Flutter와 통신할 수 없습니다.
-> 그렇기 때문에 메인 메소드 내부에서 Flutter 엔진과 관련된 비동기 메소드를 사용하려면 Flutter 코어 인증을 초기화 시켜줘야 합니다.
여기서 이 기능을 수행하는 메소드가 WidgetsFlutterBinding.ensureInitialized(); 메소드 입니다.

initializeApp 메소드를 보면 Future<FirebaseApp> 타입을 리턴하기 때문에 메소드 앞에 await를 적어 비동기 메소드 처리를 해줍니다.
그러므로 main함수 뒤에도 async를 적어주어 비동기 함수 처리해줍니다.
2. StreamBuilder
MaterialApp의 Home에서 StreamBuilder라는 위젯을 호출합니다.

StreamBuilder는 stream과 builder를 필수 매개변수로 가집니다.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Chatting Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return const ChatScreen();
}
return const LoginSignupScreen();
},
)
);
}
여기 코드에서는 stream에 FirebaseAuth.instance.authStateChanges()라는 메소드를 매개변수로 주었습니다.
이 메소드는 authentication state가 바뀔 때 이를 구독하기 위한 세가지 메소드 중 하나입니다.
authentication state를 구독하는 다른 메소드로는 idTokenChanges 메소드와 userChanges 메소드가 있습니다.
로그인이나 로그아웃을 할 때마다 authentication state가 바뀌고, 이 때 파이어베이스가 발급해준 토큰을 Firebase가 관리해줍니다.
그렇기 때문에 우리는 간단하게 Stream을 authStateChanges 메소드로 구독하며 확인해주기만 하면 됩니다.
그리고 builder에서는 stream에서 authentication state의 변화를 감지했을 때 UI를 업데이트하는 부분입니다.
위의 코드에서는 context와 snapshot이라는 두 개의 매개변수를 받습니다.
context는 현재 위젯의 빌드 컨텍스트를 나타내고, snapshot은 스트림으로부터의 데이터 상태를 나타냅니다.
특히 snapshot을 이요하여 스트림의 현재 상태를 확인하고 데이터를 처리할 수 있습니다.
snapshot.hasData를 이용하여 true이면 ChatScreen을, false이면 LoginSignupScreen을 반환하고 있습니다.
snapshot.hasData란 스트림이 데이터를 가지고 있는지를 나타내는 것으로 여기서는 로그인 상태를 확인할 수 있습니다.
다음 포스팅으로는 snapshot.hasData가 false일 때, 즉 로그인이 되어있지 않을 때 이동하는
LoginSignupScreen 위젯의 코드를 분석해보도록 하겠습니다.
긴 글 읽어주셔서 감사합니다.
'개발 > Flutter' 카테고리의 다른 글
| [Flutter] flutter_dotenv 패키지로 환경변수 설정(feat relase 환경에서의 오류 해결) (1) | 2024.09.26 |
|---|---|
| [Flutter] 채팅앱 만들기 - Flutter앱을 Firebase와 연동하기 (0) | 2024.08.17 |
| [Dart] Dart 개념 정리 - 1 (변수) (0) | 2024.07.26 |