[Flutter] auto route 를 이용한 화면 이동 2

동동·2022년 6월 15일
0

flutter auto_route

목록 보기
2/2

저번 글에서 auto_route 를 이용한 Flutter 의 화면 routing 을 알아보았다. 이전 시간에 알아 본 내용만으로도 auto_route 의 사용함에 충분한 이유가 될 수 있지만 그 밖에 auto_route 를 더 강력하게 만들어 주는 기능들을 알아보자.

Tab Navigation

Tab Navigation 은 모바일에서 가장 자주 쓰이는 형태의 화면 구성이다. 각 Tab 별로 화면 스택이 별도로 이루어지며, Tab 이동시 이전 Tab 의 화면 스택 히스토리도 유지되어야 한다. 이를 구현하기는 자체 구현하는것은 이거저거 신경쓸게 많아서 골치가 아프다. 하지만 auto_route 는 이를 쉽고 직관적으로 사용할 수 있도록 도와준다.

appRouter 설정

auto_route 에서 사용되는 모든 화면 route 정보는 appRouter 를 통해 한다고 했었다. 그럼 Tab Navigation 과 같은 Nested Navigation 은 어떻게 설정해야 할까.

간단히 children 프로퍼티 통해 nested 될 화면들을 전달해주면 된다.

(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(
      page: HomePage,
      initial: true,
      children: [
        AutoRoute(page: BookFeedPage),
        AutoRoute(page: BookListPage),
        AutoRoute(page: MyInfoPage)
      ]
    ),
    AutoRoute(path:' /login', page: LoginPage)
  ]
)
class $AppRouter {}

children 프로퍼티 통해 화면들을 리스트로 전달해 주었다. 물론 nested 의 nested 된 구성도 가능하다. 하지만 모바일 UI 에서 그렇게 까지 구성하는것은은 좋은 방식이 아니라고 생각된다.

Tab 화면 설정

이제 routing 설정이 끝났으니 실제 화면에서 Tab 을 구현해 보자.
구현은 AutoTabsRouter 를 이용해서 구현할 수 있다.

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return AutoTabsRouter(
        routes: const [
          BookFeedRoute(),
          BookListRoute(),
          MyInfoRoute()
        ],
        builder: (context, child, animation) {
          final tabRouter = AutoTabsRouter.of(context);

          return Scaffold(
            body: FadeTransition(
              opacity: animation,
              child: child,
            ),
            bottomNavigationBar: BottomNavigationBar(
              currentIndex: tabRouter.activeIndex,
              onTap: (index) {
                tabRouter.setActiveIndex(index);
              },
              items: const [
                BottomNavigationBarItem(icon: Icon(Icons.feed), label: 'book feed'),
                BottomNavigationBarItem(icon: Icon(Icons.book), label: 'book list'),
                BottomNavigationBarItem(icon: Icon(Icons.man), label: 'my info'),
              ],
            ),
          );
        }
    );
  }
}

AutoTabsRouter 를 통해 route 정보를 등록하였고, UI 로 구성은 builder 를 통해 구현하였다.

만약 위 코드 보다 좀 더 간단하게 구현하고 싶다면 AutoTabsScaffold 을 이용한다면 좀 더 간결한 코드를 작성할 수 있다.

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return AutoTabsScaffold(
        routes: const [
          BookFeedRoute(),
          BookListRoute(),
          MyInfoRoute()
        ],
      bottomNavigationBuilder: (_, tabsRouter) {
          return BottomNavigationBar(
              currentIndex: tabsRouter.activeIndex,
              onTap: tabsRouter.setActiveIndex,
              items: const [
                BottomNavigationBarItem(icon: Icon(Icons.feed), label: 'book feed'),
                BottomNavigationBarItem(icon: Icon(Icons.book), label: 'book list'),
                BottomNavigationBarItem(icon: Icon(Icons.man), label: 'my info'),
              ]
          );
      },
    );
  }
}

Route Guard 활용

만약 특정 화면에서 로그인 여부에 따라 화면 제한을 걸고 싶을 때 RouteGuard 를 사용할 수 있다.
RouteGuard 는 일종의 middleware 또는 interceptor 라고 생각하면 된다. 화면 진입시 권한 체크를 통해 로그인 화면으로 이동시켜줄 수 있고, 로그인 결과에 따라 화면 이동 여부를 결정 해 줄 수 있다

class AuthGuard extends AutoRouteGuard {        
         
 void onNavigation(NavigationResolver resolver, StackRouter router) {        
     if(authenitcated){        
       // 접근 권한이 있다면 화면 이동
        resolver.next(true);        
      }else{        
         // 접근 권한이 없다면 로그인 화면으로 이동 시킨다      
         router.push(LoginRoute(onResult: (success){        
               // 로그인 화면에서의 결과에 따라 화면 이동 여부를 결정
               resolver.next(success);        
          }));        
         }            
     }        
}

위에 작성한 Guard 를 my_info.dart 화면에 연결시켜주기 위해서는 아래와 같이 설정하면 된다.

(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(
      page: HomePage,
      initial: true,
      children: [
        AutoRoute(page: BookFeedPage),
        AutoRoute(page: BookListPage),
        AutoRoute(page: MyInfoPage, guards: [AuthGuard]) // Guard 추가
      ]
    ),
    AutoRoute(path:' /login', page: LoginPage)
  ]
)
class $AppRouter {}

복수의 guard 를 등록하고 싶다면 list 안에 추가적으로 추가하면 된다.

Observer 이용

observer 는 화면 이동이 일어날 때 그 변화를 추적할 수 있다. AutoRouterObserver 를 이용해서 구현 할 수 있다.

class RouteObserver extends AutoRouteObserver{
  // 화면이 push 될 때
  
  void didPush(Route route, Route? previousRoute) {
    print('New route pushed: ${route.settings.name}');
  }

  // Tab router 가 초기화 될 때
  
  void didInitTabRoute(TabPageRoute route, TabPageRoute? previousRoute) {
    print('Tab route visited: ${route.name}');
  }
  // Tab 이동이 일어날 때
  
  void didChangeTabRoute(TabPageRoute route, TabPageRoute previousRoute) {
    print('Tab route re-visited: ${route.name}');
  }
}

작성된 Observer 는 main.dart 의 router 설정하는 부분에서 해 줄 수 있다. navigatorObservers 는 list 형태로 반환되며, 복수의 Observer 를 등록할 수 있다.

return MaterialApp.router(        
      routerDelegate: AutoRouterDelegate(        
        _appRouter,        
        navigatorObservers: () => [RouteObserver()],        
      ),        
      routeInformationParser: _appRouter.defaultRouteParser(),        
    );

결론

지금까지 Auto_route 에 대해 알아보았다. 모바일 개발에서 routing 은 매우 중요한 부분 중에 하나다. 사실 다른건 다 몰라도 tab 구현과 guard 를 이용한 화면 관리는 매우 유용하게 쓰일 수 있을꺼 같다. 앱 개발시 초반에 화면 routing 에 대한 규칙을 정하고 미리 뼈대를 잡아 둘 수 있다면 프로젝트 수행이 한결 편해질 것이다.

참고

https://pub.dev/packages/auto_route#route-guards

0개의 댓글