마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

싱글액티비티에 로그인/회원가입화면이 있을경우

0 추천
요즘 앱을 싱글액티비티로 구성하고 나머지 화면은 프래그먼트로 구성하는 경우가 많잖아요?

그런데 앱에 회원가입/로그인 기능이 있을경우에는 어떻게 구성을 하나요?

 

로그인 화면 - 액티비티

회원가입/나머지 화면 - 프래그먼트

이렇게 구성되어 싱글액티비티에 로그인화면이 포함인건가요

 

아니면

로그인/회원가입 화면 - 액티비티

다른 첫화면 - 메인 액티비티

나머지화면 - 프래그먼트

이런식으로 로그인/회원가입화면은 별도로 생각을하고 싱글액티비티로 구성을하나요?

 

또 아니면

로그인/회원가입 - 프래그먼트

메인화면 - 액티비티

나머지화면 - 프래그먼트

이런식으로 구성되어야하나요?
codeslave (3,940 포인트) 님이 2022년 1월 7일 질문
codeslave님이 2022년 1월 7일 수정

1개의 답변

0 추천

두가지 방향이 있습니다. 로그인 관련을 별도의 액티비티로 구성하는 방법(Medium에 보면 은행 앱에 이렇게 구현한 글이 있더라구요)과 로그인이든 뭐든 상관없이 완전히 싱글 액티비티로 가는 경우. 첫번째 방법은 NavHost나 NavController를 하나만 가지고 한군데서 네비게이션 관리가 가능지만, 아래와 같은 문제들을 있고,

- 로그인 여부에 로그인이나 홈 화면을 상황에 맞게 startDestination으로 설정하기
- 로그인 화면에는 툴바나 다른 메뉴가 보이지 않지만 로그인 후에는 보여야 함

두번째 방법은 화면을 깔끔하게 분리할 수 있지만, 로그인은  네비게이션 컴포넌트를 사용함에도 거의 별개의 네비게이션 처럼 된다는 것이죠.

사실 네비게이션 컴포넌트 나오기 전에는 싱글액티비티는 현재 네비게이션 컴포넌트 등에 제공하는 코드를 구현해줘야 했기 때문에 메인액티비티에 불필요한 코드가 엄청 들어가는 God object를 만들게 됨으로써 안티 패턴으로 취급이 되었었는데, 네비게이션을 컨트롤 할 수 있게 되면서 이 부분이 해결되었고 사실 싱글액티비티 사용에는 여러가지 이득이 있습니다. 예를 들면, BaseActivity라는 걸 만들어서 공통코드(예를 들면, 사용자 interaction 체크) 등을 집어넣어서 사용했지만, 싱글액티비티를 사용하면 그럴 필요가 없죠. 이전에 액티비티 레벨에서 무언가를 공통적으로 해주어야 하는 게 있었다면, 엄청 간단해 지게 된거죠. 그리고 기본적으로 프레그먼트가 액티비티 보다는 경량입니다. 메모리 사용도 적고 빠릅니다. 앱 퍼포먼스 향상도 가져올 수 있습니다.

저같은 경우는 첫번째 방법을 사용하는데, 주된 이유는 저는 네비게이션 컴포넌트를 액티비티나 프레그먼트에서 직접 사용하지 않고 제가 만든 클래스에 감싸서 사용하고 있습니다. 그 클래스에서 사용자 로그인 체크 등을 처리합니다.

위에서 언급했던 두가지 문제는 개발자 문서를 보시면  해결방법이 나옵니다.

로그인 상태에 따른 시작화면 설정: 화면시작 시에 로그인 상태를 보고 NavGraph.startDestination을 동적으로 호출해 주면 됨.
화면에 따른 툴바나 메뉴제어: https://developer.android.com/guide/navigation/navigation-ui


전체를 싱글액티비티로 시도해 보시고, 이게 구현이 좀 어렵다면 두번째 방법을 차선책으로 사용해 보시라고 권해드리고 싶네요.

* 로그인 상태에 따라 시작화면을 설정하는 좀 더 자세한 방법은, 네비게이션 그래프에(XML)는 개발자 문서에 나온 것 처럼 홈이 되는 프레그먼를 설정하시면 되고, 메인 액티비티의 onCreate 에서 로그인 상태를 체크하셔서, 로그인이 안된 경우라면  로그인 프레그먼트를 띄운다음 백스택을 클리하고 startDestination을 로그인 프레그먼트로 잡아주시면 됩니다. 

