Firebase Data Connect로 빌드 (Android)

1. 개요

ddc52cd46f923cf1.png

이 Codelab에서는 Firebase Data Connect를 Cloud SQL 데이터베이스와 통합하여 영화 리뷰 Android 앱을 빌드합니다. 다음 작업을 수행하는 방법을 알아봅니다.

  • Firebase Data Connect용 GraphQL 스키마 작성
  • 쿼리 및 변형 작성
  • 사용자 인증을 구현하여 데이터 보호

기본 요건

  • Android 스튜디오의 최신 버전
  • API 수준 23 이상을 실행하는 Android 에뮬레이터

학습할 내용

  • 로컬 에뮬레이터로 Firebase Data Connect를 설정하는 방법
  • Data Connect 및 GraphQL을 사용하여 데이터 스키마를 설계하는 방법
  • 영화 리뷰 앱의 쿼리 및 변형을 작성하는 방법
  • Kotlin SDK를 생성하고 Android 앱에서 사용하는 방법
  • (선택사항) 프로덕션에 데이터 연결 서비스를 배포하는 방법

2. 샘플 프로젝트 설정

Firebase 프로젝트 만들기

  1. Google 계정으로 Firebase Console에 로그인합니다.
  2. Firebase Console에서 프로젝트 추가를 클릭합니다.
  3. Firebase 프로젝트 이름 (예: '영화 리뷰')을 입력하고 '계속'을 클릭합니다.
  4. Google 애널리틱스를 사용 설정하라는 메시지가 표시될 수 있습니다. 이 Codelab에서는 선택사항이 중요하지 않습니다.
  5. 1분 정도 후에 Firebase 프로젝트가 준비됩니다. '계속'을 클릭합니다.

코드 다운로드

다음 명령어를 실행하여 이 Codelab의 샘플 코드를 클론합니다. 그러면 머신에 codelab-dataconnect-android라는 디렉터리가 생성됩니다.

git clone https://github.com/firebaseextended/codelab-dataconnect-android.git

컴퓨터에 git이 없다면 GitHub에서 직접 코드를 다운로드할 수도 있습니다.

Firebase 구성 추가

  1. Firebase Console의 왼쪽 탐색 메뉴에서 프로젝트 개요를 선택합니다. Android 버튼을 클릭하여 플랫폼을 선택합니다. 패키지 이름을 입력하라는 메시지가 표시되면 com.google.firebase.example.dataconnect를 사용합니다.
  2. '앱 등록'을 클릭하고 안내에 따라 google-services.json 파일을 다운로드한 다음 방금 다운로드한 코드의 app/ 디렉터리로 이동합니다. 그런 다음 '다음'을 클릭합니다.

3. 데이터 연결 설정

설치

자동 설치

codelab-dataconnect-android 디렉터리에서 다음 명령어를 실행합니다.

curl -sL https://firebase.tools/dataconnect | bash

이 스크립트는 개발 환경을 설정하고 브라우저 기반 IDE를 실행하려고 시도합니다. 이 IDE는 사전 번들로 제공되는 VS Code 확장 프로그램을 비롯하여 스키마를 관리하고 애플리케이션에 사용할 쿼리 및 변형을 정의하고 강력한 유형의 SDK를 생성하는 데 도움이 되는 도구를 제공합니다.

스크립트를 실행하면 VS Code가 자동으로 열립니다.

참고: 데스크톱 버전의 VS Code가 이미 설치되어 있으면 스크립트가 자동으로 열립니다. 스크립트가 실패하면 아래의 수동 설치 단계를 따르세요.

수동 설치

  1. Visual Studio Code 설치
  2. Node.js를 설치합니다.
  3. VS Code에서 codelab-dataconnect-android 디렉터리를 엽니다.
  4. Visual Studio Code Marketplace에서 Firebase Data Connect 확장 프로그램을 설치합니다.

프로젝트에서 Data Connect 초기화

