[Flutter] GoRouter의 RouterDelegate와 RouteInformationProvider를 사용한 현재 라우트 추적

2025. 4. 23. 17:26Programming/Flutter

반응형

Flutter의 GoRouter를 사용해서 라우트를 구현하던 중, 전체 페이지에 공용으로 출력해야하는 UI를 라우터에 따라 변경해야하는 일이 있었습니다. RouterDelegate.addListener()를 호출해서 이벤트 핸들러를 등록해서, 라우트가 변경될 때마다 ValueNotifier의 값을 변경하는 방식으로 UI를 업데이트하여 간단하게 해결... 된다고 생각했지만, RouterDelegate.currentConfiguration.uri를 참조해서 업데이트하도록 작성했더니, push()를 사용해서 페이지를 이동했을 때는 ValueNotifier가 정상적으로 업데이트되지 않았습니다.

한참을 고민하던 중 RouterDelegate.currentConfiguration.uri를 참조하는 대신, RouteInformationProvider.value.uri를 참조하도록 변경했더니 push()/pop()을 할 때도 정상적으로 동작하는 걸 확인할 수 있었죠. 그런고로 이번에는 RouterDelegate와 RouteInformationProvider가 어떤 역할을 하는지 정리해보려고 합니다.

GoRouter의 핵심 컴포넌트

RouterDelegate

RouterDelegate는 Flutter의 Navigator 2.0에서 도입된 핵심 컴포넌트로 구현 목적은 다음과 같습니다.

  1. 상태 관리

    • 전체 네비게이션 스택의 상태를 관리
    • 라우팅 상태를 앱의 상태로 취급
  2. 선언적 API 제공

    • 명령형 네비게이션(push, pop)을 선언적 방식으로 변환
    • 라우트 구성을 객체로 표현
  3. 딥링크 처리

    • 외부 URL을 앱 내부 상태로 변환
    • 앱의 상태를 URL로 변환

RouteInformationProvider

RouteInformationProvider는 현재 라우트 정보를 제공하는 컴포넌트로 구현 목적은 다음과 같습니다.

  1. 플랫폼 통합

    • 브라우저 URL 변경 감지
    • 시스템 백 버튼 처리
    • 딥링크 처리를 위한 플랫폼 수준의 통합
  2. 라우트 정보 추상화

    • 플랫폼 독립적인 라우트 정보 제공
    • URL 기반 라우팅을 위한 표준화된 인터페이스 제공

RouterDelegate vs RouteInformationProvider

RouterDelegate

final currentPath = router.routerDelegate.currentConfiguration.uri.toString();
  • 특징:

    • 네비게이션 스택의 전체 상태를 관리
    • 라우팅 로직을 처리하는 핵심 컴포넌트
    • 이전 라우트 정보를 참조할 수 있음
    • 상태 변경이 실제 네비게이션 완료 전에 발생할 수 있음
  • 단점:

    • currentConfiguration이 항상 최신 상태를 반영하지 않을 수 있음
    • push 작업 시 이전 경로를 참조하는 경우가 발생

RouteInformationProvider

final currentPath = router.routeInformationProvider.value.uri.toString();
  • 특징:

    • 현재 라우트의 정보만을 제공
    • 항상 스택의 최상단에 있는 페이지의 URI를 정확하게 반영
    • 실제 네비게이션이 완료된 후의 상태를 제공
    • URL 기반 라우팅에 더 적합
  • 장점:

    • 더 정확한 현재 경로 정보를 제공
    • 네비게이션 완료 후의 실제 상태를 반영

실제 사용 예시

// 권장되는 방식
router.routerDelegate.addListener(() {
  final currentPath = router.routeInformationProvider.value.uri.toString();
  if (notifier.value != currentPath) {
    notifier.value = currentPath;
  }
});

이 방식에서는:

  1. routerDelegate의 리스너를 통해 모든 네비게이션 이벤트(push, pop, replace)를 감지
  2. routeInformationProvider를 통해 정확한 현재 경로 정보를 획득

동작 방식

  1. 네비게이션 이벤트 발생 시:

    사용자 액션(push/pop/replace) 
    → RouterDelegate 상태 변경 
    → 네비게이션 수행 
    → RouteInformationProvider 업데이트
  2. 딥링크나 URL 변경 시:

    외부 URL/딥링크 
    → RouteInformationProvider 업데이트 
    → RouterDelegate가 해당 정보를 기반으로 네비게이션 수행

결론

라우트 변경을 감지할 때는 RouterDelegate의 리스너를 사용하고, 현재 경로 정보를 얻을 때는 RouteInformationProvider를 사용하는 것이 가장 안정적인 방법입니다. 이는 모든 네비게이션 이벤트를 놓치지 않으면서도 정확한 현재 경로 정보를 얻을 수 있게 해줍니다.

참조자료

  1. Flutter 공식 문서 - Navigator 2.0
  2. go_router 패키지 문서
  3. Flutter Navigator 2.0 공식 제안서
  4. Flutter RouterDelegate API 문서
  5. Flutter RouteInformationProvider API 문서
반응형