FirebaseUI를 사용하여 Flutter 앱에 사용자 인증 흐름 추가

1. 시작하기 전에

이 Codelab에서는 FlutterFire UI 패키지를 사용하여 Flutter 앱에 Firebase 인증을 추가하는 방법을 알아봅니다. 이 패키지를 사용하여 이메일/비밀번호 인증과 Google 로그인 인증을 모두 Flutter 앱에 추가합니다. Firebase 프로젝트를 설정하고 FlutterFire CLI를 사용하여 Flutter 앱에서 Firebase를 초기화하는 방법도 알아봅니다.

기본 요건

이 Codelab에서는 Flutter를 사용한 경험이 있다고 가정합니다. 그렇지 않은 경우 먼저 기본사항을 학습하는 것이 좋습니다. 다음 링크가 도움이 됩니다.

Firebase에 대한 경험이 어느 정도 있어야 하지만 Flutter 프로젝트에 Firebase를 추가한 적이 없다면 괜찮습니다. Firebase Console에 익숙하지 않거나 Firebase를 처음 사용하는 경우 먼저 다음 링크를 참고하세요.

만들 항목

이 Codelab에서는 인증을 위해 Firebase를 사용하여 Flutter 앱의 인증 흐름을 빌드하는 방법을 안내합니다. 애플리케이션에는 로그인 화면, '등록' 화면, 비밀번호 복구 화면, 사용자 프로필 화면이 있습니다.

6604fc9157f2c6ae.png eab9509a41074930.png da49189a5838e0bb.png b2ccfb3632b77878.png

학습할 내용

이 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
  • 텍스트 편집기 (Flutter에서 JetBrains IDE, Android 스튜디오, VS Code를 지원함)
  • Google Chrome 브라우저 또는 개발자가 선호하는 다른 Flutter 개발 타겟 (이 Codelab의 일부 터미널 명령어는 Chrome에서 앱을 실행한다고 가정합니다.)

2. Firebase 프로젝트 만들기 및 설정

먼저 Firebase 웹 콘솔에서 Firebase 프로젝트를 만들어야 합니다.

Firebase 프로젝트 만들기

  1. Firebase에 로그인합니다.
  2. Firebase Console에서 프로젝트 추가 (또는 프로젝트 만들기)를 클릭하고 Firebase 프로젝트의 이름을 입력합니다 (예: 'FlutterFire-UI-Codelab').

df42a5e3d9584b48.png

  1. 프로젝트 만들기 옵션을 클릭하며 살펴봅니다. 메시지가 표시되면 Firebase 약관에 동의합니다. 이 앱에는 애널리틱스를 사용하지 않으므로 Google 애널리틱스 설정은 건너뛰세요.

d1fcec48bf251eaa.png

Firebase 프로젝트에 관해 자세히 알아보려면 Firebase 프로젝트 이해를 참고하세요.

Firebase 인증에 이메일 로그인 사용 설정

빌드 중인 앱은 Firebase 인증을 사용하여 사용자가 앱에 로그인할 수 있도록 합니다. 또한 신규 사용자가 Flutter 애플리케이션에서 등록할 수 있습니다.

Firebase 인증은 Firebase Console을 사용하여 사용 설정해야 하며, 사용 설정된 후에는 특별한 구성이 필요합니다.

사용자가 웹 앱에 로그인할 수 있도록 하려면 먼저 이메일/비밀번호 로그인 방법을 사용합니다. 나중에 Google 로그인 메서드를 추가합니다.

  1. Firebase Console의 왼쪽 패널에서 빌드 메뉴를 펼칩니다.
  2. 인증을 클릭한 후 시작하기 버튼을 클릭한 다음 로그인 방법 탭을 클릭합니다 (또는 여기를 클릭하여 로그인 방법 탭으로 바로 이동).
  3. 로그인 제공업체 목록에서 이메일/비밀번호를 클릭하고 사용 설정 스위치를 켭 위치로 설정한 다음 저장을 클릭합니다. 58e3e3e23c2f16a4.png

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를 설치하는 방법에는 여러 가지가 있습니다. MacOS 또는 Linux를 사용하는 경우 가장 간단한 방법은 터미널에서 다음 명령어를 실행하는 것입니다.

curl -sL https://firebase.tools | bash