왼쪽 패널에서 Firebase 아이콘을 클릭하여 Data Connect VS Code 확장 프로그램 UI를 엽니다.

  1. Google 계정으로 로그인 버튼을 클릭합니다. 브라우저 창이 열립니다. 안내에 따라 Google 계정으로 확장 프로그램에 로그인합니다. ef59f25a9e9cbfff.png
  2. Firebase 프로젝트 연결 버튼을 클릭하고 이전에 Console에서 만든 프로젝트를 선택합니다. 951a836ba0682494.png

Run firebase init 버튼을 클릭하고 통합 터미널의 단계를 따릅니다.

SDK 생성 구성

Run firebase init 버튼을 클릭하면 Firebase Data Connect 확장 프로그램에서 dataconnect/ 디렉터리를 초기화합니다.

VS Code에서 dataconnect/connector/connector.yaml 파일을 열면 기본 구성이 표시됩니다. 이 Codelab에서 코드 생성을 더 쉽게 시각화하려면 connectorId를 movies로, package를 com.google.firebase.example.dataconnect.generated로 변경합니다.

connectorId: movies
generate:
  kotlinSdk:
    outputDir: ../../app/src/main/java
    package: com.google.firebase.example.dataconnect.generated

각 상태의 의미는 다음과 같습니다.

  • connectorId - 이 커넥터의 고유한 이름입니다.
  • outputDir - 생성된 Data Connect SDK가 저장되는 경로입니다. 이 경로는 connector.yaml 파일이 포함된 디렉터리를 기준으로 합니다.
  • package - 생성된 SDK에 사용할 패키지 이름입니다.

Firebase 에뮬레이터 시작

VS Code에서 에뮬레이터 시작 버튼을 클릭합니다.

93fb67962e96a7cb.png

통합 터미널에서 에뮬레이터가 시작되는 것을 볼 수 있습니다. 제대로 시작되면 다음과 같은 출력이 표시됩니다.

8504ae0080923823.png

로컬 에뮬레이터를 사용하도록 Android 앱 구성

  1. Android 스튜디오를 엽니다.
  2. Android 스튜디오의 시작 화면에서 'Open'(열기) 버튼을 클릭하고 codelab-dataconnect-android 디렉터리를 선택합니다. Gradle이 동기화될 때까지 기다립니다.
  3. Gradle 동기화가 완료되면 app/src/main/java/com/google/firebase/example/dataconnect/MainActivity.kt 파일을 열고 useEmulator()를 호출합니다.
import com.google.firebase.example.dataconnect.generated.MoviesConnector
import com.google.firebase.example.dataconnect.generated.instance

class MainActivity : ComponentActivity() {
  ...

  // Initialize Firebase Data Connect
  MoviesConnector.instance.dataConnect.useEmulator("10.0.2.2", 9399)

  ...
}

4. 스키마 정의 및 데이터베이스 미리 채우기

이 섹션에서는 영화 애플리케이션의 핵심 항목 간의 구조와 관계를 스키마로 정의합니다. Movie, User, Review와 같은 항목은 Firebase Data Connect 및 GraphQL 스키마 디렉티브를 사용하여 관계가 설정된 데이터베이스 테이블에 매핑됩니다.

핵심 항목 및 관계

Movie 유형은 앱에서 검색 및 영화 프로필에 사용하는 제목, 장르, 태그와 같은 주요 세부정보를 보유합니다. User 유형은 리뷰 및 즐겨찾기와 같은 사용자 상호작용을 추적합니다. Review는 사용자를 영화에 연결하여 앱에서 사용자 생성 평점 및 의견을 표시할 수 있도록 합니다.

사용자 표

사용자 유형은 리뷰를 남기거나 영화에 관심을 표시하여 영화와 상호작용하는 사용자 항목을 정의합니다.

VS Code에서 dataconnect/schema/schema.gql 파일을 열고 User 테이블 정의를 주석 처리 해제하거나 추가합니다.

# Users
# Suppose a user can leave reviews for movies
# user  -> reviews is a one to many relationship,
# movie -> reviews is a one to many relationship
# movie <-> user is a many to many relationship
type User @table {
  id: String! @col(name: "user_auth")
  username: String! @col(name: "username", dataType: "varchar(50)")
  # The following are generated by the user: User! field in the Review table
  # reviews_on_user 
  # movies_via_Review
}

