Flutter에서의 Route 기능은 애플리케이션의 다양한 화면이나 페이지로 사용자를 안내하는 중요한 역할을 합니다.
이 기능을 통해 사용자는 앱 내에서 원활하게 화면을 전환하고, 다양한 데이터와 상호작용할 수 있습니다.
Route 란?
소개
Route는 Flutter 앱에서 사용자 인터페이스의 경로 또는 화면을 나타냅니다.
각 Route는 앱의 다른 화면이나 페이지를 의미하며, 사용자가 앱 내에서 이동할 때마다 새로운 Route로 전환되는 구조를 가지고 있습니다.
이를 통해 사용자는 앱의 다양한 부분을 자연스럽게 탐색할 수 있으며, 개발자는 사용자 경험을 효과적으로 설계할 수 있습니다.
기능
- 화면 전환 관리: 사용자가 앱 내에서 다른 페이지로 이동할 때, Route는 새로운 화면을 표시하고 이전 화면을 스택에서 관리합니다. 이는 사용자가 앱을 탐색할 때 일관된 경험을 제공합니다.
- 데이터 전달: Route를 통해 화면 간에 데이터를 전달할 수 있습니다. 예를 들어, 사용자가 선택한 아이템의 정보를 세부 정보 페이지로 전달하여 해당 내용을 표시할 수 있습니다.
- 사용자 경험 향상: 다양한 전환 효과와 애니메이션을 사용하여 Route 전환을 보다 매끄럽고 직관적으로 만들 수 있습니다. 이는 사용자의 몰입감을 높이고, 앱의 전반적인 외관을 개선하는 데 도움이 됩니다.
Navigator Widget
소개
Flutter에서 Navigator
Widget 은 앱 내에서 페이지 간의 이동을 관리하는 매우 중요한 역할을 수행합니다.
Navigator
는 Route기능을 스택을 통하여 관리하며, 사용자가 새로운 페이지로 이동하거나 이전 페이지로 돌아갈 때 해당 Route들을 스택에 추가하거나 제거함으로써 앱 내의 화면 전환을 가능하게 합니다.
기본 동작
- Push: 새로운 Route(화면)을 Navigator 스택에 추가합니다. 이는 사용자가 새로운 화면으로 이동할 때 사용됩니다.
- Pop: 현재 Route를 스택에서 제거합니다. 이는 사용자가 이전 화면으로 돌아갈 때 사용됩니다.
동작 예시
1. 기본 페이지 이동:
사용자가 버튼을 클릭했을 때 새로운 페이지로 이동하는 기본적인 예시입니다.
ElevatedButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) { return const PageA(); }), ); }, child: const Text('Go to Page A'), ),
결과

2. Named Route를 이용한 라우팅:
Named Route를 사용하면 앱 내에서 미리 정의된 이름으로 화면을 이동할 수 있습니다.
이 방법은 경로 이름(path name)를 통해 route를 관리합니다.
다음과 같이 MaterialApp
위젯내에서 routes
속성을 통해 경로 이름과 연결할 위젯을 정의합니다.
return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), initialRoute: '/', routes: { '/': (context) => const MyHomePage(title: 'Start Project'), '/a': (context) => const PageA(), '/b': (context) => const PageB(), }, );
Navigator.pushNamed
method를 사용하여 화면을 이동합니다.
ElevatedButton( onPressed: () { // go to '/b' path Navigator.pushNamed(context, '/b'); }, child: const Text('Go to Page B'), ),
결과

3. 매개변수를 전달하기
다음과 같이 매개변수(argText
)를 route시 전달합니다.
ElevatedButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) { return const PageC(argText: "Route with argument"); }, ), ); }, child: const Text('Go to Page C'), ),
해당 Widget(PageC
)는 매개변수를 전달받아 생성자에서 사용합니다.
class PageC extends StatelessWidget { final String argText; const PageC({super.key, required this.argText}); @override Widget build(BuildContext context) { return Center( child: Text( '(Route with argument)\nPage C\n$argText', textAlign: TextAlign.center, style: const TextStyle(fontSize: 30), ), ); } }
결과

