Friday, July 14, 2023

Flutter Navigator 2.0 이해하기

Flutter Navigator 2.0에 대해서 이해하기

Navigator 2.0은 Flutter에서 애플리케이션의 페이지 전환 및 상태 관리를 위해 제공하는 새로운 API입니다. 기존의 Navigator API가 문서 기반의 경로를 이용해 애플리케이션을 탐색했다면, Navigator 2.0은 선언적 프레임워크를 이용해 더욱 명확하고 관리하기 쉬운 네비게이션 경험을 제공합니다.

Navigator 2.0의 주요 향상된 점은 다음과 같습니다:

  • 복잡한 탐색 시나리오를 다루기에 적합한 선언적 프레임워크
  • 어댑터와 서로 다른 페이지에 대한 동적 매핑 기능
  • 웹과 모바일의 라우팅 방식 조정
  • 새롭게 도입된 MaterialApp.router 및 Router 위젯

Navigator 2.0과 기존 Navigator의 비교

기존의 Navigator는 상태 기반으로 페이지 네비게이션을 제공했습니다. 반면, Navigator 2.0은 선언적 프레임워크를 이용해 페이지 경로를 지정하고, 애플리케이션의 상태 관리에 더욱 직접적인 영향을 미칩니다. 이로 인해 웹과 같은 라우팅 기법에 더욱 친숙하게 동작하게 됩니다.

Navigator.push()와 Navigator.pop() 예시는 다음과 같습니다:

Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const DetailScreen()),
);

Navigator.pop(context);

Navigator 2.0에서는 새로운 RouterMaterialApp.router 위젯을 사용할 수 있습니다. 예시는 아래와 같습니다:

MaterialApp.router(
    routerDelegate: _routerDelegate,
    routeInformationParser: _routeInformationParser,
);

다음 부분에서는 Navigator 2.0의 기본 구조와 사용 방법에 대해 더 자세히 알아보겠습니다.

Navigator 2.0의 구조와 이해

Navigator 2.0의 구조 및 구성 요소를 이해하기 위해 아래의 핵심 구성 요소들을 살펴봅시다:

  • Router와 RouteInformationParser

    Router는 애플리케이션의 탐색 상태를 유지 관리하고 상태 변경에 따라 알림을 전달하는 역할을 담당합니다. RouteInformationParser는 URL과 탐색 상태를 서로 변환하는데 사용되는 추상 클래스입니다. 이를 통해 애플리케이션의 URL을 파싱하여 상태로 변환하거나 상태를 URL로 변환하는 작업을 수행합니다.

  • RouterDelegate

    RouterDelegate는 MaterialApp.router 위젯 내에서 사용되며, 네비게이션 로직을 구성합니다. RouterDelegate는 상태 변화를 받아 새로운 페이지를 스택에 쌓거나 기존 페이지를 제거하는 역할을 담당하며, 페이지 변경에 따라 적절한 UI를 마련하는 역할을 합니다.

  • Page

    Page는 불변성의 라우팅 설정 클래스로써, 현재 애플리케이션 상태에 따라 선언됩니다. MaterialApp.router에 제공된 라우팅 정보를 기반으로 동작하며, Route를 생성하는 빌더 역할을 합니다.

  • Builder Delegates를 통한 Page 생성

    Navigator 2.0에서는 Builder Delegates를 사용하여 페이지 스택을 관리합니다. 이 빌더는 리스트를 사용하여 페이지의 계층 구조를 정의하고, 상태에 따른 페이지 구조를 적용하여 렌더링합니다. 이를 통해 동적 레이아웃 변경을 처리할 수 있습니다.

Navigator 2.0을 개발에 적용하기

Navigator 2.0의 기본 구조를 개발에 적용하기 위해서는 MaterialApp 클래스를 MaterialApp.router로 대체하고 RouterDelegate와 RouteInformationParser를 함께 사용해야 합니다. 다음 예시를 참고해보세요:

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: MyRouterDelegate(),
      routeInformationParser: MyRouteInformationParser(),
    );
  }
}

위 코드에서 MyRouterDelegate와 MyRouteInformationParser 클래스는 사용자가 직접 구현해야 합니다.

