1. 시작하기 전에
이 Codelab에서는 FlutterFire UI 패키지를 사용하여 Flutter 앱에 Firebase 인증을 추가하는 방법을 알아봅니다. 이 패키지를 사용하면 Flutter 앱에 이메일 및 비밀번호 인증과 Google 로그인 인증을 모두 추가할 수 있습니다. Firebase 프로젝트를 설정하고 FlutterFire CLI를 사용하여 Flutter 앱에서 Firebase를 초기화하는 방법도 알아봅니다.
기본 요건
이 Codelab에서는 Flutter를 사용한 경험이 있다고 가정합니다. 그렇지 않은 경우 먼저 기본사항을 학습하는 것이 좋습니다. 다음 링크가 도움이 됩니다.
- Flutter 위젯 프레임워크 둘러보기
- 첫 Flutter 앱 작성, 1부 Codelab 사용해 보기
Firebase 경험도 있어야 하지만 Flutter 프로젝트에 Firebase를 추가한 적이 없어도 괜찮습니다. Firebase Console을 잘 모르거나 Firebase를 처음 사용하는 경우 다음 링크를 먼저 참고하세요.
만들 항목
이 Codelab에서는 Firebase를 사용하여 Flutter 앱의 인증 흐름을 빌드하는 방법을 안내합니다. 애플리케이션에는 로그인 화면, '등록' 화면, 비밀번호 복구 화면, 사용자 프로필 화면이 있습니다.
학습할 내용
이 Codelab에서는 다음을 다룹니다.
- Flutter 앱에 Firebase 추가
- Firebase Console 설정
- Firebase CLI를 사용하여 애플리케이션에 Firebase 추가
- FlutterFire CLI를 사용하여 Dart에서 Firebase 구성 생성
- Flutter 앱에 Firebase 인증 추가
- 콘솔에서 Firebase 인증 설정
firebase_ui_auth
패키지를 사용하여 이메일 및 비밀번호 로그인 추가firebase_ui_auth
패키지로 사용자 등록 추가- '비밀번호를 잊으셨나요?' 페이지 추가
firebase_ui_auth
로 Google 로그인 추가- 여러 로그인 제공업체와 호환되도록 앱을 구성합니다.
firebase_ui_auth
패키지를 사용하여 애플리케이션에 사용자 프로필 화면 추가
이 Codelab에서는 firebase_ui_auth
패키지를 사용하여 강력한 인증 시스템을 추가하는 데 중점을 둡니다. 보시다시피 위의 모든 기능을 갖춘 이 전체 앱은 약 100줄의 코드로 구현할 수 있습니다.
필요한 사항
- Flutter에 대한 실무 지식과 SDK가 설치되어 있어야 합니다.
- 텍스트 편집기 (JetBrains IDE, Android 스튜디오, VS Code는 Flutter에서 지원됨)
- Google Chrome 브라우저 또는 Flutter의 기타 기본 개발 타겟 (이 Codelab의 일부 터미널 명령어는 Chrome에서 앱을 실행한다고 가정합니다.)
2. Firebase 프로젝트 만들기 및 설정
가장 먼저 해야 할 일은 Firebase 웹 콘솔에서 Firebase 프로젝트를 만드는 것입니다.
Firebase 프로젝트 만들기
- Google 계정을 사용하여 Firebase Console에 로그인합니다.
- 버튼을 클릭하여 새 프로젝트를 만든 다음 프로젝트 이름 (예:
FlutterFire-UI-Codelab
)을 입력합니다.
- 계속을 클릭합니다.
- 메시지가 표시되면 Firebase 약관을 검토하고 이에 동의한 다음 계속을 클릭합니다.
- (선택사항) Firebase Console에서 AI 지원('Firebase의 Gemini'라고 함)을 사용 설정합니다.
- 이 Codelab에서는 Google 애널리틱스가 필요하지 않으므로 Google 애널리틱스 옵션을 사용 중지합니다.
- 프로젝트 만들기를 클릭하고 프로젝트가 프로비저닝될 때까지 기다린 다음 계속을 클릭합니다.
Firebase 프로젝트에 관해 자세히 알아보려면 Firebase 프로젝트 이해를 참고하세요.
Firebase 인증에 이메일 로그인 사용 설정
빌드 중인 앱은 Firebase 인증을 사용하여 사용자가 앱에 로그인할 수 있도록 합니다. 또한 신규 사용자가 Flutter 애플리케이션에서 등록할 수 있습니다.
Firebase 인증은 Firebase Console을 사용하여 사용 설정해야 하며, 사용 설정 후 특수 구성이 필요합니다.
사용자가 웹 앱에 로그인할 수 있도록 먼저 이메일/비밀번호 로그인 방법을 사용합니다. 나중에 Google 로그인 방법을 추가합니다.
- Firebase Console의 왼쪽 패널에서 빌드 메뉴를 펼칩니다.
- 인증을 클릭한 후 시작하기 버튼을 클릭하고 로그인 방법 탭을 클릭합니다 (또는 로그인 방법 탭으로 바로 이동).
- 로그인 제공업체 목록에서 이메일/비밀번호를 클릭하고 사용 설정 스위치를 켬 위치로 설정한 다음 저장을 클릭합니다.
3. Flutter 앱 설정
시작하기 전에 스타터 코드를 다운로드하고 Firebase CLI를 설치해야 합니다.
시작 코드 가져오기
명령줄에서 GitHub 저장소를 클론합니다.
git clone https://github.com/flutter/codelabs.git flutter-codelabs
또는 GitHub CLI 도구가 설치되어 있는 경우 다음 단계를 따르세요.
gh repo clone flutter/codelabs flutter-codelabs
샘플 코드를 머신의 flutter-codelabs
디렉터리에 클론해야 합니다. 이 디렉터리에는 여러 Codelab의 코드가 포함되어 있습니다. 이 Codelab의 코드는 flutter-codelabs/firebase-auth-flutterfire-ui
하위 디렉터리에 있습니다.
flutter-codelabs/firebase-auth-flutterfire-ui
디렉터리에는 두 개의 Flutter 프로젝트가 포함되어 있습니다. 하나는 complete
이고 다른 하나는 start
입니다. start
디렉터리에는 불완전한 프로젝트가 포함되어 있으며 이 디렉터리에서 가장 많은 시간을 보내게 됩니다.
cd flutter-codelabs/firebase-auth-flutterfire-ui/start
앞으로 건너뛰거나 완료 시 어떤 모습인지 확인하려면 complete라는 디렉터리에서 상호 참조하세요.
Codelab을 따라 하면서 직접 코드를 추가하려면 flutter-codelabs/firebase-auth-flutterfire-ui/start
에서 Flutter 앱을 시작하고 Codelab 전반에 걸쳐 해당 프로젝트에 코드를 추가해야 합니다. 해당 디렉터리를 열거나 원하는 IDE로 가져옵니다.
Firebase CLI 설치
Firebase CLI는 Firebase 프로젝트를 관리하는 도구를 제공합니다. CLI는 잠시 후에 설치할 FlutterFire CLI에 필요합니다.
CLI를 설치하는 방법은 다양합니다. firebase.google.com/docs/cli에서 운영체제에 사용할 수 있는 모든 옵션을 검토하세요.
CLI를 설치한 후 Firebase로 인증해야 합니다.
- 다음 명령어를 실행하여 Google 계정으로 Firebase에 로그인합니다.
firebase login
- 이 명령어는 로컬 머신을 Firebase에 연결하고 Firebase 프로젝트에 대한 액세스 권한을 부여합니다.
- Firebase 프로젝트를 나열하여 CLI가 올바르게 설치되었고 사용자 계정에 액세스할 수 있는지 테스트합니다. 다음 명령어를 실행합니다.
firebase projects:list
- 표시된 목록은 Firebase Console에 나열된 Firebase 프로젝트와 같아야 합니다.
flutterfire-ui-codelab.
이상이 표시되어야 합니다.
FlutterFire CLI 설치
FlutterFire CLI는 Flutter 앱에서 지원되는 모든 플랫폼에 Firebase를 쉽게 설치할 수 있도록 지원하는 도구입니다. Firebase CLI를 기반으로 빌드됩니다.
먼저 CLI를 설치합니다.
dart pub global activate flutterfire_cli
CLI가 설치되었는지 확인합니다. 다음 명령어를 실행하고 CLI에서 도움말 메뉴가 출력되는지 확인합니다.
flutterfire --help
Flutter 앱에 Firebase 프로젝트 추가
FlutterFire 구성
FlutterFire를 사용하여 Flutter 앱에서 Firebase를 사용하는 데 필요한 Dart 코드를 생성할 수 있습니다.
flutterfire configure
이 명령어를 실행하면 사용할 Firebase 프로젝트와 설정할 플랫폼을 선택하라는 메시지가 표시됩니다.
다음 스크린샷은 답변해야 하는 프롬프트를 보여줍니다.
- 사용할 프로젝트를 선택합니다. 이 경우
flutterfire-ui-codelab
를 사용합니다.
- 사용할 플랫폼을 선택합니다. 이 Codelab에는 웹, iOS, Android용 Flutter의 Firebase 인증을 구성하는 단계가 있지만 모든 옵션을 사용하도록 Firebase 프로젝트를 설정할 수 있습니다.
- 이 스크린샷은 프로세스 종료 시의 출력을 보여줍니다. Firebase에 익숙하다면 콘솔에서 플랫폼 애플리케이션 (예: Android 애플리케이션)을 만들지 않아도 되고 FlutterFire CLI가 대신 만들어 준다는 것을 알 수 있습니다.
완료되면 텍스트 편집기에서 Flutter 앱을 확인합니다. FlutterFire CLI가 firebase_options.dart
라는 파일을 수정했습니다. 이 파일에는 각 플랫폼에 필요한 Firebase 구성을 보유하는 정적 변수가 있는 FirebaseOptions
라는 클래스가 포함되어 있습니다. flutterfire configure
를 실행할 때 모든 플랫폼을 선택한 경우 web
, android
, ios
, macos
라는 정적 값이 표시됩니다.
lib/firebase_options.dart
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
return macos;
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyCqFjCV_9CZmYeIvcK9FVy4drmKUlSaIWY',
appId: '1:963656261848:web:7219f7fca5fc70afb237ad',
messagingSenderId: '963656261848',
projectId: 'flutterfire-ui-codelab',
authDomain: 'flutterfire-ui-codelab.firebaseapp.com',
storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
measurementId: 'G-DGF0CP099H',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyDconZaCQpkxIJ5KQBF-3tEU0rxYsLkIe8',
appId: '1:963656261848:android:c939ccc86ab2dcdbb237ad',
messagingSenderId: '963656261848',
projectId: 'flutterfire-ui-codelab',
storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
messagingSenderId: '963656261848',
projectId: 'flutterfire-ui-codelab',
storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
iosBundleId: 'com.example.complete',
);
static const FirebaseOptions macos = FirebaseOptions(
apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
messagingSenderId: '963656261848',
projectId: 'flutterfire-ui-codelab',
storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
iosBundleId: 'com.example.complete',
);
}
Firebase에서는 Firebase 프로젝트의 특정 플랫폼용 특정 빌드를 애플리케이션이라고 합니다. 예를 들어 FlutterFire-ui-codelab이라는 Firebase 프로젝트에는 Android용, iOS용, macOS용, 웹용 등 여러 애플리케이션이 있습니다.
DefaultFirebaseOptions.currentPlatform
메서드는 Flutter에서 노출된 TargetPlatform
enum을 사용하여 앱이 실행되는 플랫폼을 감지한 다음 올바른 Firebase 애플리케이션에 필요한 Firebase 구성 값을 반환합니다.
Flutter 앱에 Firebase 패키지 추가
마지막 설정 단계는 관련 Firebase 패키지를 Flutter 프로젝트에 추가하는 것입니다. firebase_options.dart
파일에는 아직 추가되지 않은 Firebase 패키지를 사용하므로 오류가 있어야 합니다. 터미널에서 Flutter 프로젝트의 루트(flutter-codelabs/firebase-emulator-suite/start
)에 있는지 확인합니다. 그런 다음 다음 세 명령어를 실행합니다.
flutter pub add firebase_core firebase_auth firebase_ui_auth
이 시점에서는 이러한 패키지만 필요합니다.
Firebase 초기화
추가된 패키지와 DefaultFirebaseOptions.currentPlatform,
를 사용하려면 main.dart
파일의 main
함수에서 코드를 업데이트합니다.
lib/main.dart
import 'package:firebase_core/firebase_core.dart'; // Add this import
import 'package:flutter/material.dart';
import 'app.dart';
import 'firebase_options.dart'; // And this import
// TODO(codelab user): Get API key
const clientId = 'YOUR_CLIENT_ID';
void main() async {
// Add from here...
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
// To here.
runApp(const MyApp(clientId: clientId));
}
이 코드는 두 가지 작업을 실행합니다.
WidgetsFlutterBinding.ensureInitialized()
는 Flutter 프레임워크가 완전히 부팅될 때까지 애플리케이션 위젯 코드를 실행하지 않도록 Flutter에 지시합니다. Firebase는 프레임워크가 실행되어야 하는 네이티브 플랫폼 채널을 사용합니다.Firebase.initializeApp
는 Flutter 앱과 Firebase 프로젝트 간의 연결을 설정합니다.DefaultFirebaseOptions.currentPlatform
는 생성된firebase_options.dart
파일에서 가져옵니다. 이 정적 값은 실행 중인 플랫폼을 감지하고 해당 Firebase 키를 전달합니다.
4. 초기 Firebase UI 인증 페이지 추가
인증용 Firebase UI는 애플리케이션에서 전체 화면을 나타내는 위젯을 제공합니다. 이러한 화면은 로그인, 등록, 비밀번호 찾기, 사용자 프로필 등 애플리케이션 전반에서 다양한 인증 흐름을 처리합니다. 시작하려면 기본 애플리케이션에 대한 인증 가드 역할을 하는 방문 페이지를 앱에 추가하세요.
Material 또는 Cupertino 앱
FlutterFire UI를 사용하려면 애플리케이션이 MaterialApp
또는 CupertinoApp
로 래핑되어 있어야 합니다. 선택에 따라 UI에 Material 또는 Cupertino 위젯의 차이점이 자동으로 반영됩니다. 이 Codelab에서는 app.dart
의 앱에 이미 추가된 MaterialApp
을 사용합니다.
lib/app.dart
import 'package:flutter/material.dart';
import 'auth_gate.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: AuthGate(clientId: clientId),
);
}
}
인증 상태 확인
로그인 화면을 표시하기 전에 사용자가 인증되었는지 확인해야 합니다. 이를 확인하는 가장 일반적인 방법은 Firebase 인증 플러그인을 사용하여 FirebaseAuth
의 authStateChanges
를 수신하는 것입니다.
위 코드 샘플에서 MaterialApp
는 build
메서드에서 AuthGate
위젯을 빌드합니다. (이는 FlutterFire UI에서 제공하지 않는 맞춤 위젯입니다.)
authStateChanges
스트림을 포함하도록 위젯을 업데이트해야 합니다.
authStateChanges
API는 현재 사용자(로그인한 경우) 또는 null(로그인하지 않은 경우)이 포함된 Stream
을 반환합니다. 애플리케이션에서 이 상태를 구독하려면 Flutter의 StreamBuilder 위젯을 사용하고 스트림을 전달하면 됩니다.
StreamBuilder
는 전달된 Stream의 최신 데이터 스냅샷을 기반으로 자체적으로 빌드되는 위젯입니다. Stream
에서 새 스냅샷을 내보내면 자동으로 다시 빌드됩니다.
auth_gate.dart
의 코드를 업데이트합니다.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider; // Add this import
import 'package:firebase_ui_auth/firebase_ui_auth.dart'; // And this import
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>( // Modify from here...
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(providers: []);
}
return const HomeScreen();
},
); // To here.
}
}
StreamBuilder.stream
에 앞서 언급한 스트림인FirebaseAuth.instance.authStateChanged
이 전달됩니다. 사용자가 인증된 경우 FirebaseUser
객체를 반환하고, 그렇지 않으면null
을 반환합니다.- 다음으로 코드는
snapshot.hasData
를 사용하여 스트림의 값에User
객체가 포함되어 있는지 확인합니다. - 그렇지 않으면
SignInScreen
위젯이 반환됩니다. 지금은 이 화면에서 아무 작업도 하지 않습니다. 다음 단계에서 업데이트됩니다. - 그렇지 않으면 인증된 사용자만 액세스할 수 있는 애플리케이션의 기본 부분인
HomeScreen
를 반환합니다.
SignInScreen
은 FlutterFire UI 패키지에서 제공되는 위젯입니다. 이것이 이 Codelab의 다음 단계에서 중점적으로 다룰 내용입니다. 이 시점에서 앱을 실행하면 빈 로그인 화면이 표시됩니다.
5. 로그인 화면
FlutterFire UI에서 제공하는 SignInScreen
위젯은 다음 기능을 추가합니다.
- 사용자가 로그인할 수 있도록 허용
- 사용자가 비밀번호를 잊어버린 경우 '비밀번호 찾기'를 탭하여 비밀번호 재설정 양식으로 이동할 수 있습니다.
- 아직 등록되지 않은 사용자는 '등록'을 탭하여 가입할 수 있는 다른 양식으로 이동할 수 있습니다.
이 작업에도 코드 몇 줄만 필요합니다. AuthGate
위젯의 코드를 다시 호출합니다.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(providers: [EmailAuthProvider()]); // Modify this line
}
return const HomeScreen();
},
);
}
}
SignInScreen
위젯과 providers
인수는 위에 언급된 모든 기능을 가져오는 데 필요한 유일한 코드입니다. 이제 '이메일' 및 '비밀번호' 텍스트 입력과 '로그인' 버튼이 있는 로그인 화면이 표시됩니다.
기능은 하지만 스타일이 없습니다. 위젯은 로그인 화면의 모양을 맞춤설정하는 매개변수를 노출합니다. 예를 들어 회사 로고를 추가할 수 있습니다.
로그인 화면 맞춤설정
headerBuilder
SignInScreen.headerBuilder
인수를 사용하면 로그인 양식 위에 원하는 위젯을 추가할 수 있습니다. 이 위젯은 휴대기기와 같은 좁은 화면에만 표시됩니다. 와이드 화면에서는 이 Codelab의 후반부에서 설명하는 SignInScreen.sideBuilder
를 사용할 수 있습니다.
다음 코드를 사용하여 lib/auth_gate.dart
파일을 업데이트합니다.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen( // Modify from here...
providers: [EmailAuthProvider()],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
); // To here.
}
return const HomeScreen();
},
);
}
}```
The headerBuilder argument requires a function of the type HeaderBuilder, which
is defined in the FlutterFire UI package.
```dart
typedef HeaderBuilder = Widget Function(
BuildContext context,
BoxConstraints constraints,
double shrinkOffset,
);
콜백이므로 BuildContext
, BoxConstraints
과 같은 사용할 수 있는 값을 노출하고 위젯을 반환해야 합니다. 반환하는 위젯은 화면 상단에 표시됩니다. 이 예시에서 새 코드는 화면 상단에 이미지를 추가합니다. 이제 애플리케이션이 다음과 같이 표시됩니다.
자막 빌더
로그인 화면에는 화면을 맞춤설정할 수 있는 세 가지 추가 매개변수(subtitleBuilder
, footerBuilder
, sideBuilder
)가 노출됩니다.
콜백 인수에 AuthAction
유형의 작업이 포함된다는 점에서 subtitleBuilder
와 약간 다릅니다. AuthAction
는 사용자가 있는 화면이 '로그인' 화면인지 '등록' 화면인지 감지하는 데 사용할 수 있는 enum입니다.
subtitleBuilder
를 사용하도록 auth_gate.dart의 코드를 업데이트합니다.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [EmailAuthProvider()],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) { // Add from here...
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
}, // To here.
);
}
return const HomeScreen();
},
);
}
}
바닥글 빌더
footerBuilder 인수는 subtitleBuilder와 동일합니다. 이미지가 아닌 텍스트용이므로 BoxConstraints
또는 shrinkOffset
를 노출하지 않습니다. 물론 원하는 위젯을 추가할 수 있습니다.
다음 코드를 사용하여 로그인 화면에 바닥글을 추가합니다.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [EmailAuthProvider()],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
},
footerBuilder: (context, action) { // Add from here...
return const Padding(
padding: EdgeInsets.only(top: 16),
child: Text(
'By signing in, you agree to our terms and conditions.',
style: TextStyle(color: Colors.grey),
),
);
}, // To here.
);
}
return const HomeScreen();
},
);
}
}
Side Builder
SignInScreen.sidebuilder 인수는 콜백을 허용하며 이번에는 해당 콜백의 인수가 BuildContext
및 double shrinkOffset
입니다. sideBuilder
에서 반환하는 위젯은 로그인 양식 왼쪽에 넓은 화면에서만 표시됩니다. 즉, 위젯은 데스크톱 및 웹 앱에만 표시됩니다.
내부적으로 FlutterFire UI는 중단점을 사용하여 헤더 콘텐츠를 표시해야 하는지 (모바일과 같은 긴 화면) 또는 측면 콘텐츠를 표시해야 하는지 (데스크톱 또는 웹과 같은 넓은 화면)를 결정합니다. 구체적으로 화면 너비가 800픽셀을 초과하면 측면 빌더 콘텐츠가 표시되고 헤더 콘텐츠는 표시되지 않습니다. 화면 너비가 800픽셀 미만인 경우 반대입니다.
auth_gate.dart의 코드를 업데이트하여 sideBuilder
위젯을 추가합니다.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [EmailAuthProvider()],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
},
footerBuilder: (context, action) {
return const Padding(
padding: EdgeInsets.only(top: 16),
child: Text(
'By signing in, you agree to our terms and conditions.',
style: TextStyle(color: Colors.grey),
),
);
},
sideBuilder: (context, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('flutterfire_300x.png'),
),
);
},
);
}
return const HomeScreen();
},
);
}
}
이제 창 너비를 확장하면 앱이 다음과 같이 표시됩니다 (Flutter 웹 또는 MacOS를 사용하는 경우).
사용자 생성
이제 이 화면의 코드가 모두 완료되었습니다. 하지만 로그인하려면 먼저 사용자를 만들어야 합니다. '등록' 화면을 사용하거나 Firebase 콘솔에서 사용자를 만들면 됩니다.
콘솔을 사용하려면 다음 안내를 따르세요.
- Firebase Console의 '사용자' 표로 이동합니다. 'flutterfire-ui-codelab'을 선택하거나 다른 이름을 사용한 경우 해당 프로젝트를 선택합니다. 다음 표가 표시됩니다.
- '사용자 추가' 버튼을 클릭합니다.
- 새 사용자의 이메일 주소와 비밀번호를 입력합니다. 아래 이미지에 입력한 것처럼 가짜 이메일과 비밀번호를 사용할 수 있습니다. 이렇게 하면 되지만 가짜 이메일 주소를 사용하면 '비밀번호를 잊으셨나요?' 기능이 작동하지 않습니다.
- '사용자 추가'를 클릭합니다.
이제 Flutter 애플리케이션으로 돌아가 로그인 페이지를 사용하여 사용자를 로그인할 수 있습니다. 앱은 다음과 같이 표시됩니다.
6. 프로필 화면
FlutterFire UI는 ProfileScreen
위젯도 제공하며, 이 위젯을 사용하면 몇 줄의 코드로 많은 기능을 구현할 수 있습니다.
ProfileScreen
위젯 추가
텍스트 편집기에서 home.dart
파일로 이동합니다. 다음 코드로 업데이트합니다.
lib/home.dart
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<ProfileScreen>(
builder: (context) => const ProfileScreen(),
),
);
},
),
],
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
children: [
SizedBox(width: 250, child: Image.asset('assets/dash.png')),
Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
const SignOutButton(),
],
),
),
);
}
}
새로운 코드의 참고사항은 IconButton.isPressed
메서드에 전달된 콜백입니다. 이 IconButton
를 누르면 애플리케이션이 새 익명 경로를 만들고 해당 경로로 이동합니다. 해당 경로에는 MaterialPageRoute.builder
콜백에서 반환된 ProfileScreen
위젯이 표시됩니다.
앱을 다시 로드하고 오른쪽 상단 (앱 바)에 있는 아이콘을 누르면 다음과 같은 페이지가 표시됩니다.
FlutterFire UI 페이지에서 제공하는 표준 UI입니다. 모든 버튼과 텍스트 필드는 Firebase 인증에 연결되어 있으며 즉시 작동합니다. 예를 들어 '이름' 텍스트 필드에 이름을 입력하면 FlutterFire UI가 FirebaseAuth.instance.currentUser?.updateDisplayName
메서드를 호출하여 Firebase에 해당 이름을 저장합니다.
로그아웃
현재 '로그아웃' 버튼을 누르면 앱이 변경되지 않습니다. 로그아웃되지만 AuthGate 위젯으로 다시 이동하지는 않습니다. 이를 구현하려면 ProfileScreen.actions 매개변수를 사용하세요.
먼저 home.dart의 코드를 업데이트합니다.
lib/home.dart
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<ProfileScreen>(
builder: (context) => ProfileScreen(
actions: [
SignedOutAction((context) {
Navigator.of(context).pop();
}),
],
),
),
);
},
),
],
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
children: [
SizedBox(width: 250, child: Image.asset('assets/dash.png')),
Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
const SignOutButton(),
],
),
),
);
}
}
이제 ProfileScreen
인스턴스를 만들 때 ProfileScreen.actions
인수에 작업 목록도 전달합니다. 이러한 작업은 FlutterFireUiAction
유형입니다. FlutterFireUiAction
의 하위 유형인 클래스는 다양하며 일반적으로 이러한 클래스를 사용하여 앱이 다양한 인증 상태 변경에 반응하도록 합니다. SignedOutAction은 Firebase 인증 상태가 currentUser가 null로 변경될 때 제공된 콜백 함수를 호출합니다.
SignedOutAction
가 트리거될 때 Navigator.of(context).pop()
를 호출하는 콜백을 추가하면 앱이 이전 페이지로 이동합니다. 이 예시 앱에는 하나의 영구 경로만 있습니다. 로그인한 사용자가 없으면 로그인 화면을 표시하고, 로그인한 사용자가 있으면 홈페이지를 표시합니다. 사용자가 로그아웃하면 이 문제가 발생하므로 앱에 로그인 화면이 표시됩니다.
프로필 페이지 맞춤설정
로그인 화면과 마찬가지로 프로필 페이지도 맞춤설정할 수 있습니다. 첫째, 사용자가 프로필 페이지에 있으면 현재 페이지에서 홈페이지로 돌아갈 방법이 없습니다. ProfileScreen 위젯에 AppBar를 제공하여 이 문제를 수정합니다.
lib/home.dart
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<ProfileScreen>(
builder: (context) => ProfileScreen(
appBar: AppBar(title: const Text('User Profile')),
actions: [
SignedOutAction((context) {
Navigator.of(context).pop();
}),
],
),
),
);
},
),
],
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
children: [
SizedBox(width: 250, child: Image.asset('assets/dash.png')),
Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
const SignOutButton(),
],
),
),
);
}
}
ProfileScreen.appBar
인수는 Flutter Material 패키지의 AppBar
위젯을 허용하므로 빌드하고 Scaffold
에 전달한 다른 AppBar
처럼 취급할 수 있습니다. 이 예에서는 '뒤로' 버튼을 자동으로 추가하는 기본 기능이 유지되고 화면에 제목이 표시됩니다.
프로필 화면에 자녀 추가
ProfileScreen
위젯에는 children이라는 선택적 인수도 있습니다. 이 인수는 위젯 목록을 허용하며 이러한 위젯은 ProfileScreen
을 빌드하는 데 내부적으로 이미 사용된 Column
위젯 내부에 세로로 배치됩니다. ProfileScreen
빌드 메서드의 이 Column
위젯은 전달된 하위 요소를 '로그아웃' 버튼 위에 배치합니다.
로그인 화면과 마찬가지로 회사 로고가 여기에 표시되도록 home.dart
의 코드를 업데이트합니다.
lib/home.dart
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<ProfileScreen>(
builder: (context) => ProfileScreen(
appBar: AppBar(title: const Text('User Profile')),
actions: [
SignedOutAction((context) {
Navigator.of(context).pop();
}),
],
children: [
const Divider(),
Padding(
padding: const EdgeInsets.all(2),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('flutterfire_300x.png'),
),
),
],
),
),
);
},
),
],
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
children: [
SizedBox(width: 250, child: Image.asset('assets/dash.png')),
Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
const SignOutButton(),
],
),
),
);
}
}
앱을 새로고침하면 화면에 다음과 같이 표시됩니다.
7. 멀티 플랫폼 Google 인증 로그인
FlutterFire UI는 Google, Twitter, Facebook, Apple, GitHub와 같은 서드 파티 제공업체로 인증하기 위한 위젯과 기능도 제공합니다.
Google 인증과 통합하려면 네이티브 인증 흐름을 처리하는 공식 firebase_ui_oauth_google 플러그인과 종속 항목을 설치하세요. 터미널에서 Flutter 프로젝트의 루트로 이동하여 다음 명령어를 입력합니다.
flutter pub add google_sign_in firebase_ui_oauth_google
Google 로그인 제공업체 사용 설정
다음으로 Firebase Console에서 Google 제공업체를 사용 설정합니다.
- 콘솔에서 인증 로그인 제공업체 화면으로 이동합니다.
- '새 제공업체 추가'를 클릭합니다.
- 'Google'을 선택합니다.
- '사용 설정' 스위치를 전환하고 '저장'을 누릅니다.
- 구성 파일 다운로드에 관한 정보가 포함된 모달이 표시되면 '완료'를 클릭합니다.
- Google 로그인 제공업체가 추가되었는지 확인합니다.
Google 로그인 버튼 추가
Google 로그인이 사용 설정된 상태에서 스타일이 지정된 Google 로그인 버튼을 로그인 화면에 표시하는 데 필요한 위젯을 추가합니다. auth_gate.dart
파일로 이동하여 코드를 다음과 같이 업데이트합니다.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart'; // Add this import
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [
EmailAuthProvider(),
GoogleProvider(clientId: clientId), // Add this line
],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
},
footerBuilder: (context, action) {
return const Padding(
padding: EdgeInsets.only(top: 16),
child: Text(
'By signing in, you agree to our terms and conditions.',
style: TextStyle(color: Colors.grey),
),
);
},
sideBuilder: (context, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('flutterfire_300x.png'),
),
);
},
);
}
return const HomeScreen();
},
);
}
}
여기에서 새로 추가된 코드는 SignInScreen
위젯 구성에 GoogleProvider(clientId: "YOUR_WEBCLIENT_ID")
를 추가한 것뿐입니다.
추가한 후 앱을 새로고침하면 Google 로그인 버튼이 표시됩니다.
로그인 버튼 구성
이 버튼은 추가 구성 없이는 작동하지 않습니다. Flutter Web으로 개발하는 경우 이 단계만 추가하면 됩니다. 다른 플랫폼에서는 추가 단계가 필요하며 이에 대해서는 잠시 후에 설명합니다.
- Firebase Console에서 인증 제공업체 페이지로 이동합니다.
- Google 제공업체를 클릭합니다.
- '웹 SDK 구성' 펼침 패널을 클릭합니다.
- '웹 클라이언트 ID'에서 값을 복사합니다.
- 텍스트 편집기로 돌아가서 이 ID를
clientId
이름이 지정된 매개변수에 전달하여auth_gate.dart
파일의GoogleProvider
인스턴스를 업데이트합니다.
GoogleProvider(
clientId: "YOUR_WEBCLIENT_ID"
)
웹 클라이언트 ID를 입력한 후 앱을 새로고침합니다. 웹을 사용하는 경우 'Google 계정으로 로그인' 버튼을 누르면 Google 로그인 흐름을 안내하는 새 창이 표시됩니다. 처음에는 다음과 같이 표시됩니다.
iOS 구성
iOS에서 이 기능을 사용하려면 추가 구성 프로세스가 필요합니다.
- Firebase Console에서 프로젝트 설정 화면으로 이동합니다. Firebase 앱을 나열하는 카드가 다음과 같이 표시됩니다.
- iOS를 선택합니다. 애플리케이션 이름은 스크린샷에 표시된 이름과 다릅니다. 이 Codelab을 따라
flutter-codelabs/firebase-auth-flutterfire-ui/start
프로젝트를 사용한 경우 스크린샷에 '완료'라고 표시된 부분이 '시작'이라고 표시됩니다. GoogleServices-Info.plist
버튼을 클릭하여 필요한 구성 파일을 다운로드합니다.- 다운로드한 파일을 Flutter 프로젝트의
/ios/Runner
디렉터리로 드래그합니다. - 프로젝트의 루트에서 다음 터미널 명령어를 실행하여 Xcode를 엽니다.
open ios/Runner.xcworkspace
- Runner 디렉터리를 마우스 오른쪽 버튼으로 클릭하고 'Runner'에 파일 추가를 선택합니다.
- 파일 관리자에서
GoogleService-Info.plist
를 선택합니다. - Xcode가 아닌 텍스트 편집기로 돌아가서 아래의
CFBundleURLTypes
속성을ios/Runner/Info.plist
파일에 추가합니다.<!-- Put me in the [my_project]/ios/Runner/Info.plist file --> <!-- Google Sign-in Section --> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLSchemes</key> <array> <!-- TODO Replace this value: --> <!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID --> <string>com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppkn</string> </array> </dict> </array> <!-- End of the Google Sign-in Section -->
- 웹 설정에서 추가한
GoogleProvider.clientId
를 Firebase iOS 클라이언트 ID와 연결된 클라이언트 ID로 바꿔야 합니다. 먼저 이 ID는firebase_options.dart
파일에서iOS
상수의 일부로 찾을 수 있습니다.iOSClientId
에 전달된 값을 복사합니다.static const FirebaseOptions ios = FirebaseOptions( apiKey: 'YOUR API KEY', appId: 'YOUR APP ID', messagingSenderId: '', projectId: 'PROJECT_ID', storageBucket: 'PROJECT_ID.firebasestorage.app', iosClientId: 'IOS CLIENT ID', // Find your iOS client Id here. iosBundleId: 'com.example.BUNDLE', );
- 해당 값을
lib/main.dart
파일의clientId
변수에 붙여넣습니다.
lib/main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'app.dart';
import 'firebase_options.dart';
const clientId = 'YOUR_CLIENT_ID'; // Replace this value with your Client ID.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const MyApp(clientId: clientId));
}
Flutter 앱이 이미 iOS에서 실행 중인 경우 완전히 종료한 후 애플리케이션을 다시 실행해야 합니다. 그렇지 않으면 iOS에서 앱을 실행합니다.
8. 수고하셨습니다.
Firebase Auth UI for Flutter Codelab을 완료했습니다 . 이 Codelab의 완료된 코드는 GitHub의 firebase-auth-flutterfire-ui/complete
디렉터리에서 확인할 수 있습니다.
학습한 내용
- Firebase를 사용하도록 Flutter 앱 설정
- Firebase Console에서 Firebase 프로젝트 설정
- FlutterFire CLI
- Firebase CLI
- Firebase 인증 사용
- FlutterFire UI를 사용하여 Flutter 앱에서 Firebase 인증 처리
다음 단계
- Flutter에서 Firestore 및 인증 사용에 대해 자세히 알아보세요. Flutter용 Firebase 알아보기 Codelab
- Flutter 애플리케이션 빌드를 위한 다른 Firebase 도구를 살펴봅니다.
자세히 알아보기
- Firebase 사이트: firebase.google.com
- Flutter 사이트: flutter.dev
- FlutterFire Firebase Flutter 위젯: firebase.flutter.dev
- Firebase YouTube 채널
- Flutter YouTube 채널
스파키가 여러분과 함께 축하하기 위해 왔습니다.