- Flutter 팀에서 공식적으로 지원하는 선언형 라우팅 (
Declarative Routing) 패키지이다.- Flutter의
Navigator 2.0의 복잡한 구조를 단순화하고 직관적인 URL 기반 탐색 API를 제공하여 화면 간 이동 및 라우팅 관리를 쉽고 깔끔하게 해준다.
선언적 라우팅
- 앱의 모든 라우트를 한 곳에서 URL 패턴 기반으로 명확하게 정의할 수 있다.
- 라우트 (경로)와 화면을GoRoute객체 리스트로 관리한다.
간결한 네비게이션 메서드context.go('/path') // 새 스택으로 이동 (기존 스택 초기화) context.push('/path') // 현재 스택 위에 새로운 화면 추가 context.pop() // 이전 화면으로 돌아가기
URL 기반 라우팅
- 앱의 URL 또는 모바일 앱의 딥링크를 자연스럽게 처리하도록 설계됐다.
- 특정 화면으로 직접 접근 가능하다.
매개변수 전달 (Parameters & Query)
- 경로 매개변수 ::id형식으로 선언하고state.parhParameters['id']로 접근한다.GoRoute( path:'/friends/:userId/home', // ex) /friends/abc123/home name: RouteNames.friendHome, builder: (context, state) { // URL 경로에서 직접 추출 & !를 사용해 userId가 null이 아님을 단언 final userId = state.pathParameters['userId']! return HomePage( key: valueKey(userId), visitingUserId: userId, // userId가 변경될 때마다 위젯을 새로 생성
- 사용자가
/friends/alice123/home접속go_router가alice123을:userId에서 추출HomePage에visitingUserId: alice123로 전달HomePage내부에서 이 ID로 앨리스의 데이터 조회 및 표시- 같은
HomePage위젯이지만 누구의 페이지를 보여줄지visitingUserId로 구분한다.
- 쿼리 매개변수:
?key=value형식으로state.uri.queryParameters['key']로 접근한다GoRoute( path: RoutePaths.home, name: RouteNames.home, // builder 대신 사용, 커스텀 페이지 전환 제어 pageBuilder: (context, state) { final visitingUserId = state.uri.queryParameters['visitingUserId'] return NoTransitionPage( // 페이지 전환 애니메이션 없이 즉시 표시 child: MainShellPage( // 추가 레이아웃 래퍼 child: HomePage(visitingUserId : visitingUserId), ),);},
main.dart 적용MaterialApp.router( routerConfig: _router, );
하위 라우트(routes 속성)
-GoRoute안에서 또 다른GoRoute를 정의할 수 있어 계층적 네비게이션이 가능하다.
ShellRoute
- 탭 바, 드로어 등 공통 UI가 유지되는 상태에서 내부 화면만 전환되는 구조를 지원한다.
- Flutter의
Navigator 2.0의 복잡한 구조를 단순화하고 직관적인 URL 기반 탐색 API를 제공하여 화면 간 이동 및 라우팅 관리를 쉽고 깔끔하게 해준다.redirect: (context, state) async { // 현재 어디로 가려는지 확인 // Splash 화면으로 가는 건 항상 허용 final location = state.matchedLocation; if(location == RoutePaths.Splash) { return null; // 리다이렉트 하지 않음 (원래 가려던 곳으로 감) } // 로그인 상태 확인: 사용자가 로그인 했는지 안 했는지 체크 final container = ProviderContainer(); // 로그인 관련 정보를 관리하는 곳 final autoRepository = container.read(autoRepositoryProvider); final isSignedIn = autoRepository.isSignedIn; if(isSignedIn) { // 로그인 되어 있는 경우 final userExists = await autoRepository.checkUserDataExists(); if(!userExists) { // 로그인 되어있지만 사용자 데이터가 없음 final isDeactivated = await autoRepository.checkDeactivatedAccount(); // 탈퇴한 계정인지 확인 if(isDeactivated) { // 탈퇴한 계정이면 await autoRepository.restoreAccount(); // 자동복구 시도 }} // 온보딩 완료 체크 final onboardingComplete = await autoRepository.checkOnboardingComplete(); if(!onboardingComplete) { // 로그인 했지만 아직 닉네임 설정 안함 if(location != RoutePaths.onboardingNickname) { // 어디 가려고 해도 return RoutePaths.onboardingNickname; // 무조건 닉네임 설정 화면으로 보냄 } return null; // 단, 이미 닉네임 설정 화면에 있으면 그대로 둠 } // 로그인 화면 접근 차단 if(location == RoutePaths.login || location == RoutePaths.onboardingNickname) { return RoutePaths.home; // 이미 로그인했는데 로그인 화면으로 가려고 하면 홈 화면으로 보냄 } // 로그인 안 되어 있는 경우 } else if(loacation != RoutePaths.login) { return RoutePaths.login; // 로그인 화면으로 강제 이동 } return null; }
- 등록되지 않은 경로로 접근했을 때는
errorBuilder를 통해 사용자 정의 오류 화면을 표시할 수 있다.// 앱에서 문제가 생겼을 때 보여줄 화면을 정하는 것 errorBuilder: (context, state) => ErrorPage(),
flutter pub add go_router