Firebase 및 Jetpack Compose를 사용하여 Android 앱 빌드

1. 소개

최종 업데이트 날짜: 2022-11-16

Firebase 및 Jetpack Compose를 사용하여 Android 앱 빌드

이 Codelab에서는 Make It So 라는 Android 앱을 빌드합니다. 이 앱의 UI는 기본 UI 구축을 위한 Android의 최신 도구 키트인 Jetpack Compose 로 완전히 구축되었습니다. 이는 직관적이며 .xml 파일을 작성하고 이를 활동, 프래그먼트 또는 뷰에 바인딩하는 것보다 코드가 덜 필요합니다.

Firebase와 Jetpack Compose가 얼마나 잘 함께 작동하는지 이해하는 첫 번째 단계는 최신 Android 아키텍처를 이해하는 것입니다. 좋은 아키텍처는 구성 요소가 구성되고 서로 통신하는 방식을 매우 명확하게 하기 때문에 시스템을 이해하기 쉽고, 개발하기 쉽고, 유지 관리하기 쉽습니다. Android 세계에서 권장되는 아키텍처는 Model - View - ViewModel 입니다. 모델은 애플리케이션의 데이터에 액세스하는 계층을 나타냅니다. 뷰는 UI 레이어이므로 비즈니스 로직에 대해 아무것도 몰라야 합니다. 그리고 ViewModel 은 비즈니스 로직이 적용되는 곳으로, 때로는 ViewModelModel 레이어를 호출해야 합니다.

Model - View - ViewModel이 Jetpack Compose로 빌드된 Android 앱에 어떻게 적용되는지 이해하려면 이 문서를 읽는 것이 좋습니다. 이렇게 하면 코드베이스를 더 쉽게 이해하고 다음 단계를 더 쉽게 완료할 수 있습니다.

무엇을 구축할 것인가

Make It So는 사용자가 작업을 추가 및 편집하고, 플래그, 우선순위 및 기한을 추가하고, 작업을 완료로 표시할 수 있는 간단한 할일 목록 애플리케이션입니다. 아래 이미지는 이 애플리케이션의 두 가지 기본 페이지, 즉 작업 생성 페이지와 생성된 작업 목록이 있는 기본 페이지를 보여줍니다.

Make it So Task 추가 화면Make it So 홈 화면

이 앱에 누락된 몇 가지 기능을 추가합니다.

  • 이메일과 비밀번호로 사용자 인증
  • Firestore 컬렉션에 리스너를 추가하고 UI가 변경 사항에 반응하도록 합니다.
  • 앱에서 특정 코드의 성능을 모니터링하기 위해 사용자 정의 추적을 추가합니다.
  • 원격 구성을 사용하여 기능 토글을 만들고 단계적 출시를 사용하여 실행합니다.

무엇을 배울 것인가

  • 최신 Android 애플리케이션에서 Firebase 인증, 성능 모니터링, 원격 구성, Cloud Firestore를 사용하는 방법
  • Firebase API를 MVVM 아키텍처에 적합하게 만드는 방법
  • Compose UI에서 Firebase API를 사용한 변경사항을 반영하는 방법

필요한 것

2. 샘플 앱 다운로드 및 Firebase 설정

샘플 앱의 코드 가져오기

명령줄에서 GitHub 저장소를 복제합니다.

git clone https://github.com/FirebaseExtended/make-it-so-android.git

Firebase 설정

가장 먼저 해야 할 일은 Firebase 콘솔 로 이동하여 아래와 같이 "+ 프로젝트 추가" 버튼을 클릭하여 Firebase 프로젝트를 만드는 것입니다.

Firebase 콘솔

화면에 나타나는 단계에 따라 프로젝트 생성을 완료하세요.

각 Firebase 프로젝트 내에서 Android, iOS, 웹, Flutter, Unity용 다양한 앱을 만들 수 있습니다. 여기에 표시된 대로 Android 옵션을 선택하세요.

Firebase 프로젝트 개요