영화 표

Movie 유형은 title, genre, releaseYear, rating과 같은 필드를 포함하여 영화 항목의 기본 구조를 정의합니다.

VS Code에서 dataconnect/schema/schema.gql 파일을 열고 Movie 테이블 정의를 주석 처리 해제하거나 추가합니다.

# Movies
type Movie @table {
  # The below parameter values are generated by default with @table, and can be edited manually.
  # implies directive `@col(name: "movie_id")`, generating a column name
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  imageUrl: String!
  genre: String
}

MovieMetadata 테이블

MovieMetadata 유형은 Movie 유형과 일대일 관계를 설정합니다. 영화의 감독과 같은 추가 데이터가 포함됩니다.

VS Code에서 dataconnect/schema/schema.gql 파일을 열고 MovieMetadata 테이블 정의를 주석 처리 해제하거나 추가합니다.

# Movie - MovieMetadata is a one-to-one relationship
type MovieMetadata @table {
  # @unique indicates a 1-1 relationship
  movie: Movie! @unique 
  # movieId: UUID <- this is created by the above reference
  rating: Float
  releaseYear: Int
  description: String
}

검토 표

Review 유형은 리뷰 항목을 나타내며 User 및 Movie 유형을 다대다 관계로 연결합니다 (한 사용자가 여러 리뷰를 작성할 수 있고 각 영화에 여러 리뷰가 있을 수 있음).

VS Code에서 dataconnect/schema/schema.gql 파일을 열고 Review 테이블 정의를 주석 처리 해제하거나 추가합니다.

# Reviews
type Review @table(name: "Reviews", key: ["movie", "user"]) {
  id: UUID! @default(expr: "uuidV4()")
  user: User!
  movie: Movie!
  rating: Int
  reviewText: String
  reviewDate: Date! @default(expr: "request.time")
}

자동 생성된 필드 및 기본값

스키마는 @default(expr: "uuidV4()")와 같은 표현식을 사용하여 고유 ID와 타임스탬프를 자동으로 생성합니다. 예를 들어 영화 및 리뷰 유형의 ID 필드는 새 레코드가 생성될 때 UUID로 자동으로 채워집니다.

모의 데이터 삽입

스키마가 정의되었으므로 이제 테스트를 위해 데이터베이스를 모의 데이터로 미리 채울 수 있습니다.

  1. VS Code에서 dataconnect/moviedata_insert.gql를 엽니다. Firebase Data Connect 확장 프로그램의 에뮬레이터가 실행 중인지 확인합니다.
  2. 파일 상단에 Run (local)(실행(로컬)) 버튼이 표시됩니다. 이를 클릭하면 데이터베이스에 가상 영화 데이터가 삽입됩니다.

b070f025e573ab9b.png

  1. Data Connect 실행 터미널에서 데이터가 추가되었는지 확인합니다.

e2058cb4db857058.png

데이터가 준비되면 다음 단계로 진행하여 Data Connect에서 쿼리를 만드는 방법을 알아봅니다.

5. 영화를 나열하는 쿼리 만들기

먼저 영화를 나열하는 쿼리를 만듭니다. 각 영화의 id, 제목, imageUrl, 장르를 가져옵니다.

쿼리 정의

VS Code에서 dataconnect/connector/queries.gql 파일을 열고 ListMovies 쿼리의 주석 처리를 삭제하거나 추가합니다.

query ListMovies @auth(level: PUBLIC) {
  movies {
    id
    title
    imageUrl
    genre
  }
}

새 쿼리를 테스트하려면 Run (local) 버튼을 클릭하여 로컬 데이터베이스에 대해 쿼리를 실행합니다. 데이터베이스의 영화 목록이 Data Connect 실행 터미널의 '결과' 섹션에 표시됩니다.

822bf32321df4716.png

Android 앱에서 호출

