로그인으로 Android 조건부 탐색

이 Codelab은 Kotlin 기반 Android 고급 교육 과정의 일부입니다. Codelab을 순서대로 진행하는 경우 학습 효과를 극대화할 수 있지만 순서를 바꿔 진행해도 괜찮습니다. 모든 과정 Codelab은 Kotlin Codelab의 고급 Android Codelab 방문 페이지에 나열되어 있습니다.


이 Codelab에서는 FirebaseUI로 Android에 로그인 구현을 기반으로 합니다. 이전 Codelab을 완료하지 않았다면 이 Codelab의 시작 코드를 다운로드할 수 있지만 먼저 FirebaseUI로 Android에 로그인 구현 Codelab을 완료하는 것이 좋습니다.

소개

앱에서 로그인을 지원하는 경우 이는 로그인한 사용자에게만 앱의 일부를 예약하는 일반적인 사용 사례입니다. 예를 들어 로그인한 사용자의 앱에 대한 설정 화면을 예약할 수 있습니다.

이러한 경우 조건부 탐색을 사용하여 인증 상태에 따라 사용자를 적절한 화면으로 안내할 수 있습니다.

이 Codelab에서는 기존 앱 위에 빌드하여 사용자가 로그인한 경우에만 액세스할 수 있는 설정 화면을 추가합니다. 이 작업에 Android 탐색 구성요소를 사용합니다.

기본 요건

학습할 내용

  • 로그인 여부에 따라 사용자를 앱의 적절한 화면으로 이동하는 방법

실습할 내용

  • 사용자가 성공적으로 로그인한 후 올바른 화면으로 이동하는 것을 올바르게 처리합니다.
  • 사용자가 로그인하지 않은 경우 설정 화면에 액세스하지 못하도록 하고 대신 로그인 화면으로 리디렉션합니다.

이전 Codelab에서는 Android 사실을 표시하는 앱에서 작업했습니다. 또한 앱에서 사용자가 로그인하고 로그아웃할 수 있도록 허용했습니다. 이 Codelab에서는 기존 앱에 설정 화면을 추가합니다. 로그인한 상태의 사용자만 설정 화면에 액세스할 수 있습니다.

사용자가 로그인하지 않은 경우 설정 화면에 액세스하려고 시도하면 앱이 로그인 화면으로 리디렉션됩니다. 로그인 과정이 완료되면 사용자는 원래 액세스하려고 했던 설정 화면으로 돌아갑니다.

이 Codelab에서는 FirebaseUI로 Android에 로그인 구현을 기반으로 합니다. 이전 Codelab을 완료하지 않았다면 이 Codelab의 시작 코드를 다운로드할 수 있지만 먼저 FirebaseUI로 Android에 로그인 구현 Codelab을 완료하는 것이 좋습니다.

샘플 앱을 다운로드한 후 다음 중 하나를 수행합니다.

ZIP 파일 다운로드


... 또는 다음 명령어를 사용하여 명령줄에서 GitHub 저장소를 클론하고 저장소의 start 분기로 전환합니다.

$  git clone https://github.com/googlecodelabs/android-kotlin-login-navigation

Android 스튜디오에서 프로젝트를 로드했으면 다음 단계를 따르세요.

  1. 에뮬레이터 또는 실제 기기에서 앱을 실행하여 개발이 시작되도록 환경이 올바르게 설정되었는지 확인합니다.

성공하면 홈 화면에 재미있는 Android 사실과 왼쪽 상단의 로그인 버튼이 표시됩니다.


시작 앱의 현재 기능:

  • 사용자가 로그인하지 않은 경우 로그인 버튼을 탭하면 로그인 과정이 시작되고 이메일 주소나 Google 계정으로 로그인할 수 있습니다.
  • 사용자가 로그인하면 버튼이 로그아웃 버튼으로 변경되어 사용자가 로그아웃할 수 있습니다.

이 작업에서는 사용자가 설정 화면으로 이동할 수 있는 버튼을 홈 화면에 추가합니다. 설정 화면에서 사용자는 홈 화면에 어떤 종류의 재미있는 사실을 표시할지 선택할 수 있습니다. 설정 화면에서 Android 관련 사실 또는 캘리포니아주의 사실 정보를 확인할 수 있습니다.

  1. fragment_main.xml를 엽니다.
  2. fragment_main.xml,에서 ConstraintLayout에 중첩된 설정 버튼을 추가하고 화면 오른쪽 상단에 배치합니다.

fragment_main.xml

<TextView
       android:id="@+id/settings_btn"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_margin="@dimen/text_margin"
       android:background="@color/colorAccent"
       android:padding="10dp"
       android:text="@string/settings_btn"
       android:textColor="#ffffff"
       android:textSize="20sp"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintTop_toTopOf="parent"/>
  1. nav_graph.xml를 엽니다.
  2. mainFragment 내에서 작업을 추가합니다. 작업의 idaction_mainFragment_to_customizeFragment이고 대상은 customizeFragment입니다.

nav_graph.xml

<fragment
       android:id="@+id/mainFragment"
       android:name="com.example.android.firebaseui_login_sample.MainFragment"
       android:label="MainFragment">
   <action
           android:id="@+id/action_mainFragment_to_settingsFragment"
           app:destination="@id/settingsFragment"/>
</fragment>
  1. MainFragment.kt를 엽니다.
  2. onViewCreated()에서 버튼을 탭하면 사용자가 customizeFragment로 이동하도록 settings_btnonClickListener를 설정합니다.