그런 다음 다음 단계를 따르십시오.

  1. 패키지 이름으로 com.example.makeitso 입력하고 선택적으로 별명을 입력합니다. 이 Codelab에서는 디버그 서명 인증서를 추가할 필요가 없습니다.
  2. 다음을 클릭하여 앱을 등록하고 Firebase 구성 파일에 액세스하세요.
  3. google-services.json 다운로드를 클릭하여 구성 파일을 다운로드하고 make-it-so-android/app 디렉터리에 저장합니다.
  4. 다음 을 클릭합니다. Firebase SDK는 이미 샘플 프로젝트의 build.gradle 파일에 포함되어 있으므로 다음을 클릭하여 다음 단계 로 건너뜁니다.
  5. 콘솔에서 계속을 클릭하여 완료하세요.

Make it So 앱이 제대로 작동하도록 하려면 코드로 이동하기 전에 콘솔에서 인증 공급자를 활성화하고 Firestore 데이터베이스를 생성하는 두 가지 작업을 수행해야 합니다. 먼저 사용자가 앱에 로그인할 수 있도록 인증을 활성화하겠습니다.

  1. 빌드 메뉴에서 인증 을 선택한 다음 시작하기 를 클릭합니다.
  2. 로그인 방법 카드에서 이메일/비밀번호를 선택하고 활성화합니다.
  3. 그런 다음 새 공급자 추가를 클릭하고 Anonymous 를 선택하고 활성화합니다.

다음으로 Firestore를 설정합니다. Firestore를 사용하여 로그인한 사용자의 작업을 저장합니다. 각 사용자는 데이터베이스 컬렉션 내에서 자신의 문서를 갖게 됩니다.

  1. 빌드 메뉴에서 Firestore를 선택한 다음 데이터베이스 생성을 클릭합니다.
  2. 프로덕션 모드에서 시작을 활성화한 상태로 유지하고 Next 를 클릭합니다.
  3. 메시지가 표시되면 Cloud Firestore 데이터가 저장될 위치를 선택합니다. 프로덕션 앱을 개발할 때 이 앱이 대부분의 사용자와 가까운 지역에 있고 Functions와 같은 다른 Firebase 서비스와 공통적으로 있기를 원할 것입니다. 이 Codelab에서는 기본 지역을 유지하거나 가장 가까운 지역을 선택할 수 있습니다.
  4. 활성화를 클릭하여 Firestore 데이터베이스를 프로비저닝합니다.

Firestore 데이터베이스에 대한 강력한 보안 규칙을 구축하는 시간을 가져보겠습니다. Firestore 대시보드를 열고 규칙 탭으로 이동합니다. 그런 다음 보안 규칙을 다음과 같이 업데이트합니다.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
    }
  }
}

이러한 규칙은 기본적으로 앱에 로그인한 모든 사용자가 모든 컬렉션 내에서 자신을 위한 문서를 만들 수 있음을 나타냅니다. 그런 다음 일단 생성되면 해당 문서를 생성한 사용자만 해당 문서를 보거나 업데이트하거나 삭제할 수 있습니다.

애플리케이션 실행

이제 애플리케이션을 실행할 준비가 되었습니다! Android Studio에서 make-it-so-android/start 폴더를 열고 앱을 실행합니다(Android Emulator 또는 실제 Android 기기를 사용하여 실행할 수 있음).

3. 파이어베이스 인증

어떤 기능을 추가할 예정인가요?

Make It So 샘플 앱의 현재 상태에서는 사용자가 먼저 로그인하지 않고도 앱 사용을 시작할 수 있습니다. 이를 달성하기 위해 익명 인증을 사용합니다. 그러나 익명 계정을 사용하면 사용자가 다른 장치나 향후 세션에서도 자신의 데이터에 액세스할 수 없습니다. 익명 인증은 웜 온보딩에 유용하지만 사용자가 다른 로그인 형식으로 변환할 수 있는 옵션을 항상 제공해야 합니다. 이를 염두에 두고 이 Codelab에서는 Make It So 앱에 이메일 및 비밀번호 인증을 추가합니다.

