CH05 Firebase Authentication App

Provider ์—์„œ ๊ตฌํ˜„ํ•œ ์•ฑ๊ณผ ๋™์ผํ–ˆ๊ณ , Bloc ํ™œ์šฉ ๋ฒ”์œ„๋„ TODO ์—์„œ ๋‹ค๋ค˜๋˜ ๋ฒ”์œ„ ๋‚ด์—์„œ ๋‹ค๋ค˜๋‹ค.

๋‹จ, WillPopScope ํ™œ์šฉ์— ๋Œ€ํ•ด์„œ ๋‚ด๊ฐ€ ์˜ˆ์ „์— ์ด ์•ฑ์„ ๋งŒ๋“ค๋•Œ ๋‹ค์†Œ ์œ ์‹ฌํžˆ ๋ณด์ง€ ์•Š์•˜๋˜ ๊ฒƒ ๊ฐ™์•„์„œ ๋”ฐ๋กœ ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋‘”๋‹ค.

WillPopScope ์œ„์ ฏ์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์ ฏ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž๊ฐ€ ์Šคํƒ ๋‚ด์—์„œ ์ด์ „ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค. ์ด๋•Œ WillPopScope ์œ„์ ฏ์ด ์‚ฌ์šฉ๋˜๋ฉด, ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ๋ฅผ ์บ์น˜ํ•˜์—ฌ ์ปค์Šคํ…€ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

WillPopScope ์œ„์ ฏ์€ onWillPop ์†์„ฑ์„ ๊ฐ€์ง€๋ฉฐ, ์ด ์†์„ฑ์€ Future์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ onWillPop์ด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ด๋ฒคํŠธ๋Š” ๋ฌด์‹œ๋˜๊ณ  ์•ฑ์€ ์ด์ „ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์—, false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ด๋ฒคํŠธ๊ฐ€ ์ทจ์†Œ๋˜๊ณ  ์•ฑ์€ ํ˜„์žฌ ํ™”๋ฉด์— ๋จธ๋ฌด๋ฅด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

WillPopScope๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ Scaffold๋‚˜ AppBar์™€ ๊ฐ™์€ ์œ„์ ฏ์„ ์‚ฌ์šฉํ•  ๋•Œ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์œ„์ ฏ์„ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ํ˜„์žฌ ํ™”๋ฉด์ด ์ข…๋ฃŒ๋˜์–ด์•ผ ํ•˜์ง€๋งŒ, WillPopScope๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋ฒคํŠธ๋ฅผ ์บ์น˜ํ•˜์—ฌ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž๊ฐ€ ๋’ค๋กœ ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฆฌ์Šค๋„ˆ์— ๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ์„ค์ •ํ•ด๋’€์„๋•Œ ๋‹ค์ด์–ผ๋กœ๊ทธ๊ฐ€ ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœ๋˜๋Š” ๋ฌธ์ œ๋„ ์•„๋ž˜์™€ ๊ฐ™์ด ํ•ด๊ฒฐํ–ˆ๋‹ค.

class SplashPage extends StatelessWidget {
  static const String routeName = '/';
  const SplashPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocConsumer<AuthBloc, AuthState>(
      listener: (context, state) {
        if (state.authStatus == AuthStatus.unauthenticated) {
          Navigator.pushNamedAndRemoveUntil(
            context,
            SigninPage.routeName,
            (route) {
              print('route.settings.name: ${route.settings.name}');
              print('ModalRoute: ${ModalRoute.of(context)!.settings.name}');

              return route.settings.name ==
                      ModalRoute.of(context)!.settings.name
                  ? true
                  : false;
            },
          );
        } else if (state.authStatus == AuthStatus.authenticated) {
          Navigator.pushNamed(context, HomePage.routeName);
        }
      },
      builder: (context, state) {
        return Scaffold(
          body: Center(
            child: CircularProgressIndicator(),
          ),
        );
      },
    );
  }
}

๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ๋กœ๊ทธ์•„์›ƒ์„ ํ•œ ๋’ค ๋กœ๊ทธ์ธ์„ ์˜๋„์ ์œผ๋กœ ์‹คํŒจํ•˜๋ฉด ์›๋ž˜ ํ•œ ๋ฒˆ ๋– ์•ผํ•  ๋‹ค์ด์–ผ๋กœ๊ทธ๊ฐ€ ์ค‘์ฒฉํ•ด์„œ ๋‘ ๊ฐœ ๋œจ๋Š” ํ˜„์ƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค์ด์–ผ๋กœ๊ทธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฆฌ์Šค๋„ˆ์— ๊ฑธ๋ ค์žˆ๋‹ค.

child: BlocConsumer<SigninCubit, SigninState>(
  listener: (context, state) {
    if (state.signinStatus == SigninStatus.error) {
      errorDialog(context, state.error);
    }
  },
  ...
),  
  1. ์ƒํƒœ๊ฐ€ ์‹ค์ œ๋กœ ๋‘ ๋ฒˆ ๋ฐ”๋€Œ์—ˆ๊ฑฐ๋‚˜

  2. ๋ฆฌ์Šค๋„ˆ๊ฐ€ ๋‘ ๊ฐœ ๋“ฑ๋ก๋˜์–ด์žˆ๊ฑฐ๋‚˜

