로그인을 사용한 Android 조건부 탐색

이 Codelab은 Kotlin 기반 Android 고급 교육 과정의 일부입니다. Codelab을 순서대로 진행하는 경우 학습 효과를 극대화할 수 있지만 순서를 바꿔 진행해도 괜찮습니다. 모든 교육 과정 Codelab은 Kotlin 기반 고급 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()에서 settings_btnonClickListener를 설정하여 버튼을 탭하면 사용자가 customizeFragment로 이동하도록 합니다.

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.kt에서 onViewCreated()의 아무 곳에서나 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. 앱을 다시 실행하고 이제 로그인에 성공하면 로그인 페이지가 아닌 설정 페이지로 이동하는지 확인합니다.

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

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

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

Android 개발자 문서:

Codelab:

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