CLI를 설치한 후에는 Firebase로 인증해야 합니다.

  1. 다음 명령어를 실행하여 Google 계정으로 Firebase에 로그인합니다.
firebase login
  1. 이 명령어는 로컬 머신을 Firebase에 연결하고 Firebase 프로젝트에 대한 액세스 권한을 부여합니다.
  1. Firebase 프로젝트를 나열하여 CLI가 올바르게 설치되었고 사용자 계정에 액세스하는지 테스트합니다. 다음 명령어를 실행합니다.
firebase projects:list
  1. 표시된 목록은 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 프로젝트와 설정할 플랫폼을 선택하라는 메시지가 표시됩니다.

다음 스크린샷은 답변해야 하는 메시지를 보여줍니다.

  1. 사용할 프로젝트를 선택합니다. 이 경우 flutterfire-ui-codelab 1359cdeb83204baa.png를 사용합니다.
  2. 사용할 플랫폼을 선택합니다. 이 Codelab에서는 웹, iOS, Android용 Flutter의 Firebase 인증을 구성하는 단계를 설명하지만 모든 옵션을 사용하도록 Firebase 프로젝트를 설정할 수 있습니다. 301c9534f594f472.png
  3. 이 스크린샷은 프로세스 종료 시의 출력을 보여줍니다. Firebase에 익숙한 경우 Console에서 플랫폼 애플리케이션 (예: Android 애플리케이션)을 만들지 않아도 FlutterFire CLI에서 자동으로 만들었음을 알 수 있습니다. 12199a85ade30459.png

완료되면 텍스트 편집기에서 Flutter 앱을 확인합니다. FlutterFire CLI에서 firebase_options.dart라는 새 파일을 생성했습니다. 이 파일에는 각 플랫폼에 필요한 Firebase 구성을 보유하는 정적 변수가 있는 FirebaseOptions라는 클래스가 포함되어 있습니다. flutterfire configure를 실행할 때 모든 플랫폼을 선택한 경우 web, android, ios, macos라는 정적 값이 표시됩니다.

firebase_options.dart

import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
   show defaultTargetPlatform, kIsWeb, TargetPlatform;

/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
///   options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
 static FirebaseOptions get currentPlatform {
   if (kIsWeb) {
     return web;
   }
   // ignore: missing_enum_constant_in_switch
   switch (defaultTargetPlatform) {
     case TargetPlatform.android:
       return android;
     case TargetPlatform.iOS:
       return ios;
     case TargetPlatform.macOS:
       return macos;
   }

   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 패키지 추가

마지막 설정 단계는 Flutter 프로젝트에 관련 Firebase 패키지를 추가하는 것입니다. firebase_options.dart 파일에는 아직 추가되지 않은 Firebase 패키지를 사용하므로 오류가 있습니다. 터미널에서 flutter-codelabs/firebase-emulator-suite/start의 Flutter 프로젝트 루트에 있는지 확인합니다. 그런 다음 다음 세 가지 명령어를 실행합니다.

flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add firebase_ui_auth

현재 필요한 패키지는 이 두 가지뿐입니다.

Firebase 초기화

추가된 패키지를 사용하려면 DefaultFirebaseOptions.currentPlatform,main.dart 파일의 main 함수에서 코드를 업데이트합니다.

main.dart

void main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp(
   options: DefaultFirebaseOptions.currentPlatform,
 );


 runApp(const MyApp());
}

이 코드는 두 가지 작업을 실행합니다.

  1. WidgetsFlutterBinding.ensureInitialized()는 Flutter 프레임워크가 완전히 부팅될 때까지 애플리케이션 위젯 코드 실행을 시작하지 말라고 Flutter에 지시합니다. Firebase는 프레임워크가 실행되어야 하는 네이티브 플랫폼 채널을 사용합니다.
  2. 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을 사용합니다.

app.dart

import 'package:flutter/material.dart';
import 'auth_gate.dart';

class MyApp extends StatelessWidget {
 const MyApp({super.key});
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     theme: ThemeData(
       primarySwatch: Colors.blue,
     ),
     home: const AuthGate(),
   );
 }
}

인증 상태 확인

