현 프로젝트 시작단계

11. 로그인상태 유지 ,세션유지

깡 딱 2025. 3. 19. 00:43
728x90

이거는 전에 해봤던 경험이 있어서 생각보다 얼마 안걸렸다.

 

내가 현재 원하는건

 

✅ 앱 실행 → 세션이 있으면 HomeMain, 없으면 login_total_screen
✅ 로그인 성공 → 세션을 저장 후 HomeMain으로 이동
✅ 로그아웃 → 세션 삭제 후 로그인 화면으로 이동

 

근데 여기서 하단바가 있다면 하단바가 있는 화면에서 세션을 줘야 오류가 생기지않는다. 참고하길

 

 

 

메인화면에서 화면을 전달할떄 

home: AuthWrapper(), // 동적 초기 화면 설정

이코드로 전달되게한다.

 

 

로그인후 로그인화면을 스택에서 제거한이유는

만약 로그아웃을 했을때 로그인 화면에 뒤로가기가 있다면 뒤로가기를 누르면 홈화면으로 다시 들어가지게 되는 

문제가 발생한다.

방지하기 위해서 넣은것이다.

로그인후 로그인화면을 제거하고 홈화면으로 이동한다.

 

로그아웃 버튼 클릭시 스택제거 

onPressed: () async {
  Navigator.of(context).pop(); // 팝업 닫기

  // 로그아웃 실행 후 완료될 때까지 기다림
  await Provider.of<AuthService>(context, listen: false).signOut();

  // 로그아웃 완료 후 로그인 화면으로 이동 (이전 스택 제거)
  if (!mounted) return; // 위젯이 이미 dispose된 경우 실행 방지
  Navigator.pushAndRemoveUntil(
    context,
    MaterialPageRoute(builder: (context) => login_total_screen()),
        (Route<dynamic> route) => false, // 모든 이전 화면 제거
  );
},

 

 

홈화면에 들어갈때 

// 인증 상태에 따라 화면 분기
class AuthWrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final authViewModel = Provider.of<AuthViewModel>(context, listen: false);

    return FutureBuilder<bool>(
      future: authViewModel.checkSession(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Scaffold(body: Center(child: CircularProgressIndicator()));
        }
        if (snapshot.hasData && snapshot.data == true) {
          // 로그인 후 로그인 화면을 제거하고 홈 화면으로 이동
          WidgetsBinding.instance.addPostFrameCallback((_) {
            Navigator.pushAndRemoveUntil(
              context,
              MaterialPageRoute(builder: (context) => HomeScreen()),
                  (Route<dynamic> route) => false, // 모든 이전 화면 제거
            );
          });
          return SizedBox(); // 화면 깜빡임 방지용 빈 위젯
        }
        return login_total_screen(); // 세션이 없으면 로그인 화면
      },
    );
  }
}

 

 

 

여기서 두번째 문제점 

홈화면으로 갔을때 뒤로가기를 누르면 세션이 유지된 상태라도 라우터로 설정 해놓지 않았다면 

로그인 화면으로 간다. 그렇기 때문에

 

 

뒤로가기를 막아준다. 그러면 세션유지가 잘된다.

return WillPopScope(
  onWillPop: () async {
    // 뒤로 가기를 막고 앱을 종료
    return false; // 뒤로 가기 방지
  },

 

 

 

 

백엔드 코드

 

 

앱시작시 세션복원과 사용자를 확인한다.

그래야 로그인화면으로 가지 않고 홈화면부터 뜨니까 

// 앱 시작 시 세션 복원 및 사용자 상태 확인
Future<bool> checkSession() async {
  try {
    final session = Supabase.instance.client.auth.currentSession;
    if (session != null) {
      _currentUser = Supabase.instance.client.auth.currentUser;
      notifyListeners();
      return true; // 세션이 유효함
    }
    return false; // 세션이 없음
  } catch (error) {
    print('Error checking session: $error');
    return false;
  }
}

 

 

로그인 시에는

로그인 성공시 사용자 정보를 저장한다. 그렇지 않으면 세션유지가 안되기 때문에 

Future<String?> signIn(String email, String password) async {
  _isLoading = true;
  _errorMessage = null;
  notifyListeners();

  try {
    final user = await _supabaseService.signInWithEmailAndPassword(
      email: email,
      password: password,
    );

    _isLoading = false;
    if (user == null) {
      _errorMessage = '로그인 실패: 사용자 정보를 확인할 수 없습니다.';
      notifyListeners();
      return _errorMessage;
    }
    _currentUser = user; // 로그인 성공 시 사용자 정보 저장
    notifyListeners();
    return null; // 로그인 성공
  } catch (error) {
    _isLoading = false;
    _errorMessage = error.toString().replaceFirst('Exception: ', '');
    notifyListeners();
    return _errorMessage;
  }
}

 

로그아웃 시

 

로그아웃을할때 세션이 없어져야된다

// 로그아웃 메서드 추가 (필요 시)
Future<void> signOut() async {
  await Supabase.instance.client.auth.signOut();
  _currentUser = null;
  notifyListeners();
}

 

 

 

 

728x90