안드로이드 앱 개발 시 파이어베이스를 서버로 많이 사용한다. RealtimeDatabase, Firestore, Storage 등등이 있는데 RealtimeDatabase를 기준으로 작성하겠다.
출처 : AWS
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
)
문서처럼
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>
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의 경우에는 성공이면 null이 돌아오기 때문에 String을 리턴타입으로 해줬다
@DELETE("/${DB_ROOT}/UserData/{uid}.json")
suspend fun deleteUserData(
@Path("uid") uid: String,
@Query("auth") token: String,
): Response<String>