로그인 화면을 표시하려면 사용자가 현재 인증되었는지 확인해야 합니다. 이를 확인하는 가장 일반적인 방법은 Firebase 인증 플러그인을 사용하여 FirebaseAuth의 authStateChanges를 리슨하는 것입니다.

위의 코드 샘플에서 MaterialApp는 build 메서드에서 AuthGate 위젯을 빌드하고 있습니다. 이 위젯은 FlutterFire UI에서 제공하지 않는 맞춤 위젯입니다.

authStateChanges 스트림을 포함하도록 위젯을 업데이트해야 합니다.

authStateChanges API는 현재 로그인한 사용자 (로그인한 경우)가 포함된 Stream 또는 로그인하지 않은 경우 null을 반환합니다. 애플리케이션에서 이 상태를 구독하려면 Flutter의 StreamBuilder 위젯을 사용하고 스트림을 전달하면 됩니다.

StreamBuilder는 전달된 스트림의 데이터의 최신 스냅샷을 기반으로 자체 빌드되는 위젯입니다. 스트림에서 새 스냅샷을 내보낼 때 자동으로 다시 빌드됩니다.

auth_gate.dart의 코드를 업데이트합니다.

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});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [],
          );
        }

        return const HomeScreen();
      },
    );
  }
}
  • StreamBuilder.stream에 앞서 언급한 스트림인 FirebaseAuth.instance.authStateChanged이 전달됩니다. 이 스트림은 사용자가 인증된 경우 Firebase User 객체를 반환합니다. 그렇지 않으면 null을 반환합니다.
  • 다음으로 코드는 snapshot.hasData를 사용하여 스트림의 값에 User 객체가 포함되어 있는지 확인합니다.
  • 없으면 SignInScreen 위젯이 반환됩니다. 현재 이 화면은 아무것도 하지 않습니다. 이 내용은 다음 단계에서 업데이트됩니다.
  • 그렇지 않으면 인증된 사용자만 액세스할 수 있는 애플리케이션의 기본 부분인 HomeScreen를 반환합니다.

SignInScreen는 FlutterFire UI 패키지에서 가져온 위젯입니다. 이 내용은 이 Codelab의 다음 단계에서 다룹니다. 이 시점에서 앱을 실행하면 빈 로그인 화면이 표시됩니다.

5. 로그인 화면

FlutterFire UI에서 제공하는 SignInScreen 위젯은 다음 기능을 추가합니다.

  • 사용자가 로그인하도록 허용
  • 사용자가 비밀번호를 잊어버린 경우 '비밀번호 찾기'를 탭하면 비밀번호 재설정 양식으로 이동합니다.
  • 아직 등록하지 않은 사용자는 '등록'을 탭하면 가입할 수 있는 다른 양식으로 이동할 수 있습니다.

이 작업에는 코드 몇 줄만 있으면 됩니다. AuthGate 위젯의 코드를 호출합니다.

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});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [
              EmailAuthProvider(), // new
            ],
          );
        }

        return const HomeScreen();
      },
    );
  }
}

SignInScreen 위젯과 providers 인수가 앞서 언급된 모든 기능을 가져오는 데 필요한 유일한 코드입니다. 이제 '이메일' 및 '비밀번호' 텍스트 입력란과 '로그인' 버튼이 있는 로그인 화면이 표시됩니다.

작동하지만 스타일이 없습니다. 위젯은 로그인 화면의 모양을 맞춤설정하는 매개변수를 노출합니다. 예를 들어 회사 로고를 추가할 수 있습니다.

로그인 화면 맞춤설정

headerBuilder

SignInScreen.headerBuilder 인수를 사용하여 로그인 양식 위에 원하는 위젯을 추가할 수 있습니다. 이 위젯은 휴대기기와 같이 좁은 화면에만 표시됩니다. 넓은 화면에서는 이 Codelab의 후반부에서 설명하는 SignInScreen.sideBuilder를 사용할 수 있습니다.

다음 코드를 사용하여 auth_gate.dart 파일을 업데이트합니다.

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});

 @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'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

headerBuilder 인수에는 FlutterFire UI 패키지에 정의된 HeaderBuilder 유형의 함수가 필요합니다.

typedef HeaderBuilder = Widget Function(
 BuildContext context,
 BoxConstraints constraints,
 double shrinkOffset,
);