코딩할 시간입니다!

사용자가 계정을 생성하자마자 이메일과 비밀번호를 입력하여 Firebase 인증 API에 이메일 자격 증명을 요청한 다음 새 자격 증명을 익명 계정에 연결해야 합니다. Android Studio에서 AccountServiceImpl.kt 파일을 열고 다음과 같이 linkAccount 함수를 업데이트합니다.

모델/서비스/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

이제 SignUpViewModel.kt 열고 onSignUpClick 함수의 launchCatching 블록 내에서 linkAccount 서비스 함수를 호출합니다.

스크린/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

먼저 인증을 시도하고, 호출이 성공하면 다음 화면( SettingsScreen )으로 진행됩니다. launchCatching 블록 내에서 이러한 호출을 실행할 때 첫 번째 줄에서 오류가 발생하면 예외가 포착되어 처리되며 두 번째 줄에는 전혀 도달하지 않습니다.

SettingsScreen 다시 열리자마자 사용자가 이미 인증되었으므로 로그인계정 만들기 옵션이 사라졌는지 확인해야 합니다. 이를 위해 SettingsViewModel 현재 사용자의 상태( AccountService.kt 에서 사용 가능)를 수신하여 계정이 익명인지 아닌지 확인하도록 하겠습니다. 이렇게 하려면 SettingsViewModel.kt 에서 uiState 다음과 같이 업데이트하세요.

화면/설정/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

마지막으로 해야 할 일은 SettingsScreen.kt 에서 uiState 업데이트하여 SettingsViewModel 에서 내보낸 상태를 수집하는 것입니다.

화면/설정/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

이제 사용자가 변경될 때마다 사용자의 새 인증 상태에 따라 옵션을 표시하도록 SettingsScreen 자체적으로 재구성됩니다.

테스트할 시간입니다!

Make it So를 실행하고 화면 오른쪽 상단에 있는 기어 아이콘을 클릭하여 설정으로 이동합니다. 거기에서 계정 만들기 옵션을 클릭하세요.

Make it So 설정 화면Make it So 회원가입 화면

계정을 만들려면 유효한 이메일과 강력한 비밀번호를 입력하세요. 작동해야 하며 설정 페이지로 리디렉션되어야 합니다. 여기서 로그아웃하고 계정을 삭제하는 두 가지 새로운 옵션이 표시됩니다. 사용자 탭을 클릭하면 Firebase 콘솔의 인증 대시보드에서 생성된 새 계정을 확인할 수 있습니다.

4. 클라우드 파이어스토어

어떤 기능을 추가할 예정인가요?

Cloud Firestore의 경우 Make it So 에 표시된 작업을 나타내는 문서를 저장하는 Firestore 컬렉션에 리스너를 추가합니다. 이 리스너를 추가하면 이 컬렉션에 대한 모든 업데이트를 받게 됩니다.

코딩할 시간입니다!

StorageServiceImpl.kt 에서 사용 가능한 Flow 다음과 같이 업데이트하세요.

모델/서비스/impl/StorageServiceImpl.kt

override val tasks: Flow<List<Task>>
    get() =
      auth.currentUser.flatMapLatest { user ->
        firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
      }

이 코드는 user.id 를 기반으로 작업 컬렉션에 리스너를 추가합니다. 각 작업은 tasks 라는 컬렉션문서 로 표시되며 각 작업에는 userId 라는 필드가 있습니다. currentUser 의 상태가 변경되면(예: 로그아웃) 새 Flow 생성됩니다.

이제 TasksViewModel.ktFlow 서비스와 동일하게 반영되도록 해야 합니다.

화면/작업/TasksViewModel.kt

val tasks = storageService.tasks

