Flutter로 앱을 개발할 때, 구글 로그인(Google Sign-In)을 사용하여 사용자의 인증과 유저 정보를 관리할 수 있습니다.
구글 로그인을 통해 유저의 기본 정보를 받아와서 Firebase Firestore에 저장하거나, 앱 내에서 활용할 수 있습니다.
이번 포스팅에서는 Flutter에서 구글 로그인을 설정하고, 유저 정보를 Firestore에 저장 및 관리하는 방법을 단계별로 설명하겠습니다.
1. 프로젝트 설정
Flutter에서 구글 로그인을 구현하려면 몇 가지 사전 작업이 필요합니다.
1.1 Firebase 프로젝트 생성 및 설정
- Firebase Console에서 새로운 프로젝트를 생성합니다.
- Firebase 프로젝트에 Android 및 iOS 앱을 추가합니다.
- google-services.json(Android) 및 GoogleService-Info.plist(iOS) 파일을 Flutter 프로젝트에 각각 추가합니다.
- Firebase Authentication에서 'Google' 제공자를 활성화합니다.
1.2 pubspec.yaml에 필요한 패키지 추가
다음 패키지를 pubspec.yaml 파일에 추가합니다.
dependencies:
firebase_core: latest_version
firebase_auth: latest_version
google_sign_in: latest_version
cloud_firestore: latest_version
2. 구글 로그인 구현
2.1 Firebase 초기화
main.dart 파일에서 Firebase를 초기화합니다.
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:your_project_name/app.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
2.2 구글 로그인 로직 구현
구글 로그인을 처리하는 로직을 서비스 클래스로 분리합니다.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:your_project_name/models/user_model.dart';
import 'package:your_project_name/services/firestore_service.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirestoreService _firestoreService = FirestoreService();
Future<UserModel?> signInWithGoogle() async {
try {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) {
// 사용자가 로그인 취소
return null;
}
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final UserCredential result = await _auth.signInWithCredential(credential);
final User? user = result.user;
if (user != null) {
// Firestore에 유저가 이미 존재하는지 확인
UserModel? existingUser = await _firestoreService.getUser(user.uid);
if (existingUser == null) {
// Firestore에 유저 정보가 없다면 새로운 유저 정보 저장
UserModel newUser = UserModel(
uid: user.uid,
email: user.email!,
nickname: user.displayName ?? "New User",
profileImageUrl: user.photoURL,
);
await _firestoreService.saveUser(newUser);
return newUser;
} else {
return existingUser;
}
}
} catch (e) {
print(e.toString());
return null;
}
return null;
}
Future<void> signOut() async {
await _auth.signOut();
await _googleSignIn.signOut();
}
}
이제 이 AuthService 클래스를 사용하여 구글 로그인을 앱에서 처리할 수 있습니다
3. 유저 정보 관리
구글 로그인을 통해 가져온 유저 정보를 Firestore에 저장하고, 필요할 때 불러오는 로직을 구현합니다.
3.1 Firestore 서비스 작성
lib/services/firestore_service.dart 파일을 생성하고, 유저 정보를 Firestore에 저장하고 불러오는 로직을 작성합니다.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:your_project_name/models/user_model.dart';
class FirestoreService {
final FirebaseFirestore _db = FirebaseFirestore.instance;
// Firestore에 유저 정보 저장
Future<void> saveUser(UserModel user) async {
await _db.collection('users').doc(user.uid).set(user.toMap());
}
// Firestore에서 유저 정보 불러오기
Future<UserModel?> getUser(String uid) async {
DocumentSnapshot doc = await _db.collection('users').doc(uid).get();
if (doc.exists) {
return UserModel.fromMap(doc.data() as Map<String, dynamic>, doc.id);
}
return null;
}
// 유저 정보 업데이트
Future<void> updateUser(UserModel user) async {
await _db.collection('users').doc(user.uid).update(user.toMap());
}
}
3.2 유저 모델 정의
유저 정보를 관리하기 위한 모델을 정의합니다.
class UserModel {
final String uid;
final String email;
final String? nickname;
final String? profileImageUrl;
UserModel({
required this.uid,
required this.email,
this.nickname,
this.profileImageUrl,
});
factory UserModel.fromMap(Map<String, dynamic> data, String uid) {
return UserModel(
uid: uid,
email: data['email'] ?? '',
nickname: data['nickname'],
profileImageUrl: data['profileImageUrl'],
);
}
Map<String, dynamic> toMap() {
return {
'email': email,
'nickname': nickname,
'profileImageUrl': profileImageUrl,
};
}
UserModel copyWith({String? nickname, String? profileImageUrl}) {
return UserModel(
uid: uid,
email: email,
nickname: nickname ?? this.nickname,
profileImageUrl: profileImageUrl ?? this.profileImageUrl,
);
}
}
4. UI에서 구글 로그인 연동
사용자가 버튼을 클릭하면 구글 로그인을 통해 인증을 처리하고, Firestore에 유저 정보를 저장하는 간단한 UI를 구현합니다.
import 'package:flutter/material.dart';
import 'package:your_project_name/services/auth_service.dart';
import 'package:your_project_name/models/user_model.dart';
class LoginScreen extends StatelessWidget {
final AuthService _authService = AuthService();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Google Sign-In'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
UserModel? user = await _authService.signInWithGoogle();
if (user != null) {
// 로그인 성공 시, 유저 정보를 확인하고 다음 화면으로 이동
Navigator.push(
context,
MaterialPageRoute(builder: (context) => UserProfileScreen(user: user)),
);
} else {
// 로그인 실패 시, 에러 메시지 표시
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to sign in with Google')),
);
}
},
child: Text('Sign in with Google'),
),
),
);
}
}
4.1 유저 프로필 화면
로그인 후, 유저의 정보를 보여주는 프로필 화면을 구현합니다.
import 'package:flutter/material.dart';
import 'package:your_project_name/models/user_model.dart';
import 'package:your_project_name/services/auth_service.dart';
import 'package:your_project_name/services/firestore_service.dart';
class UserProfileScreen extends StatelessWidget {
final UserModel user;
final AuthService _authService = AuthService();
final FirestoreService _firestoreService = FirestoreService();
UserProfileScreen({required this.user});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('${user.nickname}\'s Profile'),
actions: [
IconButton(
icon: Icon(Icons.logout),
onPressed: () async {
await _authService.signOut();
Navigator.of(context).popUntil((route) => route.isFirst);
},
)
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (user.profileImageUrl != null)
Center(
child: CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(user.profileImageUrl!),
),
),
SizedBox(height: 20),
Text(
'Nickname: ${user.nickname}',
style: TextStyle(fontSize: 18),
),
SizedBox(height: 10),
Text(
'Email: ${user.email}',
style: TextStyle(fontSize: 18),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
// 예시로 유저 닉네임을 업데이트하는 기능
UserModel updatedUser = user.copyWith(nickname: 'Updated Nickname');
await _firestoreService.updateUser(updatedUser);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Nickname updated successfully!')),
);
},
child: Text('Update Nickname'),
),
],
),
),
);
}
}
5. 맺음말
이제 구글 로그인을 통해 사용자의 정보를 Firebase Firestore에 저장하고, 관리하는 방법을 구현했습니다.
사용자는 구글 로그인을 통해 앱에 로그인하고, 기본적인 프로필 정보를 확인하거나 업데이트할 수 있습니다.
확장 포인트
- 추가 유저 정보 관리: 기본적인 유저 정보 외에도, 사용자 선호도, 활동 로그 등을 추가적으로 저장하고 관리할 수 있습니다.
- 유저 정보 보안: Firestore 규칙을 설정하여, 사용자 본인만 자신의 정보를 읽고 쓸 수 있도록 설정할 수 있습니다.
- 소셜 로그인 추가: 구글 로그인 외에도 Facebook, Apple 등 다양한 소셜 로그인 제공자를 추가할 수 있습니다.
- UI 개선: 로그인 및 프로필 화면을 보다 직관적이고, 사용자 친화적으로 디자인할 수 있습니다.
이 포스팅에서는 구글 로그인을 사용해 유저 정보를 관리하는 방법을 소개했지만, 이를 바탕으로 다양한 확장 기능을 추가하여 더욱 완성도 높은 앱을 만들 수 있습니다.
공감과 댓글은 저에게 큰 힘이 됩니다.
Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.
'Flutter > Snippet' 카테고리의 다른 글
플러터 ElevatedButton: VS Code자동 완성 스니펫 (1) | 2024.09.24 |
---|---|
플러터에서 Apple 로그인을 이용하여 유저 정보를 관리하는 방법 (0) | 2024.08.29 |
플러터 앱에 Firebase를 이용하여 사용자 정보 관리 기능 추가하기 (6) | 2024.08.29 |
플러터에서 텍스트 타이핑 효과를 내는 위젯: 자세한 가이드 (0) | 2024.08.12 |
플러터에서 AdMob API로 수익 정보 조회하기 (6) | 2024.07.28 |