• 카테고리

    질문 & 답변
  • 세부 분야

    모바일 앱 개발

  • 해결 여부

    미해결

go router redirect 동작 질문

24.03.05 22:23 작성 조회수 173

0

안녕하세요 redirect 이용해서 구현하는 것에 질문이 있어요
예를 들면

1) 어떤 상세 페이지에서 컨텐츠 보고 있었음

2) 토큰만료 되서 로그인 페이지로 감

3) 재로그인하고 아까 상세 페이지로 복귀

또는

1) 로그아웃했음 (auth state 에 따라 redirect함)
2) 뒤로 가기가 있는 로그인 페이지로 이동
3) 뒤로가기 하고 싶으나 (context.pop할 페이지가 없다고 나옴)

이런 시나리오라 할 떄

 

go router 같은 경우 redirect 으로 로그인 페이지로 보내게 되면 context.pop할때 뒤로갈 페이지가 없다고 되는데 이런경우는 어떻게 다뤄야할까요?

당장 생각되는건 redirect 되는 페이지들이 context.go 처럼 작동되어서 context.push 같이 redirect 될 수 있도록 조절이 가능하면 좋을 것 같다는 생각이 드는데 방법이 있는지 궁금해요.

만약에 위 해결 방법이 없다면 수동적으로라도 redirect 을 사용 안하고 auth state 별로 라우팅을 명시해주는게 나을까요..?

아래는 구현한 코드 예제입니다

 

final goRouterProvider = Provider<GoRouter>((ref) {
  final authProvider = AuthNotifier(ref: ref);

  return GoRouter(
    navigatorKey: MyApp.navigatorKey,
    debugLogDiagnostics: false,
    initialLocation: RouterPathEnum.SPLASH.path,
    redirect: authProvider.redirectLogic,
    refreshListenable: authProvider,
    routes: [
      ...RouterPathEnum.values
          .map(
            (value) => transitionRoute(
              path: value.path,
              routerEnum: value,
              duration: const Duration(milliseconds: 500),
            ),
          )
          .toList(),
      ...goDynamicRouteList,

      /// -- Deep Link Page --
    ],
  );
}); 


class AuthNotifier extends ChangeNotifier {
  final Ref ref;

  AuthNotifier({required this.ref}) {
    //LoginPlatformEnum 상태 listen -> 상태가 변경되면 notifyListeners() 호출
    ref.listen<LoginPlatformEnum?>(
      authViewModelProvider,
      (previous, next) {
        if (previous != next) {
          notifyListeners();
        }
      },
    );
  }

  String? redirectLogic(_, GoRouterState state) {
    final authState = ref.read(authViewModelProvider);

    /// 로그인 여부
    final authenticated = authState;

    /// 로그인 하려는 경우
    final authenticating = (state.matchedLocation == RouterPathEnum.LOGIN.path) ||
        (state.matchedLocation == RouterPathEnum.SIGNUP.path) ||
        (state.matchedLocation == RouterPathEnum.PASSWORD_RESET.path);

    final isSplash = (state.matchedLocation == RouterPathEnum.SPLASH.path);

    log('authenticated.value: $authenticated authenticating: $authenticating');
    if (isSplash) return null;

    /**
     * authenticated - 로그인이 안된 경우 (LoginPlatformEnum.none)
     * 로그인을 시도하는 케이스 : 원하는 페이지로 이동
     * 그 외 케이스 : 로그인 페이지 이동
     */

    if (authenticated == LoginPlatformEnum.NONE) {
      return authenticating ? null : RouterPathEnum.LOGIN.path;
    }

    /**
     * authenticated - 로그인 성공한 경우
     * 로그인하려는 페이지 or splash -> total main 페이지로 이동
     * 그 외 케이스 : 원하는 페이지로 이동
     */
    return (authenticating) ? RouterPathEnum.TOTAL_MAIN.path : null;
  }
}

답변 1

답변을 작성해보세요.

0

안녕하세요!

말씀하신 기능은 웹에서도 흔히 사용하는 방법입니다.

상태를 계속 전달 해줘야하는데 방법은 많습니다.

가장 흔히 사용되는 방법은 로그인 페이지로 가기 전 redirect 위치를 query parameter로 전달해주는 방법입니다.

예를들면 /auth?redirect=/post/123

이런식으로 로그인 페이지로 보내고 로그인에 성공 했을때 redirect 쿼리에 있는 값을 파싱해서 보내주면 됩니다.

감사합니다!

답변 감사합니다!

제가 우선 이해한 내용을 말씀드려보자면

(1)
/main (메인페이지) , /detail (상세페이지) , / login(로그인 페이지)
이렇게 있다 가정하고 사용자가 /main -> / detail 페이지에 위치해 있을 때
go router 에서 redirect으로 auth state 가 로그아웃되어서 로그인 페이지로 가게 되면
기존에 있던 메인페이지, 상세페이지 route가 다 사라지게 되고 (로그인페이지에서 뒤로가기 하면 There is nothing to pop 상태)
(대신에 위에 말씀해주신 방법으로 /main / detail 경로처럼 redirect 보낼 경로를 저장하고 로그인페이지에 query parameter에 넘겨줘서 로그인 성공 시 context.go 로 다시 가게끔 하는게 맞을까요?)

(2) 위의 방법이 가능하다면 간단한 예제가 있을지 궁금해요!

(3) 또한 이 상태에서 로그인페이지의 뒤로가기 버튼은 눌러도 돌아갈 페이지가 없는데 아예 메인페이지로 보내는게 나을지 의견도 궁금해요.

(4) 이에 추가 질문도 있습니다!
제가 bottom navigation에 메인페이지, 마이페이지 이렇게 있다고 할때
아무래도 sub route들이 없는 단순히 go router 최상단에 1차적으로 등록되는 페이지들인데
예를 들어서 회원가입 페이지에서 회원가입 완료되었고 마이페이지로 바로 보내고 싶다. 다만 메인페이지가 스택으로 쌓인 상태로 보내고 싶다고 가정할 때

두 페이지 다 route 최상단에 위치해 있으니깐 마이페이지가 메인페이지의 sub route가 아님에도 불구하고 메인페이지 - 마이페이지 이렇게 스택쌓아서 마이페이지로 context.go 할 수 있는 방법이 있을까요?

질문이 다소 많고 이해하기 어려우신 점 있으시면 말씀해주시면 감사하겠습니다!   

/auth 페이지가 가장 아래의 스택이라면 더이상 pop 할게 없는게 당연합니다. 이 상태에서 올리고싶은 라우트가 있다면 매우 일반적인 방법으로 라우트들을 올려주시면 됩니다.

로그인 상태에서 뒤로가기를 눌렀을때 사람들이 예상하는 액션이 있을지를 모르겠습니다. 보통 로그인 페이지는 가장 첫 페이지로 인식하는게 맞기 때문에 뒤로가기 했을때 아무런 액션이 없어도 이상하게 생각하진 않을 것 같아요.

go router로 라우터 스택에 페이지를 쌓을 수 있는 방법은 제가 강의에서 모두 가르쳐드렸습니다. imperative하게 두개의 라우트를 쌓고 싶다면 두번 푸쉬를 해주면 되고 declarative하게 이동하고 싶다면 원하는 라우트를 네스팅해서 정의한 다음 go를 하시면 됩니다.