그리고 마지막으로 UI를 표현하는 TasksScreens.ktcomposable function 만들어 이 흐름을 인지하고 상태로 수집하도록 하겠습니다. 상태가 변경될 때마다 구성 가능한 함수는 자동으로 자체적으로 재구성되어 사용자에게 가장 최근 상태를 표시합니다. TasksScreen composable function 에 다음을 추가합니다.

화면/작업/TasksScreen.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

구성 가능한 함수가 이러한 상태에 액세스하면 LazyColumn (화면에 목록을 표시하는 데 사용하는 구조)을 다음과 같이 업데이트할 수 있습니다.

화면/작업/TasksScreen.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

테스트할 시간입니다!

작동하는지 테스트하려면 앱을 사용하여 새 작업을 추가하세요(화면 오른쪽 하단에 있는 추가 버튼을 클릭). 작업 생성이 완료되면 Firestore 콘솔의 Firestore 컬렉션에 표시됩니다. 동일한 계정으로 다른 기기에서 Make it So 에 로그인하면 할일 항목을 편집하고 모든 기기에서 실시간으로 업데이트되는 것을 확인할 수 있습니다.

5. 성능 모니터링

어떤 기능을 추가할 예정인가요?

성능은 앱을 사용하여 간단한 작업을 완료하는 데 너무 많은 시간이 걸리고 성능이 좋지 않으면 사용자가 앱 사용을 포기할 가능성이 높기 때문에 주의해야 할 매우 중요한 사항입니다. 그렇기 때문에 때때로 사용자가 앱에서 수행하는 특정 여정에 대한 일부 측정항목을 수집하는 것이 유용합니다. 이를 돕기 위해 Firebase Performance Monitoring은 맞춤 추적을 제공합니다. Make it So 에서 사용자 정의 추적을 추가하고 다양한 코드 조각의 성능을 측정하려면 다음 단계를 따르세요.

코딩할 시간입니다!

Performance.kt 파일을 열면 Trace라는 인라인 함수가 표시됩니다. 이 함수는 Performance Monitoring API를 호출하여 사용자 지정 추적을 생성하고 추적 이름을 매개변수로 전달합니다. 표시되는 다른 매개변수는 모니터링하려는 코드 블록입니다. 각 추적에 대해 수집된 기본 측정항목은 완전히 실행하는 데 걸리는 시간입니다.

모델/서비스/Performance.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

사용자 정의 추적을 측정하고 추가하는 데 중요하다고 생각되는 코드베이스 부분을 선택할 수 있습니다. 다음은 이 Codelab에서 앞서 AccountServiceImpl.kt 에서 본 linkAccount 함수에 커스텀 추적을 추가하는 예시입니다.

모델/서비스/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String): Unit =
  trace(LINK_ACCOUNT_TRACE) {
      val credential = EmailAuthProvider.getCredential(email, password)
      auth.currentUser!!.linkWithCredential(credential).await()
  }

이제 당신 차례입니다! Make it So 앱에 일부 사용자 지정 추적을 추가하고 다음 섹션으로 진행하여 예상대로 작동하는지 테스트합니다.

테스트할 시간입니다!

사용자 지정 추적 추가를 마친 후 앱을 실행하고 측정하려는 기능을 몇 번 사용해 보세요. 그런 다음 Firebase 콘솔로 이동하여 성능 대시보드 로 이동합니다. 화면 하단에는 네트워크 요청 , 맞춤 추적 , 화면 렌더링 이라는 세 가지 탭이 있습니다.

사용자 정의 추적 탭으로 이동하여 코드베이스에 추가한 추적이 여기에 표시되는지 확인하고 이러한 코드 조각을 실행하는 데 일반적으로 걸리는 시간을 확인할 수 있습니다.

6. 원격 구성

어떤 기능을 추가할 예정인가요?

앱의 모양을 원격으로 변경하는 것부터 다양한 사용자 세그먼트에 대해 다양한 동작을 구성하는 것까지 원격 구성의 다양한 사용 사례가 있습니다. 이 Codelab에서는 원격 구성을 사용하여 Make it So 앱의 새로운 편집 작업 기능을 표시하거나 숨기는 기능 토글을 만듭니다.