이로써 Navigator 2.0의 기본 구조를 소개하였습니다. 다음 장에서는 Navigator 2.0에서 Page와 Router를 사용하는 방법에 대해 더 자세히 알아보겠습니다.

Navigator 2.0에서 Page 및 Router의 활용

이번 장에서는 Navigator 2.0에서 Page와 Router를 사용하는 방법을 알아보겠습니다.

1. Page 생성

먼저, 애플리케이션의 가능한 경로의 경우에 대해 Page 클래스를 생성해줍니다. Flutter에서는 기본적으로 MaterialPage와 CupertinoPage를 제공해 주지만, 사용자가 원하는 경우 Custom Page 클래스를 생성하여 사용할 수도 있습니다. 다음은 MaterialPage 예시입니다.

MaterialPage(
  key: const ValueKey('homePage'),
  child: const HomePage(),
)

2. RouterDelegate의 구현

RouterDelegate를 정의하여 애플리케이션의 직접적인 탐색 로직을 구현합니다. 추상 클래스인 RouterDelegate를 구현하고, 필요한 메서드를 오버라이드하여 사용합니다.

class MyRouterDelegate extends RouterDelegate<RoutePath>
    with ChangeNotifier, PopNavigatorRouterDelegateMixin<RoutePath> {
  final GlobalKey<NavigatorState> _navigatorKey;
  MyRouterDelegate() : _navigatorKey = GlobalKey<NavigatorState>();

  @override
  GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;

  // ... 더 많은 메서드 오버라이드
}

3. RouteInformationParser의 구현

RouteInformationParser를 구현하여 Route 정보를 애플리케이션의 상태로 변환하고, 상태를 Route 정보로 역변환하는 기능을 추가합니다.

class MyRouteInformationParser extends RouteInformationParser<RoutePath> {
  @override
  Future<RoutePath> parseRouteInformation(
      RouteInformation routeInformation) async {
    // 로직 구현...
  }

  @override
  RouteInformation restoreRouteInformation(RoutePath path) {
    // 로직 구현...
  }
}

4. 애플리케이션 구조 적용

Navigator 2.0을 사용한 애플리케이션의 기본 구조를 적용하기 위해 아래의 예시를 참고합니다.

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: MyRouterDelegate(),
      routeInformationParser: MyRouteInformationParser(),
    );
  }
}

이로써 Navigator 2.0에서 Page 및 Router 사용법을 소개하였습니다. 다음 장에서는 Navigator 2.0에서 새로운 경로를 추가 및 처리하는 방법에 대해 알아보겠습니다.

Navigator 2.0에서 새로운 경로의 추가 및 처리

Navigator 2.0에서 새로운 페이지의 경로를 등록하고 처리하는 방법을 알아봅시다. 이는 사용자가 앱 내에서 어떤 상태를 선택할 때, 로직을 처리하도록하기 위한 방법입니다.

새로운 경로의 추가

Navigator 2.0에서 새로운 경로를 등록하려면, RouterDelegate의 상태 안에 경로를 정의하고 관리해야 합니다. 아래 예제에서는 간단한 페이지 계층 구조를 표현하는 BookRouteDelegate 클래스를 생성합니다.

class BookRouteDelegate extends RouterDelegate<BookRoutePath>
    with ChangeNotifier, PopNavigatorRouterDelegateMixin<BookRoutePath> {
  @override
  final GlobalKey<NavigatorState> navigatorKey;

  BookRoutePath get currentPath => _selectedPath;
  set currentPath(BookRoutePath path) {
    _selectedPath = path;
    notifyListeners();
  }

  BookRoutePath _selectedPath;

  BookRouteDelegate() : navigatorKey = GlobalKey<NavigatorState>();
  
  ...
}

이 클래스는 애플리케이션의 상태에 따라 다양한 페이지를 만들 수 있습니다. 예를 들면 다음과 같이 정의할 수 있습니다.

List<Page> buildPages() {
  List<Page> pages = <Page>[];

  if (_selectedPath.isListPage) {
    pages.add(
      MaterialPageRoute(
        settings: RouteSettings(name: '/'),
        builder: (context) => BookListScreen(onBookClicked: _handleBookClicked),
      ),
    );
  } else if (_selectedPath.isDetailsPage) {
    pages.add(
      MaterialPageRoute(
        settings: RouteSettings(name: '/details'),
        builder: (context) => BookDetailsScreen(
          book: _books.firstWhere((b) => b.id == _selectedPath.id),
        ),
      ),
    );
  }

  return pages;
}