이제 Data Connect 에뮬레이터에서 쿼리를 테스트했으므로 앱에 추가해 보겠습니다.

Android 스튜디오에서 app/src/main/java/com/google/firebase/example/dataconnect/MoviesScreen.kt 파일을 열고 다음 코드를 추가하여 영화 목록을 그리드 형식으로 표시합니다.

import com.google.firebase.example.dataconnect.generated.ListMoviesQuery
import com.google.firebase.example.dataconnect.generated.MoviesConnector
import com.google.firebase.example.dataconnect.generated.execute
import com.google.firebase.example.dataconnect.generated.instance

@Composable
fun MoviesScreen(
    onMovieClicked: (id: String) -> Unit
) {
    var movies by remember { mutableStateOf(emptyList<ListMoviesQuery.Data.MoviesItem>()) }
    LaunchedEffect(Unit) {
        // Queries need to be executed in a coroutine context
        try {
          movies = MoviesConnector.instance.listMovies.execute().data.movies
        } catch (e: Exception) {
          // Will be done at a later step
        }
    }
    LazyVerticalGrid(GridCells.Adaptive(150.dp)) {
        items(movies) { movie ->
            MovieCard(
                movieId = movie.id.toString(),
                movieTitle = movie.title,
                movieImageUrl = movie.imageUrl,
                movieGenre = movie.genre,
                onMovieClicked = {
                    onMovieClicked(movie.id.toString())
                }
            )
        }
    }
}

앱 실행

Android 스튜디오에서 Run(실행) 버튼을 클릭하여 Android 에뮬레이터에서 앱을 실행합니다.

앱이 실행되면 다음과 같은 화면이 표시됩니다.

ddc52cd46f923cf1.png

6. 영화 세부정보 쿼리 만들기

이제 앱에서 영화를 표시할 수 있으므로 각 영화의 세부정보를 표시하는 쿼리를 만들어 보겠습니다.

쿼리 정의

VS Code에서 dataconnect/connector/queries.gql 파일을 열고 GetMovieById 쿼리의 주석 처리를 삭제하거나 추가합니다.

# Get movie by id
query GetMovieById($id: UUID!) @auth(level: PUBLIC) {
  movie(id: $id) {
    id
    title
    imageUrl
    genre
    metadata: movieMetadata_on_movie {
      rating
      releaseYear
      description
    }
    reviews: reviews_on_movie {
      id
      reviewText
      reviewDate
      rating
      user {
        id
        username
      }
    }
  }
}

Android 앱에서 호출

Android 스튜디오에서 app/src/main/java/com/google/firebase/example/dataconnect/MovieDetailScreen.kt 파일을 열고 다음 코드를 추가합니다.

importcom.google.firebase.example.dataconnect.generated.GetMovieByIdQuery
importcom.google.firebase.example.dataconnect.generated.MoviesConnector
importcom.google.firebase.example.dataconnect.generated.execute
importcom.google.firebase.example.dataconnect.generated.instance

@Composable
fun MovieDetailScreen(
    movieId: String
) {
    var movie by remember { mutableStateOf<GetMovieByIdQuery.Data.Movie?>(null) }
    LaunchedEffect(Unit) {
        movie = MoviesConnector.instance.getMovieById.execute(
            UUID.fromString(movieId)
        ).data.movie
    }
    if (movie == null) {
        LoadingScreen()
    } else {
        MovieDetails(
            movieTitle = movie!!.title,
            movieImageUrl = movie!!.imageUrl,
            movieGenre = movie!!.genre,
            movieRating = movie!!.metadata?.rating,
            movieReleaseYear = movie!!.metadata?.releaseYear,
            movieDescription = movie!!.metadata?.description,
        )
    }
}

앱 실행

Android 스튜디오에서 Run(실행) 버튼을 클릭하여 Android 에뮬레이터에서 앱을 실행합니다.

7. 사용자를 삽입하는 변형 만들기

이제 앱에서 데이터를 표시할 수 있으므로 앱에서 새 데이터를 추가해 보겠습니다. 안전하게 추가하려면 Firebase 인증을 사용해야 합니다.

