Medium의 Learning Flutter’s new navigation and routing system이라는 글을 일부 번역하여 정리한 글입니다. 상세한 구현 로직 및 사용방법은 원문 글에 자세히 나와있습니다. Navigator 2.0은 플러터 서비스가 브라우저 환경에서 제공될 때(?) 필요한 API가 아닐까 생각됩니다.
✓Navigator 2.0이라는 새로운 API는 기존 시스템을 파괴하며 대체되는 것이 아니라 단순히 새로운 선언형(declarative) API가 추가된 것이다.
Navigator 2.0이 도입되기 이전에는 1-1)다중 페이지를 방문하거나 혹은 1-2)다중 페이지의 방문 이력을 제거하거나 또는 2)현재 페이지 바로 이전 이력을 제거하는 것이 어려웠다.
*하지만, 만약 기존의 동작하는 방식에 만족한다면 명령적(imperative)방식을 그대로 사용해도 괜찮다.
✓선언형 프로그래밍은 무엇을 어떻게(how) 할 것인가에 관심이 있고 명령형 프로그래밍은 무엇을(what)을 할 것인가에 조금 더 집중한다. 그렇지만 조금 더 살펴보면 선언형 프로그래밍을 하기위해서는 어떻게를 수행하기 위한 여러 동작들이 추상화되어 있어야 한다는걸 알 수 있다.
네비게이터(Navigator)
: 라우트 객체의 스택(stack)을 관리하는 위젯
라우트(Route)
: 네비게이터를 통해 관리되는 객체로 일반적으로 MaterialPageRoute와 같은 클래스에서 구현된다. 익명 라우트(Anonymous route)와 기명 라우트(Named route)로 구분된다.
Navigator 2.0 이전에 라우트는 네비게이터의 스택 위에서 화면이 띄워지거나(pushed) 제거(popped)되었다.
대부분의 모바일 앱은 스택(stack)처럼 서로를 겹쳐서 화면을 띄운다. Navigator.of()를 사용해서 내비게이터에 접근하거나, 새로운 화면을 띄우거나 이전 화면으로 되돌아 갈 수 있다.
Navigator.push()
: 새로운 화면을 띄울 때 사용한다.
Navigator.pop()
: 이전 화면으로 되돌아 갈 때 사용한다.
플러터는 익명 라우트 뿐만 아니라 기명 라우트 방식도 제공한다. 이 방식은 route 객체와 path가 반드시 사전에 정의되어 있어야 한다. 이 방식을 사용하면 arguments를 전달할 수 있지만 대신 라우트 스스로가 arguments를 해석할 수는 없다.
web에서 실행되는 서비스에서 /details/:id 형태의 route를 사용할 때 id를 스스로 parse 할 수 없다. 별도로 id를 추출해서 넘겨줘야 한다.
onGenerateRoute: (settings) {
// Handle '/'
if (settings.name == '/') {
return MaterialPageRoute(builder: (context) => HomeScreen());
}
// Handle '/details/:id'
var uri = Uri.parse(settings.name);
if (uri.pathSegments.length == 2 &&
uri.pathSegments.first == 'details') {
var id = uri.pathSegments[1];
return MaterialPageRoute(builder: (context) => DetailScreen(id: id));
}
return MaterialPageRoute(builder: (context) => UnknownScreen());
},
Navagator 2.0 API는 앱의 화면들을 앱 상태 함수로 만들고 web URLs와 같은 기본 플랫폼에서 라우트를 해석할 수 있는 기능을 제공하기 위해서 새로운 클래스를 추가했다.
네비게이터의 history stack을 설정할 때 사용하는 불변 객체
객체를 구분할 수 있는 ValueKey를 할당
하면 Navigator가 각각의 MaterialPage가 다른 페이지임을 인식
할 수 있다.빌드할 페이지별로 커스텀된
애니메이션 효과를 적용
하거나 다른 효과를 적용하고 싶을 경우에는 Page 클래스를 상속
받아 그 안에서 구현할 수 있다.onPopPage
: Navigator가 갖는 프로퍼티 속성 중 하나로 Navigator.pop()이 실행될 때, 실행되는 콜백함수가 정의되는 위치로 앱 상태를 업데이트할 때 사용된다. 앱 상태를 업데이트할 때는 didPop 메서드를 사용하여 pop 동작이 정상적으로 이뤄졌는지 확인한 뒤 앱 상태를 업데이트 해야한다.네비게이터에 의해 나타나는 페이지 목록을 구성한다. 페이지는 서비스가 실행되는 플랫폼 환경이나 앱 변경 상태에 따라 변경된다. 다만, 앱이 아닌 브라우저 환경에서 사용자가 URL을 직접 변경하는 경우에는 사용자 정보를 직접 해석할 수 없기 때문에 이를 해석하고 동기화하는 작업이 필요하다.
RouteInformationParser
: RouteInformationProvider로 부터 라우트 정보를 가져와 유저가 정의한 데이터 타입을 해석할 때 사용한다.
RouterDelegate
: 앱 내에서의 변화를 라우터가 어떻게 학습하고 어떻게 응답하는지에 대한 앱 별 동작을 정의한다. 또한, RouteInformationParser와 앱 상태를 감지하고 현재 페이지의 네비게이터를 빌드한다.
BackButtonDispatcher
: 백 버튼을 눌렀을 때 라우터에게 해당 동작을 보고한다.