콜백이므로 BuildContextBoxConstraints와 같이 사용할 수 있는 값을 노출하고 위젯을 반환해야 합니다. 반환하는 위젯이 화면 상단에 표시됩니다. 이 예에서는 새 코드가 화면 상단에 이미지를 추가합니다. 이제 애플리케이션이 다음과 같이 표시됩니다.

73d7548d91bbd2ab.png

자막 빌더

로그인 화면은 화면을 맞춤설정할 수 있는 세 가지 매개변수(subtitleBuilder, footerBuilder, sideBuilder)를 추가로 노출합니다.

subtitleBuilder는 콜백 인수에 AuthAction 유형의 작업이 포함된다는 점에서 약간 다릅니다. AuthAction는 사용자가 있는 화면이 '로그인' 화면인지 '등록' 화면인지 감지하는 데 사용할 수 있는 enum입니다.

subtitleBuilder를 사용하도록 auth_gate.dart의 코드를 업데이트합니다.

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});

 @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('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!'),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

애플리케이션을 새로고침하면 다음과 같이 표시됩니다.

footerBuilder 인수는 subtitleBuilder와 동일합니다. 이미지가 아닌 텍스트용으로 설계되어 BoxConstraints 또는 shrinkOffset를 노출하지 않습니다. 원하는 위젯을 추가할 수는 있습니다.

이 코드를 사용하여 로그인 화면에 바닥글을 추가합니다.

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});

 @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('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),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }}

측면 빌더

SignInScreen.sidebuilder 인수는 콜백을 허용하며, 이번에는 콜백의 인수가 BuildContextdouble shrinkOffset입니다. sideBuilder가 반환하는 위젯은 로그인 양식 왼쪽에 와이드 화면에서만 표시됩니다. 즉, 위젯은 데스크톱 및 웹 앱에만 표시됩니다.

내부적으로 FlutterFire UI는 브레이크포인트를 사용하여 헤더 콘텐츠를 표시해야 하는지 (모바일과 같은 세로 모드 화면) 아니면 측면 콘텐츠를 표시해야 하는지 (가로 모드 화면, 데스크톱 또는 웹)를 결정합니다. 특히 화면 너비가 800픽셀을 초과하면 측면 빌더 콘텐츠가 표시되고 헤더 콘텐츠는 표시되지 않습니다. 화면 너비가 800픽셀 미만이면 그 반대가 적용됩니다.

auth_gate.dart의 코드를 업데이트하여 sideBuilder 위젯을 추가합니다.

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});

 @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('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를 사용하는 경우 창 너비를 넓히면 앱이 다음과 같이 표시됩니다.

8dc60b4e5d7dd2d0.png

사용자 생성

이제 이 화면에 관한 모든 코드가 완료되었습니다. 하지만 로그인하기 전에 사용자를 만들어야 합니다. '등록' 화면을 사용하거나 Firebase Console에서 사용자를 만들 수 있습니다.

콘솔을 사용하려면 다음 안내를 따르세요.

  1. Firebase Console에서 '사용자' 테이블로 이동합니다.
  2. 여기를 클릭
  3. 'flutterfire-ui-codelab' (또는 다른 이름을 사용한 경우 다른 프로젝트)을 선택합니다. 다음과 같은 표가 표시됩니다.

f038fd9a58ed60d9.png

  1. '사용자 추가' 버튼을 클릭합니다.

2d78390d4c5dbbfa.png

  1. 새 사용자의 이메일 주소와 비밀번호를 입력합니다. 아래 이미지에 입력한 이메일과 비밀번호는 가짜일 수 있습니다. 이메일 주소를 입력하면 되지만 가짜 이메일 주소를 사용하면 '비밀번호 찾기' 기능이 작동하지 않습니다.

62ba0feb33d54add.png

  1. '사용자 추가'를 클릭합니다.

32b236b3ef94d4c7.png

이제 Flutter 애플리케이션으로 돌아가 로그인 페이지를 통해 사용자를 로그인할 수 있습니다. 앱이 다음과 같이 표시됩니다.

dd43d260537f3b1a.png

6. 프로필 화면

FlutterFire UI는 ProfileScreen 위젯도 제공합니다. 이 위젯을 사용하면 코드 몇 줄로 많은 기능을 사용할 수 있습니다.

ProfileScreen 위젯 추가

텍스트 편집기에서 home.dart 파일로 이동합니다. 다음 코드로 업데이트합니다.

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: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

주목할 만한 새 코드는 IconButton.isPressed method.에 전달된 콜백입니다. 이 IconButton가 눌리면 애플리케이션이 새 익명의 경로를 만들고 해당 경로로 이동합니다. 이 경로에는 MaterialPageRoute.builder 콜백에서 반환된 ProfileScreen 위젯이 표시됩니다.

앱을 새로고침하고 오른쪽 상단의 아이콘 (앱 바)을 누르면 다음과 같은 페이지가 표시됩니다.

36487fc4ab4f26a7.png

FlutterFire UI 페이지에서 제공하는 표준 UI입니다. 모든 버튼과 텍스트 필드는 Firebase 인증에 연결되어 있으며 즉시 작동합니다. 예를 들어 '이름' 텍스트 필드에 이름을 입력하면 FlutterFire UI에서 FirebaseAuth.instance.currentUser?.updateDisplayName 메서드를 호출하여 Firebase에 이름을 저장합니다.

로그아웃

현재 '로그아웃' 버튼을 누르면 앱이 변경되지 않습니다. 로그아웃되지만 AuthGate 위젯으로 다시 이동되지는 않습니다. 이를 구현하려면 ProfileScreen.actions 매개변수를 사용하세요.

먼저 home.dart의 코드를 업데이트합니다.

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: [
            Image.asset('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를 제공하여 이 문제를 해결합니다.

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: [
           Image.asset('dash.png'),
           Text(
             'Welcome!',
             style: Theme.of(context).textTheme.displaySmall,
           ),
           const SignOutButton(),
         ],
       ),
     ),
   );
 }
}