이 Codelab에서는 앱이 익명 인증을 사용하여 사용자를 로그인 처리하지만, 더 안전한 앱을 만들려면 이메일/비밀번호 인증이나 제휴 ID 공급업체와 같은 다른 인증 방법을 사용하는 것이 좋습니다.

변형 정의

VS Code에서 dataconnect/connector/mutations.gql 파일을 열고 UpsertUser 쿼리의 주석 처리를 삭제하거나 추가합니다.

# Upsert (update or insert) a user's username based on their auth.uid
mutation UpsertUser($username: String!) @auth(level: USER) {
  user_upsert(
    data: {
      id_expr: "auth.uid"
      username: $username
    }
  )
}

Android 앱에서 호출

Android 스튜디오에서 app/src/main/java/com/google/firebase/example/dataconnect/MainActivity.kt 파일을 열고 다음과 같이 변형을 호출합니다.

import com.google.firebase.example.dataconnect.generated.execute

LaunchedEffect(Unit) {
  // If there's no user signed in, sign in an anonymous user
  if (firebaseAuth.currentUser == null) {
    firebaseAuth.signInAnonymously().await()
    val newUsername = getRandomUsername()
    MoviesConnector.instance.upsertUser.execute(newUsername)
  }
}

앱 실행

Android 스튜디오에서 Run(실행) 버튼을 클릭하여 Android 에뮬레이터에서 앱을 실행합니다.

8. 축하합니다

축하합니다. Android 앱에 Firebase Data Connect를 추가했습니다.

이제 Data Connect를 설정하고, 쿼리 및 변형을 만들고, 사용자 인증을 처리하는 데 필요한 주요 단계를 알게 되었습니다.

다음 단계

선택사항: 프로덕션에 배포

지금까지 이 앱은 Firebase 에뮬레이터만 사용했습니다. 이 앱을 실제 Firebase 프로젝트에 배포하는 방법을 알아보려면 다음 단계로 진행하세요.

9. (선택사항) 앱 배포

지금까지 이 앱은 완전히 로컬이었고 모든 데이터가 Firebase 에뮬레이터 도구 모음에 포함되어 있었습니다. 이 섹션에서는 이 앱이 프로덕션에서 작동하도록 Firebase 프로젝트를 구성하는 방법을 알아봅니다.

Firebase 인증 사용 설정

Firebase Console에서 인증 섹션으로 이동하여 '시작하기'를 클릭합니다. 로그인 방법 탭으로 이동하여 제공업체에서 익명 로그인 옵션을 선택합니다.

익명 로그인 방법을 사용 설정하고 '저장'을 클릭합니다.

Firebase Data Connect 스키마 배포

중요: 프로젝트에 스키마를 배포하는 것이 처음이라면 이 프로세스에서 Cloud SQL PostgreSQL 인스턴스가 생성되며, 이때 약 15분 정도 걸릴 수 있습니다. Cloud SQL 인스턴스가 준비되고 Firebase 데이터 연결과 통합될 때까지는 배포할 수 없습니다.

  1. Firebase Data Connect VS Code 확장 프로그램 UI에서 프로덕션에 배포를 클릭합니다.
  2. 스키마 변경사항을 검토하고 잠재적으로 파괴적인 수정사항을 승인해야 할 수도 있습니다. 다음과 같은 메시지가 표시됩니다.
    • firebase dataconnect:sql:diff를 사용하여 스키마 변경사항 검토
    • 변경사항이 만족스러우면 firebase dataconnect:sql:migrate로 시작된 흐름을 사용하여 변경사항을 적용합니다.

PostgreSQL용 Cloud SQL 인스턴스가 최종적으로 배포된 스키마와 데이터로 업데이트됩니다. Firebase Console에서 상태를 모니터링할 수 있습니다.

이제 로컬 에뮬레이터에서와 마찬가지로 Firebase Data Connect 패널에서 Run(실행)(프로덕션)을 클릭하여 프로덕션 환경에 데이터를 추가할 수 있습니다.