[Flutter] Flutter 라우팅, 복잡함을 덜어내는 방법 GoRouter

서연·2025년 10월 23일
post-thumbnail

📖 GoRouter

  • 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_routeralice123:userId에서 추출
  • HomePagevisitingUserId: 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,
);

🧱 중첩 라우트 & ShellRoute

하위 라우트(routes 속성)
- GoRoute 안에서 또 다른 GoRoute를 정의할 수 있어 계층적 네비게이션이 가능하다.


ShellRoute
- 탭 바, 드로어 등 공통 UI가 유지되는 상태에서 내부 화면만 전환되는 구조를 지원한다.


🔒 Redirect 기능 (인증 및 접근 제어)

  • 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

0개의 댓글