4. 결과 받기
다음과 같이 Navigator.pop
에 의해 리턴될 때, 반환 값을 전달 받을 수 있습니다.
ElevatedButton( onPressed: () async { final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => const PageD()), ); AlertDialog dlg = AlertDialog( title: const Text('Result'), content: Text('$result'), ); // ignore: use_build_context_synchronously showDialog( context: context, builder: (BuildContext context) => dlg, ); }, child: const Text('Go to Page D'), ),
PageD
가 Navigator.pop
시, 결과를 리턴합니다.
@override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ ElevatedButton( onPressed: () { Navigator.pop(context, 'Option A'); }, child: const Text('Option A'), ), ElevatedButton( onPressed: () { // Return the result and return the prior page. Navigator.pop(context, 'Option B'); }, child: const Text('Option B'), ) ], ), ); }
결과

Go_router 패키지 소개
기존의 Navigator
를 사용하는 방법도 있지만, 더 강력하고 직관적인 라우팅인 go_router
패키지를 필요에 따라 사용합니다.
이 패키지는 Flutter의 라우팅을 더욱 편리하게 만들어주며, 복잡성을 줄이는 데 크게 기여합니다.
자세한 정보는 go_router pub.dev 페이지에서 확인할 수 있습니다.
개요
go_router
는 Flutter 라우팅을 위한 선언적, 강력하며, 유연한 패키지입니다.
기존의 Navigator 방식 대비 적은 코드로 더 많은 기능을 수행할 수 있으며, URL을 통한 깊은 링크(deep link) 지원, 라우트 가드(route guards), 파라미터와 쿼리 처리 등 고급 라우팅 기능을 제공합니다.
Go_router 사용의 장점
- 선언적 라우팅:
go_router
는 선언적 API를 통해 라우트를 정의합니다.
이는 라우트 구조를 한눈에 파악하기 쉽게 만들어 줍니다. - 간결성: 복잡한 라우트 구조도 간결하게 표현할 수 있어 코드의 양을 크게 줄일 수 있습니다.
- 깊은 링크 지원: 외부 URL을 통해 앱 내 특정 페이지로 직접 이동하는 것을 지원합니다.
- 라우트 가드: 사용자 인증 상태 등에 따라 라우트 접근을 제어할 수 있는 기능을 제공합니다.
설치
$ flutter pub add go_router
사용하고자 하는 파일에 다음을 import
합니다.
import 'package:go_router/go_router.dart';
예제
이 코드는 기본 홈 화면과 ID에 따라 세부 정보를 표시하는 화면을 가지는 간단한 라우터 설정 예시입니다.
기본 routing
GoRouter
와 GoRoute
를 통해 Routing Path를 정의합니다.
final _router = GoRouter(initialLocation: '/', routes: [ GoRoute( path: '/', builder: (context, state) => const MyHomePage(title: 'Start Project')), GoRoute(path: '/e', builder: (context, state) => const PageE()), ]); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp.router( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), routerConfig: _router, ); } }
그리고 이동하고자 하는 곳에서 다음과 같이 절대경로를 이용해 이동할 수 있습니다.
주의해야 할 점은 context.go()
경우 기본적으로 context.push()
와 달리 뒤로 갈 경우, 이전 페이지로 이동하지 않습니다.
ElevatedButton( onPressed: () => context.go('/e'), child: const Text('Go to Page E'), ),
매개변수를 포함한 routing
다음과 같이 route 시, 매개변수를 전달할 수 있습니다.
아래의 경우 /f/:argText
를 통해 전달된 매개변수를 PageF
생성시 전달합니다.
final _router = GoRouter(initialLocation: '/', routes: [ GoRoute( path: '/', builder: (context, state) => const MyHomePage(title: 'Start Project')), GoRoute(path: '/e', builder: (context, state) => const PageE()), GoRoute( path: '/f/:argText', builder: (context, state) => PageF(argText: state.pathParameters['argText']!), ), ]);
이때 , context.go 시, 다음과 같이 매개변수(123
)을 전달할 수 있습니다.
ElevatedButton( onPressed: () => context.go('/f/123'), child: const Text('Go to Page F'), ),