코딩할 시간입니다!

가장 먼저 해야 할 일은 Firebase 콘솔에서 구성을 만드는 것입니다. 이렇게 하려면 원격 구성 대시보드 로 이동하여 매개 변수 추가 버튼을 클릭해야 합니다. 아래 이미지에 따라 필드를 채우십시오.

원격 구성 매개변수 만들기 대화상자

모든 필드가 채워지면 저장 버튼을 클릭한 다음 게시 할 수 있습니다. 이제 매개변수가 생성되어 코드베이스에서 사용할 수 있으므로 새 값을 앱에 가져오는 코드를 추가해야 합니다. ConfigurationServiceImpl.kt 파일을 열고 다음 두 함수의 구현을 업데이트합니다.

모델/서비스/impl/ConfigurationServiceImpl.kt

override suspend fun fetchConfiguration(): Boolean {
  return remoteConfig.fetchAndActivate().await()
}

override val isShowTaskEditButtonConfig: Boolean
  get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()

첫 번째 함수는 서버에서 값을 가져오고 앱이 시작되자마자 SplashViewModel.kt 에서 호출됩니다. 이는 처음부터 모든 화면에서 최신 값을 사용할 수 있도록 하는 가장 좋은 방법입니다. 나중에 사용자가 무언가를 하고 있을 때 UI나 앱의 동작을 변경하면 좋은 사용자 경험이 아닙니다!

두 번째 함수는 콘솔에서 방금 생성한 매개변수에 대해 게시된 부울 값을 반환합니다. 그리고 loadTaskOptions 함수에 다음을 추가하여 TasksViewModel.kt 에서 이 정보를 검색해야 합니다.

화면/작업/TasksViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

첫 번째 줄에서 값을 검색하고 이를 사용하여 두 번째 줄의 작업 항목에 대한 메뉴 옵션을 로드합니다. 값이 false 이면 메뉴에 편집 옵션이 포함되지 않음을 의미합니다. 이제 옵션 목록이 있으므로 UI가 이를 올바르게 표시하도록 해야 합니다. Jetpack Compose로 앱을 빌드할 때 TasksScreen 의 UI 모양을 선언하는 composable function 찾아야 합니다. 따라서 TasksScreen.kt 파일을 열고 LazyColum 업데이트하여 TasksViewModel.kt 에서 사용 가능한 옵션을 가리키도록 합니다.

화면/작업/TasksScreen.kt

val options by viewModel.options

LazyColumn {
  items(tasks.value, key = { it.id }) { taskItem ->
    TaskItem(
      options = options,
      [...]
    )
  }
}

TaskItem 단일 작업의 UI 모양을 선언하는 또 다른 composable function 입니다. 그리고 각 작업에는 사용자가 끝에 있는 점 3개 아이콘을 클릭하면 표시되는 옵션이 포함된 메뉴가 있습니다.

테스트할 시간입니다!

이제 앱을 실행할 준비가 되었습니다! Firebase 콘솔을 사용하여 게시한 값이 앱 동작과 일치하는지 확인하세요.

  • false 인 경우 점 3개 아이콘을 클릭하면 두 가지 옵션만 표시됩니다.
  • true 인 경우 점 3개 아이콘을 클릭하면 세 가지 옵션이 표시됩니다.

콘솔에서 값을 몇 번 변경하고 앱을 다시 시작해 보세요. 원격 구성을 사용하면 앱에서 새로운 기능을 실행하는 것이 얼마나 쉬운가요?

7. 축하합니다

축하합니다. Firebase 및 Jetpack Compose를 사용하여 Android 앱을 성공적으로 빌드했습니다.

UI용 Jetpack Compose로 완전히 구축된 Android 앱에 Firebase 인증, 성능 모니터링, 원격 구성, Cloud Firestore를 추가하고 권장되는 MVVM 아키텍처에 맞게 만드셨습니다.

추가 읽기

참조 문서