MainFragment.kt

binding.settingsBtn.setOnClickListener {
   val action = MainFragmentDirections.actionMainFragmentToSettingsFragment()
   findNavController().navigate(action)
}
  1. 해결되지 않은 오류가 표시되면 빌드 메뉴에서 앱을 다시 컴파일하여 생성한 새 탐색 작업을 생성하고 사용합니다.
  2. 앱을 다시 실행합니다. 이제 오른쪽 상단에 제대로 작동하는 설정 버튼이 표시됩니다.
  3. 버튼을 클릭하면 설정 화면으로 이동합니다. 설정 화면에는 하나의 옵션만 표시되므로 사용자가 홈 화면에 표시하려는 재미있는 사실의 유형을 선택할 수 있습니다.
  4. Android 기기의 뒤로 버튼을 클릭하여 홈 화면으로 돌아갑니다.

이 작업에서는 사용자가 로그인 전 설정 화면에 액세스하려고 할 때 사용자를 로그인 화면으로 이동하는 코드를 추가합니다.

  1. SettingsFragment.kt를 엽니다.
  2. onViewCreated()에서 authenticationState를 관찰하고 인증되지 않으면 사용자를 LoginFragment로 리디렉션합니다.

SettingsFragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   super.onViewCreated(view, savedInstanceState)
   val navController = findNavController()
   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
       when (authenticationState) {
           LoginViewModel.AuthenticationState.AUTHENTICATED -> Log.i(TAG, "Authenticated")
           // If the user is not logged in, they should not be able to set any preferences,
           // so navigate them to the login fragment
           LoginViewModel.AuthenticationState.UNAUTHENTICATED -> navController.navigate(
               R.id.loginFragment
           )
           else -> Log.e(
               TAG, "New $authenticationState state that doesn't require any UI change"
           )
       }
   })
}

앱은 설정 화면에 액세스하려고 할 때 사용자를 로그인 화면으로 이동시키므로 로그인 화면에서 뒤로 버튼 동작도 처리해야 합니다. 앱이 뒤로 버튼 동작 처리를 맞춤설정하지 않으면 사용자가 설정 화면으로 돌아가려고 하는 무한한 루프에 빠지다가 다시 로그인 화면으로 리디렉션됩니다.

  1. LoginFragment.kt를 엽니다.
  2. onViewCreated()에서 사용자를 MainFragment로 다시 돌아와 뒤로 버튼 작업을 처리합니다.

LoginFragment.kt

// If the user presses the back button, bring them back to the home screen
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
   navController.popBackStack(R.id.mainFragment, false)
}
  1. 앱을 다시 실행하고 로그인하지 않은 경우 설정 화면에 액세스하려고 시도하면 로그인 절차로 리디렉션됩니다.

사용자가 성공적으로 로그인하도록 했지만 사용자가 정상적으로 로그인한 후에 발생하는 상황을 처리하지 못했기 때문에 로그인 시도가 실패한 것처럼 표시됩니다. 이 문제는 다음 단계에서 해결합니다.

지금까지 사용자가 로그인하지 않고 설정 화면에 액세스하려고 하면 사용자를 로그인 화면으로 리디렉션하도록 앱을 설정했습니다.

하지만 로그인 과정을 거치면 다시 로그인 화면으로 돌아갑니다. 이는 만족스러운 사용자 경험이 아니며 혼란을 일으킬 수 있습니다.

이상적인 사용자 환경을 제공하려면 앱에서 사용자가 정상적으로 로그인한 후 설정 화면으로 돌아가야 합니다.

  1. LoginFragment.ktonViewCreated()에서 authenticationState를 관찰하고 성공적으로 인증되면 사용자를 SettingsFragment로 다시 이동합니다.

LoginFragment.kt

// Observe the authentication state so we can know if the user has logged in successfully.
// If the user has logged in successfully, bring them back to the settings screen.
// If the user did not log in successfully, display an error message.
viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
   when (authenticationState) {
      // Since our login flow is only one screen instead of multiple 
      // screens, we can utilize popBackStack(). If our login flow 
      // consisted of multiple screens, we would have to call 
      // popBackStack() multiple times.
       LoginViewModel.AuthenticationState.AUTHENTICATED -> navController.popBackStack()
       else -> Log.e(
           TAG,
           "Authentication state that doesn't require any UI change $authenticationState"
       )
   }
})
  1. 앱을 다시 실행하고 이제 성공적으로 로그인하면 Login(로그인) 페이지 대신 Settings(설정) 페이지로 이동합니다.

이 솔루션 저장소(https://github.com/googlecodelabs/android-kotlin-login-navigation)에서 모든 솔루션 코드가 포함된 전체 앱을 확인할 수 있습니다.

이 Codelab에서는 로그인을 지원하는 앱에서 우수한 사용자 환경을 만드는 방법에 관한 권장사항을 알아봤습니다. 앱의 인증 상태를 관찰하여 사용자가 액세스할 수 있는 화면을 확인하고 필요한 경우 로그인 화면으로 리디렉션할 수 있었습니다.

Android 탐색의 권장사항에 관한 자세한 내용은 다음 리소스를 확인하세요.

Android 개발자 문서:

Codelab:

이 과정의 다른 Codelab에 관한 링크는 Kotlin Codelab의 고급 Android 방문 페이지를 참고하세요.