์ธ๋ฐ ์ด ๊ฒฝ์šฐ 2๋ฒˆ์˜ ๊ฒฝ์šฐ๋กœ ์ธํ•ด ๋‹ค์ด์–ผ๋กœ๊ทธ๊ฐ€ ๋‘ ๊ฐœ ๋œจ๋Š” ๊ฒƒ์ด๋‹ค. ์™œ๋ƒํ•˜๋ฉด Splash ์—์„œ pushNamed ๋กœ Signin Page ๋กœ ๋ณด๋ƒˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ฒซ ๋กœ๊ทธ์ธ ์ง„์ž…์‹œ ํ•˜๋‚˜์™€ Home ์—์„œ ๋กœ๊ทธ์•„์›ƒํ•œ ํ›„ Splash ์—์„œ ๋ถ„๊ธฐ๋ฅผ ํƒ€๋ฉด์„œ Splash ๋กœ ๋ณด๋‚ธ ๊ฒƒ ๋‘ ๊ฐœ๊ฐ€ ์ค‘์ฒฉ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ ์ž signin ์—์„œ ์Œ“์ธ ๋ผ์šฐํŠธ๋ฅผ ๊ฒ€์‚ฌํ•ด์„œ splash ์™ธ์— ๋ชจ๋“  ๊ฒƒ์„ ์—†์• ๋Š” ์ž‘์—…์„ ํ•ด์ค€ ๊ฒƒ์ด๋‹ค.

Navigator.pushNamedAndRemoveUntil ์— ๋Œ€ํ•ด์„œ ์ž ๊น ์•Œ์•„๋ณด์ž.


Navigator.pushNamedAndRemoveUntil์€ ํ˜„์žฌ ํŽ˜์ด์ง€์—์„œ ์ง€์ •ํ•œ ๊ฒฝ๋กœ ์ด๋ฆ„์˜ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋ฉด์„œ, ์ด์ „ ํŽ˜์ด์ง€ ์Šคํƒ์—์„œ ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

Navigator.pushNamedAndRemoveUntil์˜ ์ธ์ž๋กœ๋Š” 1) ์ด๋™ํ•  ๊ฒฝ๋กœ ์ด๋ฆ„๊ณผ 2) ์ด์ „ ํŽ˜์ด์ง€ ์Šคํƒ์—์„œ ์ œ๊ฑฐํ•  ํŽ˜์ด์ง€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์ด์ „ ํŽ˜์ด์ง€ ์Šคํƒ์—์„œ ๊ฐ ํŽ˜์ด์ง€๋ฅผ ๊ฒ€์‚ฌํ•˜์—ฌ ํŽ˜์ด์ง€๋ฅผ ์ œ๊ฑฐํ• ์ง€ ๋ง์ง€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ โ€˜/Aโ€™ ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•˜๋ฉด์„œ ์ด์ „ ํŽ˜์ด์ง€ ์Šคํƒ์—์„œ โ€˜/โ€™ (๋ฃจํŠธ) ๊ฒฝ๋กœ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Navigator.pushNamedAndRemoveUntil(
  context,
  '/A',
  (route) => route.settings.name == '/',
);

๋„ํ๋จผํŠธ๋ฅผ ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋‚˜์™€์žˆ๋‹ค.

  /// Push the route with the given name onto the navigator, and then remove all
  /// the previous routes until the `predicate` returns true.
  ///
  /// {@macro flutter.widgets.navigator.pushNamedAndRemoveUntil}
  ///
  /// {@macro flutter.widgets.navigator.pushNamed.returnValue}
  ///
  /// {@macro flutter.widgets.Navigator.pushNamed}
  ///
  /// {@tool snippet}
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// void _handleOpenCalendar() {
  ///   navigator.pushNamedAndRemoveUntil('/calendar', ModalRoute.withName('/'));
  /// }
  /// ```
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [restorablePushNamedAndRemoveUntil], which pushes a new route that can
  ///    be restored during state restoration.
  @optionalTypeArgs
  Future<T?> pushNamedAndRemoveUntil<T extends Object?>(
    String newRouteName,
    RoutePredicate predicate, {
    Object? arguments,
  }) {
    return pushAndRemoveUntil<T>(_routeNamed<T>(newRouteName, arguments: arguments)!, predicate);
  }

Push the route with the given name onto the navigator, and then remove all the previous routes until the predicate returns true.

์ด๊ฑธ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด โ€˜๋ฌด์กฐ๊ฑด ์ง€์šด๋‹ค. predicate ์ด true ๋ฅผ return ํ•  ๋•Œ ๊นŒ์ง€โ€™ ๋กœ ๋™์ž‘ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ pushNamedAndRemoveUntil ๊ฐ€ ์‹คํ–‰๋˜๋ฉด predicate ์—์„œ ํ˜„์žฌ ์Šคํƒ์— ์Œ“์ธ ๋ชจ๋“  route ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ predicate ์ ์šฉ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์‚ฌํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

Last updated