ProfileScreen.appBar 인수는 Flutter Material 패키지의 AppBar 위젯을 허용하므로 빌드하여 Scaffold에 전달한 다른 AppBar와 마찬가지로 취급할 수 있습니다. 이 예에서는 '뒤로' 버튼을 자동으로 추가하는 기본 기능이 유지되고 화면에 제목이 추가됩니다.

프로필 화면에 자녀 추가하기

ProfileScreen 위젯에는 children이라는 선택적 인수도 있습니다. 이 인수는 위젯 목록을 허용하며, 이러한 위젯은 이미 내부적으로 ProfileScreen을 빌드하는 데 사용된 Column 위젯 내에 세로로 배치됩니다. ProfileScreen 빌드 메서드의 이 열 위젯은 전달된 하위 요소를 '로그아웃' 버튼 위에 배치합니다.

로그인 화면과 마찬가지로 회사 로고를 표시하도록 home.dart의 코드를 업데이트합니다.

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: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

앱을 새로고침하면 화면에 다음과 같이 표시됩니다.

ebe5792b765dbf87.png

7. 멀티플랫폼 Google 인증 로그인

FlutterFire UI는 Google, 트위터, Facebook, Apple, GitHub와 같은 서드 파티 제공업체로 인증하기 위한 위젯과 기능도 제공합니다.

Google 인증과 통합하려면 네이티브 인증 흐름을 처리하는 공식 firebase_ui_oauth_google 플러그인과 종속 항목을 설치합니다. 터미널에서 Flutter 프로젝트의 루트로 이동하여 다음 명령어를 입력합니다.

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Google 로그인 제공업체 사용 설정

그런 다음 Firebase Console에서 Google 제공업체를 사용 설정합니다.

  1. 콘솔에서 인증 로그인 제공업체 화면으로 이동합니다.
  2. '새 제공업체 추가'를 클릭합니다. 8286fb28be94bf30.png
  3. 'Google'을 선택합니다. c4e28e6f4974be7f.png
  4. '사용'이라고 라벨이 지정된 스위치를 전환하고 '저장'을 누릅니다. e74ff86990763826.png
  5. 구성 파일 다운로드에 관한 정보가 포함된 모달이 표시되면 '완료'를 클릭합니다.
  6. Google 로그인 제공업체가 추가되었는지 확인합니다. 5329ce0543c90d95.png

Google 로그인 버튼 추가

