[Android] 공식문서만 보고 Firebase REST API로 연결하기

uuranus·2023년 4월 21일
0
post-thumbnail

안드로이드 앱 개발 시 파이어베이스를 서버로 많이 사용한다. RealtimeDatabase, Firestore, Storage 등등이 있는데 RealtimeDatabase를 기준으로 작성하겠다.

REST API

출처 : AWS

  • REST(Representational State Transfer)는 복잡한 네크워크 통신을 관리하기 위해 API의 작동 방식에 대한 조건을 부과한 소프트웨어 아키텍쳐이다.
  • API가 REST를 따른 경우, RESTful API라고 한다.

SDK vs REST API

  • firebase는 네트워크 통신하는 방식이 자체 SDK를 통한 방식, REST API로 통신하는 방식이 있다.
  • 자체 SDK는 firebase의 메소드를 통해서 콜백 함수로 정의한다.
  • 콜백함수로 호출하다보니 여러번 네트워크 통신을 하다보면 콜백 함수 안에 콜백 함수 안에 콜백함수.. 이렇게 되기 때문에 코드가 복잡해질 수 있다.
  • REST API를 사용하면 Kotlin coroutine을 통해 동기적으로 보이는 것처럼 깔끔하게 작업을 할 수 있고 호출함수 호출 이후의 데이터 처리 함수를 분리하기가 쉬워 REST API를 사용했다.
  • 또, 나중에 파이어베이스 서버가 아닌 서버와 통신을 해야할 수도 있는데 그런 서버는 대부분 REST API를 따를 것이기 때문에 미리 연습해놓는 것도 좋다고 생각했다.

DTO 만들기

Data Transfer Object의 약자로 프로세스 간에 데이터를 전달하는 객체이다. 위키백과

  • 서버의 데이터 구조에 비해 UI 데이터 구조는 자주 바뀐다.

  • 따라서, UI용 데이터 객체네트워크 통신용 데이터 객체를 나누어서 서로의 객체로 변경할 수 있게 하는 확장 메소드를 만드는 게 나중에 수정할 때 좋다.

  • DTO 클래스는 실제 통신을 할 때는 JSON으로 전송되어야 함으로 Gson을 통해서 변경될 수 있도록 하자.

data class UserDataDTO(
    @SerializedName("nickname") val nickname: String,
    @SerializedName("uid") val uid: String,
    @SerializedName("lastLogin") val lastLogin: Long,
    @SerializedName("isGuest") val isGuest: Boolean
)
  • 다음처럼 @SerializedName으로 JSON에서 어떤 키값으로 저장할 것인지를 설정해줄 수 있다. 변수랑 동일한 이름을 사용할 거라면 안해도 되지만 보통 백엔드는 snake case를 쓰지만 프론트는 camel case를 쓰기 때문에 키값명이 서로 다를 수 있다.

Retrofit으로 API method 생성하기

파이어베이스 공식문서
Retrofit 메소드 만들기

GET

문서처럼

curl 'https://[PROJECT_ID].firebaseio.com/UserData/uid.json'

을 하면

{ "error": "Permission denied" }

다음과 같은 코드가 나온다. 이는 데이터베이스의 보안 규칙 때문인데 개발용이라면 read,write를 다 false로 해도 되지만 보통은 "auth.uid!=null" 로 로그인이 되어있는 사용자만 접근할 수 있게 막아놓는다.
파이어베이스 인증요청

access_token은 Google OAuth2로 접근할 때이고 auth는 FirebaseAuth로 접근할 때이다. 나는 Auth를 쓰기 때문에 auth로 찾아봤다. 위 REST 요청 인증이라는 링크를 따라 가보면 다음과 같은 코드를 찾을 수 있다.

FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
    .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
        public void onComplete(@NonNull Task<GetTokenResult> task) {
            if (task.isSuccessful()) {
                String idToken = task.getResult().getToken();
                // Send token to your backend via HTTPS
                // ...
            } else {
                // Handle error -> task.getException();
            }
        }
    });

출처
위 코드처럼 ID토큰을 얻을 수 있고 유효기간이 짧기 때문에 나는 사용자가 앱을 시작할 때마다 위 코드로 ID토큰을 받아오기로 했다.

@GET("/${DB_ROOT}/UserData/{uid}.json")
suspend fun getUserData(
    @Path("uid") uid: String,
    @Query("auth") token: String,
): Response<UserData>
  • 위처럼 auth를 쿼리로 전달해주면 원하는 데이터값을 얻을 수 있다.

POST

Post도 동일하게 auth를 쿼리로 전달해야 한다.

@POST("/${DB_ROOT}/UserData/{uid}.json")
suspend fun postUserData(
    @Path("uid") uid: String,
    @Query("auth") token: String,
    @Body data: UserDataDTO
): Response<PostDTO>

GET, PUT의 경우에는 데이터값이 리턴으로 돌아오지만 POST는

{ "name": "-INOQPH-aV_psbk3ZXEX" }

위처럼 푸시한 데이터들의 키값이 리턴되어 돌아오기 때문에 name 변수를 가지고 있는 PostDTO를 만들어주었다.


DELETE

DELETE의 경우에는 성공이면 null이 돌아오기 때문에 String을 리턴타입으로 해줬다

@DELETE("/${DB_ROOT}/UserData/{uid}.json")
suspend fun deleteUserData(
    @Path("uid") uid: String,
    @Query("auth") token: String,
): Response<String>
profile
Android Developer

0개의 댓글