아래에 아주 기본적인 코드를 적어 볼게요.

nav_graph.xml
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:id="@+id/nav_graph"
   app:startDestination="@id/home_fragment">

   <fragment
       android:id="@+id/home_fragment"
       android:name="HomeFragment"
       android:label="Game" />

   <fragment
       android:id="@+id/login_fragment"
       android:name="LoginFragment />

</navigation>


MainActivity
class MainActivity: AppCompatActivity  {
 
     override fun onCreate(saveInstance: Bundle?) {
          super.onCreate(saveInstance);
          setContentView(binding.root);

          setupViews();
          // 액티비티가 안드로이드 시스템에 의해 다시 생성된 경우(예: 디바이스 로테이션, 다크모드 세팅 등)
          // 네비게이션 컴포넌트가 상태를 기억하고 있기 때문에 네비게이션을 초기화하지 않는다.
          if (saveInstance != null) {
             setupNavigation();
          }
     }

     private fun setupNavigation() {
         navController = ...

         if (session.isNotLoggedIn) {
             goToLogin();
         } else {
             goHome();
         }
     }

     private fun goToLogin() {
         navController.navigate(
                R.id.logn_fragment, 
                null, 
                navOptions {
                  popUpTo = R.id.nav_graph,
                  inclusive = false
                }
        }
        navGraph.startDestination = R.id.login_fragment
     }

    private fun goHome() {
         navController.navigate(
                R.id.home_fragment, 
                null, 
                navOptions {
                  popUpTo = R.id.nav_graph,
                  inclusive = false
                }
        }
        navGraph.startDestination = R.id.home_fragment
     }
}

 

spark (227,470 포인트) 님이 2022년 1월 7일 답변
문서를 보니 Global Action이란게 추가 되었네요.
https://developer.android.com/guide/navigation/navigation-global-action
이거랑 조합해서 사용하시면 좋을 듯합니다.
감사합니다. '완전' 싱글액티비 사용이 선호?되는것 같네요..

선생님 그렇다면 로그인/회원가입 화면 포함해서 완전히 싱글액티비티로 갈경우 질문드릴게요.

싱글액티비티이면 어느 화면을 액티비티 기준으로 삼아야 하는가?
인데요
제가 첫번째 방법에서는 로그인 또는 회원가입이라고 했는데 적다보니 첫번째,세번째 방법이 사실 똑같이 둘다 완전 싱글액티비티인데 차이점이 어느 화면을 액티비티로 삼는가의 차이점인거 같거든요.

싱글액티비티의 기준이 시작화면(로그인화면)인지 아니면 로그인 이후의 첫화면인지 궁금합니다.

당연히 더 많은 기능을 수행하는 후자인가요?


+) 만약 로그인 화면이 아닌 다른 이후화면을 액티비티로 잡을경우, 로그인화면은 프래그먼트의 사용을 뜻하는데 이 경우 앱 시작후 시작화면을 매니페스트에서 설정하지 않고 바로 선생님이 하신것처럼 Navigation을 통해 컨트롤해주면 될까요?
로그인 후의 메인화면이 홈이 되는게 좀 더 합리적일 듯 한데, 말씀드렸다시피 로그인 상황에 따라 strtDestination을 다시 설정하시면 될 것 같아요.
AndroidManifest에는 액티비티만 설정이 가능하구요, startDestination(프레그먼트)는 navigation XML에 설정이 가능해요. 그런데 어차피 시작 프레그먼트를 동적으로 바꾸셔야 하기 때문에 startDestination 자체가 큰 문제는 되지 않을 것으로 보이네요. 어쨋거나 코드를 통해 컨트롤 하셔야 해요. 로그인 액티비티를 사용하더라도 그렇구요.
아래 링크를 읽어보세요. 도움이 되실 거예요.
https://developer.android.com/guide/navigation/navigation-conditional
https://medium.com/androiddevelopers/navigation-conditional-navigation-e82d7e4905f0
참 다른 옵션으로는  startDestination을 홈 프레그먼트로 설정하고 startDestination 다시 설정하거나 할 필요없이 로그인이 안되었을 경우는 로그인 프레그먼트를 홈 프레그먼트 위에 띄우고, 로그인 프레그먼트에서 백버튼을 누르면 앱이 종료되도록 만드는 방법도 있습니다.
...