Google 로그인을 사용 설정한 상태에서 로그인 페이지에 스타일이 지정된 Google 로그인 버튼을 표시하는 데 필요한 위젯을 추가합니다. auth_gate.dart 파일로 이동하여 코드를 다음과 같이 업데이트합니다.

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'; // new
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR_WEBCLIENT_ID"),  // new
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('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 로그인 버튼이 표시됩니다.

aca71a46a011bfb5.png

로그인 버튼 구성

추가 구성 없이는 버튼이 작동하지 않습니다. Flutter Web으로 개발하는 경우 이 작업을 실행하기 위해 추가해야 하는 유일한 단계입니다. 다른 플랫폼에는 추가 단계가 필요하며 이는 조금 후에 설명합니다.

  1. Firebase Console에서 인증 제공업체 페이지로 이동합니다.
  2. Google 제공업체를 클릭합니다. 9b3a325c5eca6e49.png
  3. '웹 SDK 구성' 확장 패널을 클릭합니다.
  4. '웹 클라이언트 ID' 711a79f0d931c60f.png의 값을 복사합니다.
  5. 텍스트 편집기로 돌아가서 이 ID를 이름이 clientId인 매개변수에 전달하여 auth_gate.dart 파일의 GoogleProvider 인스턴스를 업데이트합니다.
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

웹 클라이언트 ID를 입력한 후 앱을 새로고침합니다. 'Google 계정으로 로그인' 버튼을 누르면 Google 로그인 흐름을 안내하는 새 창이 표시됩니다 (웹을 사용하는 경우). 처음에는 다음과 같이 표시됩니다.

14e73e3c9de704bb.png

iOS 구성

iOS에서 이 기능을 사용하려면 추가 구성 프로세스가 필요합니다.

  1. Firebase Console에서 프로젝트 설정 화면으로 이동합니다. Firebase 앱이 다음과 같이 표시된 카드가 표시됩니다. fefa674acbf213cc.png
  2. iOS를 클릭합니다. 애플리케이션 이름은 제 이름과 다를 수 있습니다. flutter-codelabs/firebase-auth-flutterfire-ui/start 프로젝트를 사용하여 이 Codelab을 따라 했다면 '완료'라고 표시된 부분에 '시작'이라고 표시됩니다.
  3. 'GoogleServices-Info.plist' 버튼을 클릭하여 필요한 구성 파일을 다운로드합니다. f89b3192871dfbe3.png
  4. 다운로드한 파일을 라는 디렉터리로 드래그 앤 드롭합니다 ./ios/Runner를 사용합니다.
  5. 프로젝트 루트에서 다음 터미널 명령어를 실행하여 Xcode를 엽니다. open ios/Runner.xcworkspace
  6. Runner 디렉터리를 마우스 오른쪽 버튼으로 클릭하고 'Runner'에 파일 추가를 선택합니다. 858986063a4c5201.png
  7. 파일 관리자에서 GoogleService-Info.plist를 선택합니다.
  8. Xcode가 아닌 텍스트 편집기로 돌아가 [my_project]/ios/Runner/Info.plist 파일에 아래의 CFBundleURLTypes 속성을 추가합니다.
<!-- 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 -->
  1. 웹 설정에서 추가한 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',
);
  1. 이 값을 AuthGate 위젯의 GoogleProvider.clientId 인수에 붙여넣습니다.
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';
import 'package:flutter/material.dart';

import 'home.dart';


class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR IOS CLIENT ID"),  // replace String
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('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 앱이 이미 iOS에서 실행 중인 경우 완전히 종료한 다음 애플리케이션을 다시 실행해야 합니다. 그렇지 않으면 iOS에서 앱을 실행합니다.

8. 수고하셨습니다.

Flutter용 Firebase 인증 UI Codelab을 완료했습니다 . 이 Codelab의 완료된 코드는 github의 'complete' 디렉터리(Flutter Codelabs)에서 확인할 수 있습니다.

학습한 내용

  • Firebase를 사용하도록 Flutter 앱 설정
  • Firebase Console에서 Firebase 프로젝트 설정
  • FlutterFire CLI
  • Firebase CLI
  • Firebase 인증 사용
  • FlutterFire UI를 사용하여 Flutter 앱에서 Firebase 인증을 쉽게 처리

다음 단계

자세히 알아보기

스파키가 함께 축하해 드립니다.

2a0ad195769368b1.gif