새로운 경로를 추가하는 것은 간단하게 리스트 안에 원하는 경로를 추가하면 됩니다. 그리고 RouterDelegate의 build 메서드를 사용하여 페이지를 구성하십시오.

경로의 처리

Navigator 2.0에서 새로운 경로를 처리하려면, RouterDelegate의 상태에 적절한 로직을 구현해야 합니다. 예를 들어, 아래처럼 버튼 클릭 이벤트를 처리하는 메서드를 구현할 수 있습니다.

void _handleBookClicked(Book book) {
  currentPath = BookRoutePath.details(book.id);
}

void _handleGoToList() {
  currentPath = BookRoutePath.list();
}

이런식으로 애플리케이션의 상태에 따라 경로를 관리하고 동적으로 처리할 수 있습니다.

이로써 새로운 경로 추가와 처리를 설명하였습니다. 다음 장에서는 Navigator 2.0 사용 시 주의 사항 및 결론을 다루겠습니다.

Navigator 2.0 사용 시 주의 사항 및 결론

Navigator 2.0을 사용하여 애플리케이션의 네비게이션을 구현할 때, 다음과 같은 주의 사항들을 기억해야 합니다.

주의 사항

  • 백그라운드 애니메이션과 이전 페이지 삭제

    사용자가 뒤로 가기 버튼을 누르거나 명시적으로 이전 페이지로 돌아가는 경우, 기본 동작은 애니메이션과 함께 현재 페이지를 스택에서 삭제하는 것입니다. Navigator 2.0에서는 Pages API를 사용하여 스택에 원하는 패턴을 정의할 수 있으므로 이러한 동작을 원하지 않는 경우 이를 처리해야 합니다.

  • 컴파일 오류 없는 코드 작성

    코드 예시를 제공할 때 컴파일 오류가 발생하지 않도록 철저하게 확인하세요. 컴파일 오류가 있는 코드는 앱 개발에 도움이 되지 않고 제대로 작동하지 않습니다.

  • 접근성 관련 기능 고려

    앱의 접근성 및 이용성을 높이기 위해 HTML 태그를 사용해 다양한 접근성 도구를 지원하는 것이 중요합니다. 디자이너들은 코드 상으로 항상 SEO 태그를 고려해 작성해야 합니다.

  • 코드 최적화

    코드 최적화는 앱의 성능을 향상시키는 중요한 요소입니다. 불필요한 중복 코드를 제거하고, 메모리 사용을 최소화하며, 반복적인 연산은 가능한 한 적게 수행하도록 코드를 작성해야 합니다.

  • 테스트

    앱의 기능이 예상대로 작동하는지 확인하려면 충분한 테스트가 필요합니다. Flutter에서는 Widget 테스트, 유닛 테스트, 통합 테스트 등 다양한 테스트 방법을 제공하므로 이를 활용하면 좋습니다.

결론

Navigator 2.0은 Flutter에서 애플리케이션의 네비게이션을 관리하는 데 매우 강력한 도구입니다. 기존 Navigator 1.0에서 제공하지 않았던 세밀한 컨트롤과 유연성을 제공하며, 특히 웹과 데스크톱 플랫폼에서의 사용을 목표로 설계되었습니다.

그러나 Navigator 2.0의 API는 복잡하고 이해하기 어렵다는 주요한 단점이 있습니다. 따라서 애플리케이션의 복잡성에 따라 적절한 네비게이션 방법을 선택하는 것이 중요합니다. 간단한 애플리케이션의 경우 Navigator 1.0이나 간단한 라우팅 패키지를 사용하는 것이 더 효과적일 수 있습니다.

이 글을 통해 Navigator 2.0의 기본적인 사용 방법과 주의 사항을 알아보았습니다. 이를 바탕으로 Flutter에서 강력한 네비게이션 시스템을 구축할 수 있기를 바랍니다.

참고 자료

참고 자료를 통해 Navigator 2.0에 대한 더 깊이 있는 이해를 얻을 수 있습니다. Flutter 개발에 성공을 바랍니다!


0 개의 댓글:

Post a Comment