해당 강의를 학습하면서 정리한 글입니다. (강력추천)
https://www.udemy.com/course/flutter-provider-essential-korean/
ensureInitialized 를 사용하는 이유는 파이어베이스가 네이티브 코드를 사용하기 때문!void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}






User.fromDoc)User.initialUser)import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
class User with _$User {
factory User({
required String id,
required String name,
required String email,
required String profileImage,
required int level,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
factory User.fromDoc(DocumentSnapshot userDoc) {
final userData = userDoc.data() as Map<String, dynamic>?;
return User(
id: userDoc.id,
name: userData!['name'],
email: userData['email'],
profileImage: userData['profileImage'],
level: int.parse(userData['level']),
);
}
factory User.initialUser() {
return User(
id: '',
name: '',
email: '',
profileImage: '',
level: -1,
);
}
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'goods.freezed.dart';
part 'goods.g.dart';
class Goods with _$Goods {
factory Goods({
required String goods_id,
required String goods_name,
required List<String> imagePath,
required String time, //새상품일 경우 구매 날짜, 중고 상품일 경우 등록 날짜
required String goods_status, //새상품, 중고 상품
required String user_id,
}) = _Goods;
factory Goods.fromJson(Map<String, dynamic> json) => _$GoodsFromJson(json);
factory Goods.fromDoc(DocumentSnapshot goodsDoc) {
final goodsData = goodsDoc.data() as Map<String, dynamic>?;
List<dynamic> imagepathDynamic = goodsData!['imagePath'];
List<String> imagepathString =
imagepathDynamic.map((e) => e.toString()).toList();
return Goods(
goods_id: goodsDoc.id,
goods_name: goodsData['goods_name'],
imagePath: imagepathString,
time: goodsData['time'],
goods_status: goodsData['goods_status'],
user_id: goodsData['user_id'],
);
}
factory Goods.initialGoods() {
return Goods(
goods_id: "",
goods_name: "",
imagePath: [""],
time: "",
goods_status: "",
user_id: "",
);
}
}import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'post.freezed.dart';
part 'post.g.dart';
class Post with _$Post {
factory Post({
required String post_id,
required String goods_id, //선택한 nft 굿즈 아이디
required String title,
required String thumbnailImagePath,
required List<String> imagePath,
required String category,
required String price,
required String desc,
required String time, //글 등록 날짜
required String post_status, //판매중, 판매완료
required String user_id,
}) = _Post;
factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
factory Post.fromDoc(DocumentSnapshot postDoc) {
final postData = postDoc.data() as Map<String, dynamic>?;
List<dynamic> imagepathDynamic = postData!['imagePath'];
List<String> imagepathString =
imagepathDynamic.map((e) => e.toString()).toList();
return Post(
post_id: postDoc.id,
goods_id: postData['goods_id'],
title: postData['title'],
thumbnailImagePath: postData['thumbnailImagePath'],
imagePath: imagepathString,
category: postData['category'],
price: postData['price'],
desc: postData['desc'],
time: postData['time'],
post_status: postData['post_status'],
user_id: postData['user_id'],
);
}
factory Post.initialPost() {
return Post(
post_id: "",
goods_id: "",
title: "",
thumbnailImagePath: "",
imagePath: [""],
category: "",
price: "",
desc: "",
time: "",
post_status: "",
user_id: "",
);
}
}// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'package:equatable/equatable.dart';
class CustomError extends Equatable {
final String code;
final String message;
final String plugin;
CustomError({
this.code = '',
this.message = '',
this.plugin = '',
});
List<Object> get props => [code, message, plugin];
bool get stringify => true;
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
final usersRef = FirebaseFirestore.instance.collection('users');
final goodsRef = FirebaseFirestore.instance.collection('goods');
final postsRef = FirebaseFirestore.instance.collection('posts');
final storageRef = FirebaseStorage.instance.ref();

fbAuth로 firebase_auth를 import
import 'package:firebase_auth/firebase_auth.dart' as fbAuth;firebaseFirestore, firebaseAuth 변수 만들고 생성자 생성
firebaseAuth.userChanges : firebase의 유저 상태에 대한 정보를 stream 데이터로 알려주는 함수를 사용
signup 함수
name, email, password를 받음.
try-catch 문을 만들어서 작업 수행.
firebaseAuth에러와 일반 에러를 분리해서 별도로 처리.
firebaseAuth에서 에러가 발생할 경우 FirebaseAuthException 오브젝트를 받음. 이 오브젝트에서는 code, message, plugin 세개의 프로퍼티가 있음. 이걸로 CustomError 만들어서 throw 할 예정.

! 붙여서 사용일반 에러도 CustomError를 throw 함.
try {
// ...
} on SomeException catch(e) {
//Handle exception of type SomeException
} catch(e) {
//Handle all other exceptions
}
try {} catch(Exception e) {} == 다트에서 try {} on Exception catch(e) {}createUserWithEmailAndPassword 호출.
UserCredential를 리턴하는데, 이걸 변수에 저장함. 또 성공하면 자동으로 로그인이 되고, 유저의 상태가 변함.UserCredential 의 user 프로퍼티를 signedInUser에 저장함. signup이 성공했기 때문에 user는 null이 아니라서 ! 를 붙여서 저장.
signedInUser.uid를 id로 하는 document를 users collections에 만듬.
users.Ref는 constants 폴더에 만든 users collection에 대한 레퍼런스.profileImage는 랜덤하게 이미지 뽑아서 생성⇒ signup 할때마다 users collections에 새로운 document를 생성
signin 함수
signInWithEmailAndPassword를 호출. 이때도 성공하면 유저의 상태가 변함.signout 함수
firebaseAuth.signOut(); 호출만 함. 이때도 성공하면 유저의 상태가 변함.import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart' as fbAuth;
import '../../constants/db_constants.dart';
import '../../models/custom_error.dart';
class AuthRepository {
final FirebaseFirestore firebaseFirestore;
final fbAuth.FirebaseAuth firebaseAuth;
AuthRepository({
required this.firebaseFirestore,
required this.firebaseAuth,
});
Stream<fbAuth.User?> get user => firebaseAuth.userChanges();
Future<void> signup({
required String name,
required String email,
required String password,
}) async {
try {
final fbAuth.UserCredential userCredential =
await firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
final signedInUser = userCredential.user!;
await usersRef.doc(signedInUser.uid).set({
//user 클래스와 동일
'name': name,
'email': email,
'profileImage': 'https://picsum.photos/300',
'level': '1',
});
} on fbAuth.FirebaseAuthException catch (e) {
throw CustomError(
code: e.code,
message: e.message!,
plugin: e.plugin,
);
} catch (e) {
throw CustomError(
code: 'Exception',
message: e.toString(),
plugin: 'flutter_error/server_error',
);
}
}
Future<void> signin({
required String email,
required String password,
}) async {
try {
await firebaseAuth.signInWithEmailAndPassword(
email: email,
password: password,
);
} on fbAuth.FirebaseAuthException catch (e) {
throw CustomError(
code: e.code,
message: e.message!,
plugin: e.plugin,
);
} catch (e) {
throw CustomError(
code: 'Exception',
message: e.toString(),
plugin: 'flutter_error/server_error',
);
}
}
Future<void> signout() async {
await firebaseAuth.signOut();
}
}