Parse Android 앱을 Firebase로 마이그레이션

서비스로서의 백엔드(BaaS) 솔루션을 찾고 있는 Parse 사용자에게 Firebase는 Android 앱을 위한 이상적인 대안입니다.

이 가이드에서는 특정 서비스를 앱에 통합하는 방법을 설명합니다. Firebase 기본 설정 안내는 Android 설정 가이드를 참조하세요.

Google 애널리틱스

Google 애널리틱스는 앱 사용 및 사용자 참여에 대한 통계를 제공하는 무료 앱 측정 솔루션입니다. 애널리틱스는 Firebase 기능 전체에 통합되며 Firebase SDK를 사용하여 정의할 수 있는 최대 500개의 고유한 이벤트에 대한 무제한 보고를 제공합니다.

자세한 내용은 Google 애널리틱스 문서를 참조하세요.

추천 마이그레이션 전략

여러 분석 제공업체를 함께 이용하는 경우에도 Google 애널리틱스를 손쉽게 도입할 수 있습니다. 앱에 추가하기만 하면 최초 사용, 앱 업데이트, 기기 모델, 연령 등 애널리틱스에서 자동으로 수집하는 이벤트 및 사용자 속성을 활용할 수 있습니다.

커스텀 이벤트 및 사용자 속성의 경우 이벤트 및 속성을 로깅하는 데 Parse Analytics 및 Google 애널리틱스를 둘 다 사용하는 이중 작성 전략을 사용하여 새 솔루션을 점진적으로 도입할 수 있습니다.

코드 비교

Parse Analytics

// Start collecting data
ParseAnalytics.trackAppOpenedInBackground(getIntent());

Map<String, String> dimensions = new HashMap<String, String>();
// Define ranges to bucket data points into meaningful segments
dimensions.put("priceRange", "1000-1500");
// Did the user filter the query?
dimensions.put("source", "craigslist");
// Do searches happen more often on weekdays or weekends?
dimensions.put("dayType", "weekday");

// Send the dimensions to Parse along with the 'search' event
ParseAnalytics.trackEvent("search", dimensions);

Google 애널리틱스

// Obtain the FirebaseAnalytics instance and start collecting data
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);

Bundle params = new Bundle();
// Define ranges to bucket data points into meaningful segments
params.putString("priceRange", "1000-1500");
// Did the user filter the query?
params.putString("source", "craigslist");
// Do searches happen more often on weekdays or weekends?
params.putString("dayType", "weekday");

// Send the event
mFirebaseAnalytics.logEvent("search", params);

Firebase 실시간 데이터베이스

Firebase 실시간 데이터베이스는 NoSQL 클라우드 호스팅 데이터베이스입니다. 데이터는 JSON으로 저장되며 연결된 모든 클라이언트에 실시간으로 동기화됩니다.

자세한 내용은 Firebase 실시간 데이터베이스 문서를 참조하세요.

Parse 데이터와의 차이

객체

Parse에서는 JSON 호환 데이터의 키-값 쌍이 있는 ParseObject 또는 그 서브클래스를 저장합니다. 이 데이터는 스키마가 없습니다. 즉, 각 ParseObject에 있는 키를 지정할 필요가 없습니다.

모든 Firebase 실시간 데이터베이스 데이터는 JSON 객체로 저장되고 ParseObject에 해당하는 것은 없습니다. 사용 가능한 JSON 유형에 해당하는 JSON 트리 값 유형에 작성하면 됩니다. 자바 객체를 사용하여 데이터베이스 읽기와 쓰기를 단순화할 수 있습니다.

다음 예는 게임의 최고 점수를 저장할 수 있는 방법을 보여줍니다.

Parse
@ParseClassName("GameScore")
public class GameScore {
        public GameScore() {}
        public GameScore(Long score, String playerName, Boolean cheatMode) {
            setScore(score);
            setPlayerName(playerName);
            setCheatMode(cheatMode);
        }

        public void setScore(Long score) {
            set("score", score);
        }

        public Long getScore() {
            return getLong("score");
        }

        public void setPlayerName(String playerName) {
            set("playerName", playerName);
        }

        public String getPlayerName() {
            return getString("playerName");
        }

        public void setCheatMode(Boolean cheatMode) {
            return set("cheatMode", cheatMode);
        }

        public Boolean getCheatMode() {
            return getBoolean("cheatMode");
        }
}

// Must call Parse.registerSubclass(GameScore.class) in Application.onCreate
GameScore gameScore = new GameScore(1337, "Sean Plott", false);
gameScore.saveInBackground();
Firebase
// Assuming we defined the GameScore class as:
public class GameScore {
        private Long score;
        private String playerName;
        private Boolean cheatMode;

        public GameScore() {}
        public GameScore(Long score, String playerName, Boolean cheatMode) {
            this.score = score;
            this.playerName = playerName;
            this.cheatMode = cheatMode;
        }

        public Long getScore() {
            return score;
        }

        public String getPlayerName() {
            return playerName;
        }

        public Boolean getCheatMode() {
            return cheatMode;
        }
}

// We would save it to our list of high scores as follows:
DatabaseReference mFirebaseRef = FirebaseDatabase.getInstance().getReference();
GameScore score = new GameScore(1337, "Sean Plott", false);
mFirebaseRef.child("scores").push().setValue(score);
자세한 내용은 Android에서 데이터 읽기 및 쓰기 가이드를 참조하세요.

데이터 사이의 관계

ParseObject는 다른 ParseObject와 연관되어 있을 수 있습니다. 모든 객체는 다른 객체를 값으로 사용할 수 있습니다.

Firebase 실시간 데이터베이스에서는 플랫 데이터 구조를 사용하여 관계를 더 잘 표현합니다. 이 구조에서는 별도의 경로로 데이터를 분할하므로 별도의 호출로 효율적으로 다운로드할 수 있습니다.

다음 예는 블로깅 앱의 게시물과 작성자 사이의 관계를 구조화하는 방법을 보여줍니다.

Parse
// Create the author
ParseObject myAuthor = new ParseObject("Author");
myAuthor.put("name", "Grace Hopper");
myAuthor.put("birthDate", "December 9, 1906");
myAuthor.put("nickname", "Amazing Grace");

// Create the post
ParseObject myPost = new ParseObject("Post");
myPost.put("title", "Announcing COBOL, a New Programming Language");

// Add a relation between the Post and the Author
myPost.put("parent", myAuthor);

// This will save both myAuthor and myPost
myPost.saveInBackground();
Firebase
DatabaseReference firebaseRef = FirebaseDatabase.getInstance().getReference();
// Create the author
Map<String, String> myAuthor = new HashMap<String, String>();
myAuthor.put("name", "Grace Hopper");
myAuthor.put("birthDate", "December 9, 1906");
myAuthor.put("nickname", "Amazing Grace");

// Save the author
String myAuthorKey = "ghopper";
firebaseRef.child('authors').child(myAuthorKey).setValue(myAuthor);

// Create the post
Map<String, String> post = new HashMap<String, String>();
post.put("author", myAuthorKey);
post.put("title", "Announcing COBOL, a New Programming Language");
firebaseRef.child('posts').push().setValue(post);

다음 데이터 레이아웃은 결과입니다.

{
  // Info about the authors
  "authors": {
    "ghopper": {
      "name": "Grace Hopper",
      "date_of_birth": "December 9, 1906",
      "nickname": "Amazing Grace"
    },
    ...
  },
  // Info about the posts: the "author" fields contains the key for the author
  "posts": {
    "-JRHTHaIs-jNPLXOQivY": {
      "author": "ghopper",
      "title": "Announcing COBOL, a New Programming Language"
    }
    ...
  }
}
자세한 내용은 데이터베이스 구조화 가이드를 확인하세요.

데이터 읽기

Parse에서는 특정 Parse 객체의 ID를 사용하거나 ParseQuery로 쿼리를 실행하여 데이터를 읽습니다.

Firebase에서는 데이터베이스 참조에 비동기 리스너를 연결하여 데이터를 검색합니다. 리스너는 데이터의 초기 상태에 한 번 트리거되고 데이터가 변경되면 다시 트리거되므로 데이터가 변경되었는지 확인하기 위해 코드를 추가할 필요가 없습니다.

다음 예는 '객체' 섹션에 제시된 예를 기준으로 특정 플레이어의 점수를 검색할 수 있는 방법을 보여줍니다.

Parse
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.whereEqualTo("playerName", "Dan Stemkoski");
query.findInBackground(new FindCallback<ParseObject>() {
    public void done(List<ParseObject> scoreList, ParseException e) {
        if (e == null) {
            for (ParseObject score: scoreList) {
                Log.d("score", "Retrieved: " + Long.toString(score.getLong("score")));
            }
        } else {
            Log.d("score", "Error: " + e.getMessage());
        }
    }
});
Firebase
DatabaseReference mFirebaseRef = FirebaseDatabase.getInstance().getReference();
Query mQueryRef = mFirebaseRef.child("scores").orderByChild("playerName").equalTo("Dan Stemkoski");

// This type of listener is not one time, and you need to cancel it to stop
// receiving updates.
mQueryRef.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot snapshot, String previousChild) {
        // This will fire for each matching child node.
        GameScore score = snapshot.getValue(GameScore.class);
        Log.d("score", "Retrieved: " + Long.toString(score.getScore());
    }
});
사용할 수 있는 이벤트 리스너 유형과 데이터의 순서 지정 및 필터링 방법의 자세한 내용은 Android에서 데이터 읽기 및 쓰기 가이드를 참조하세요.

추천 마이그레이션 전략

데이터 다시 생각하기

Firebase 실시간 데이터베이스는 연결된 전체 클라이언트에서 순식간에 데이터를 동기화하도록 최적화되며 그 결과 데이터 구조는 Parse 코어 데이터와 다릅니다. 따라서 이전의 첫 번째 단계는 다음을 포함하여 데이터에서 필요한 변경사항을 고려하는 것입니다.

  • Parse 객체를 Firebase 데이터에 매핑하는 방식
  • 상위-하위 관계가 있는 경우 별도의 호출로 효율적으로 다운로드할 수 있도록 다른 경로로 데이터를 분할하는 방법

데이터 이전

Firebase에서 데이터를 구조화하는 방식을 결정한 후에는 앱이 양쪽 데이터베이스에 모두에 쓰기 작업을 해야 하는 기간을 어떻게 처리할지 계획해야 합니다. 이때 다음과 같은 옵션을 선택할 수 있습니다.

백그라운드 동기화

이 시나리오에서는 두 가지 앱 버전이 있습니다. Parse를 사용하는 이전 버전과 Firebase를 사용하는 새 버전입니다. 두 데이터베이스 사이의 동기화는 Parse에서 Firebase로 Parse Cloud Code에서 처리되며 코드에서 Firebase 변경사항을 수신하고 Parse에 변경사항을 동기화합니다. 다음은 새 버전 사용을 시작하기 전에 해야 하는 일입니다.

  • 기존 Parse 데이터를 새 Firebase 구조로 변환하고 Firebase 실시간 데이터베이스에 작성합니다.
  • 이전 클라이언트에서 Parse 데이터에서 적용한 변경사항을 Firebase 실시간 데이터베이스에 작성하기 위해 Firebase REST API를 사용하는 Parse Cloud Code 함수를 작성합니다.
  • Firebase에서 변경사항을 수신하는 코드를 작성 및 배포하고 Parse 데이터베이스에 동기화합니다.

이 시나리오에서는 이전 코드와 새 코드를 확실하게 분리하여 클라이언트를 단순하게 유지합니다. 이 시나리오의 과제는 초기 내보내기에서 대형 데이터세트를 처리하고 양방향 동기화가 무한 반복되지 않도록 하는 것입니다.

이중 작성

이 시나리오에서는 Firebase와 Parse를 둘 다 사용하는 앱의 새 버전을 작성하고 Parse Cloud Code를 사용하여 이전 클라이언트에서 발생한 변경사항을 Parse 데이터에서 Firebase 실시간 데이터베이스로 동기화합니다. 충분한 인원의 사용자가 Parse 전용 버전 앱에서 이전한 경우 이중 작성 버전에서 Parse 코드를 제거할 수 있습니다.

이 시나리오에는 서버 측 코드가 필요하지 않습니다. 단점은 액세스하지 않은 데이터는 이전되지 않는 것이고 앱의 크기가 양쪽 SDK 사용량에 따라 증가하는 것입니다.

Firebase 인증

Firebase 인증은 비밀번호 및 인기 있는 ID 제공업체(예: Google, Facebook, Twitter 등)를 사용하여 사용자를 인증할 수 있습니다. 또한 UI 라이브러리도 제공하므로 모든 플랫폼을 대상으로 앱에 전체 인증 환경을 구현하고 유지하는 데 크게 자원을 들이지 않아도 됩니다.

자세한 내용은 Firebase 인증 문서를 참조하세요.

Parse 인증과의 차이

Parse는 사용자 계정 관리에 필요한 기능을 자동으로 처리하는 ParseUser라는 특수한 사용자 클래스를 제공합니다. ParseUserParseObject의 서브클래스이므로, 사용자 데이터는 Parse 데이터에서 사용할 수 있고 기타 ParseObject 등 추가 필드를 사용하여 확장할 수 있습니다.

FirebaseUser에는 별도의 프로젝트 내 사용자 데이터베이스에 저장된 고정 기본 속성 집합(고유 ID, 기본 이메일 주소, 이름, 사진 URL)이 있습니다. 이러한 속성은 사용자가 업데이트할 수 있습니다. FirebaseUser 객체에 직접 다른 속성을 추가할 수는 없으며 대신 추가 속성을 Firebase 실시간 데이터베이스에 저장할 수 있습니다.

다음 예시는 사용자를 등록하고 전화번호 필드를 추가하는 방법을 보여줍니다.

Parse
ParseUser user = new ParseUser();
user.setUsername("my name");
user.setPassword("my pass");
user.setEmail("email@example.com");

// other fields can be set just like with ParseObject
user.put("phone", "650-253-0000");

user.signUpInBackground(new SignUpCallback() {
    public void done(ParseException e) {
        if (e == null) {
            // Hooray! Let them use the app now.
        } else {
            // Sign up didn't succeed. Look at the ParseException
            // to figure out what went wrong
        }
    }
});
Firebase
FirebaseAuth mAuth = FirebaseAuth.getInstance();

mAuth.createUserWithEmailAndPassword("email@example.com", "my pass")
    .continueWithTask(new Continuation<AuthResult, Task<Void>> {
        @Override
        public Task<Void> then(Task<AuthResult> task) {
            if (task.isSuccessful()) {
                FirebaseUser user = task.getResult().getUser();
                DatabaseReference firebaseRef = FirebaseDatabase.getInstance().getReference();
                return firebaseRef.child("users").child(user.getUid()).child("phone").setValue("650-253-0000");
            } else {
                // User creation didn't succeed. Look at the task exception
                // to figure out what went wrong
                Log.w(TAG, "signInWithEmail", task.getException());
            }
        }
    });

추천 마이그레이션 전략

계정 마이그레이션

Parse에서 Firebase로 사용자 계정을 마이그레이션하려면 사용자 데이터베이스를 JSON 또는 CSV 파일로 내보낸 후 Firebase CLI의 auth:import 명령어를 사용하여 파일을 Firebase 프로젝트로 가져옵니다.

우선 Parse 콘솔이나 자체 호스팅 데이터베이스에서 사용자 데이터베이스를 내보냅니다. 예를 들어 Parse 콘솔에서 내보낸 JSON 파일은 다음과 같습니다.

{ // Username/password user
  "bcryptPassword": "$2a$10$OBp2hxB7TaYZgKyTiY48luawlTuYAU6BqzxJfpHoJMdZmjaF4HFh6",
  "email": "user@example.com",
  "username": "testuser",
  "objectId": "abcde1234",
  ...
},
{ // Facebook user
  "authData": {
    "facebook": {
      "access_token": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
      "expiration_date": "2017-01-02T03:04:05.006Z",
      "id": "1000000000"
    }
  },
  "username": "wXyZ987654321StUv",
  "objectId": "fghij5678",
  ...
}

그런 다음 내보낸 파일의 형식을 Firebase CLI의 요건에 맞게 변환합니다. Parse 사용자의 objectId를 Firebase 사용자의 localId로 사용합니다. 또한 Parse의 bcryptPassword 값을 base64로 인코딩하여 passwordHash 필드에 사용합니다. 예를 들면 다음과 같습니다.

{
  "users": [
    {
      "localId": "abcde1234",  // Parse objectId
      "email": "user@example.com",
      "displayName": "testuser",
      "passwordHash": "JDJhJDEwJE9CcDJoeEI3VGFZWmdLeVRpWTQ4bHVhd2xUdVlBVTZCcXp4SmZwSG9KTWRabWphRjRIRmg2",
    },
    {
      "localId": "fghij5678",  // Parse objectId
      "displayName": "wXyZ987654321StUv",
      "providerUserInfo": [
        {
          "providerId": "facebook.com",
          "rawId": "1000000000",  // Facebook ID
        }
      ]
    }
  ]
}

마지막으로 bcrypt를 해시 알고리즘으로 지정하여 변환된 파일을 Firebase CLI로 가져옵니다.

firebase auth:import account_file.json --hash-algo=BCRYPT

사용자 데이터 이전

사용자 데이터가 더 있는 경우 데이터 이전 섹션에 설명된 전략을 사용하여 이러한 추가 데이터를 Firebase 실시간 데이터베이스로 이전할 수 있습니다. 계정 마이그레이션 섹션에 설명된 흐름을 사용하여 계정을 마이그레이션하는 경우 Firebase 계정이 Parse 계정과 같은 ID를 갖게 되고 사용자 ID로 입력한 모든 관계를 쉽게 마이그레이션하고 재현할 수 있습니다.

Firebase 클라우드 메시징

Firebase 클라우드 메시징(FCM)은 메시지와 알림을 무료로 안정적으로 전송할 수 있는 크로스 플랫폼 메시징 솔루션입니다. 알림 작성기는 모바일 앱 개발자를 위해 Firebase 클라우드 메시징을 기반으로 개발된 무료 서비스로서, 타겟팅된 사용자 알림을 제공합니다.

자세한 내용은 Firebase 클라우드 메시징 문서를 참조하세요.

Parse 푸시 알림과의 차이

알림에 등록된 기기에 설치된 모든 Parse 애플리케이션에는 연결된 Installation 객체가 있으며 알림 대상을 설정하는 데 필요한 모든 데이터를 여기에 저장합니다. InstallationParseUser의 서브클래스입니다. 즉, Installation 인스턴스에 원하는 데이터를 추가할 수 있습니다.

알림 작성기는 앱, 앱 버전, 기기 언어 등의 정보에 따라 사전 정의된 사용자 세그먼트를 제공합니다. Google 애널리틱스 이벤트 및 속성을 사용하면 좀 더 복잡한 사용자 세그먼트를 만들어 잠재고객을 구축할 수 있습니다. 자세한 내용은 잠재고객 도움말 가이드를 참조하세요. 이러한 타겟팅 정보는 Firebase 실시간 데이터베이스에 표시되지 않습니다.

추천 마이그레이션 전략

기기 토큰 이전

본 문서 작성 시점을 기준으로 Parse Android SDK는 알림 작성기에서 제공하는 기능과 호환되지 않는 이전 버전의 FCM 등록 토큰을 사용합니다.

앱에 FCM SDK를 추가하여 새 토큰을 얻을 수 있지만 이렇게 하면 Parse SDK에서 알림을 수신할 때 사용하는 토큰이 무효화될 수 있습니다. 이를 방지하려면 Parse SDK에서 Parse의 발신자 ID와 보내는 사람 ID를 모두 사용하도록 Parse SDK를 설정하면 됩니다. 이렇게 하면 Parse SDK에서 사용하는 토큰이 무효화되지 않지만 이 해결책은 Parse에서 프로젝트를 종료할 때 작동이 중지된다는 점에 유의해야 합니다.

FCM 주제로 채널 마이그레이션

알림을 보내는 데 Parse 채널을 사용하는 경우, 같은 게시자-구독자 모델을 제공하는 FCM 주제로 이전할 수 있습니다. Parse에서 FCM으로 전환을 처리하기 위해, Parse SDK를 사용하여 Parse 채널에서 수신을 거부하고 FCM SDK를 사용하여 해당하는 FCM 주제를 구독하는 새 버전의 앱을 작성할 수 있습니다. 이 버전의 앱에서 Parse SDK의 알림 수신을 중지해야 하며 앱의 매니페스트에서 다음을 제거합니다.

<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParsePushBroadcastReceiver"
  android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.GcmBroadcastReceiver"
  android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />

<!--
IMPORTANT: Change "com.parse.starter" to match your app's package name.
-->
<category android:name="com.parse.starter" />
</intent-filter>
</receiver>

<!--
IMPORTANT: Change "YOUR_SENDER_ID" to your GCM Sender Id.
-->
<meta-data android:name="com.parse.push.gcm_sender_id"
  android:value="id:YOUR_SENDER_ID" />;

예를 들어 사용자가 'Giants' 주제를 구독하는 경우 다음을 수행할 수 있습니다.

ParsePush.unsubscribeInBackground("Giants", new SaveCallback() {
    @Override
    public void done(ParseException e) {
        if (e == null) {
            FirebaseMessaging.getInstance().subscribeToTopic("Giants");
        } else {
            // Something went wrong unsubscribing
        }
    }
});

이 전략을 사용하면 Parse 채널과 해당하는 FCM 주제 모두에 메시지를 보내며 이전 버전과 새 버전의 사용자를 모두 지원할 수 있습니다. 충분한 인원의 사용자가 Parse 전용 버전 앱에서 이전한 경우 이 버전을 중단하고 FCM만 사용하여 메시지를 보내기 시작할 수 있습니다.

자세한 내용은 FCM 주제 문서를 참조하세요.

Firebase 원격 구성

Firebase 원격 구성은 사용자가 앱 업데이트를 다운로드할 필요 없이 앱의 동작과 모양을 변경할 수 있는 클라우드 서비스입니다. 원격 구성을 사용할 때는 앱의 동작과 디자인을 제어하는 인앱 기본값을 만듭니다. 그런 다음 나중에 Firebase Console을 사용하여 모든 앱 사용자 또는 사용자층의 특정 세그먼트에 대한 인앱 기본값을 재정의할 수 있습니다.

Firebase 원격 구성은 여러 솔루션을 테스트하려는 경우에 이전할 때 매우 유용하고 다른 제공업체에 더 많은 클라이언트를 동적으로 이동할 수 있습니다. 예를 들어 데이터에 Firebase와 Parse를 둘 다 사용하는 앱 버전이 있는 경우 임의 백분위수 규칙을 사용하여 Firebase에서 읽을 클라이언트를 결정하고 비율을 점차 늘려 볼 수 있습니다.

Firebase 원격 구성의 자세한 내용은 원격 구성 소개를 참조하세요.

Parse 구성과의 차이

Parse 구성을 사용하여 Parse Config Dashboard에서 앱에 키-값 쌍을 추가하고 클라이언트에서 ParseConfig를 가져옵니다. 가져오는 모든 ParseConfig 인스턴스는 변경할 수 없습니다. 이후에 네트워크에서 새 ParseConfig를 가져올 때 기존 ParseConfig 인스턴스는 전혀 수정하지 않지만 새 인스턴스를 만들고 getCurrentConfig()를 통해 사용할 수 있습니다.

Firebase 원격 구성을 사용하여 Firebase Console에서 재정의할 수 있는 키-값 쌍의 인앱 기본값을 만들고 규칙과 조건을 사용하여 사용자층 세그먼트마다 다른 앱 사용자 환경을 제공할 수 있습니다. Firebase 원격 구성은 앱에 키-값 쌍을 사용할 수 있게 해주는 싱글톤 클래스를 구현합니다. 처음에 싱글톤은 앱에서 정의한 기본값을 반환합니다. 언제든지 서버에서 새로운 값 집합을 앱에 손쉽게 가져올 수 있습니다. 새 집합을 가져온 후에 새 값을 앱에 사용할 수 있도록 활성화할 시기를 선택할 수 있습니다.

추천 마이그레이션 전략

Parse 구성의 키-값 쌍을 Firebase 콘솔로 복사하여 Firebase 원격 구성으로 이전한 다음, Firebase 원격 구성을 사용하는 앱의 새 버전을 배포할 수 있습니다.

Parse 구성과 Firebase 원격 구성을 둘 다 실험하려는 경우 충분한 인원의 사용자가 Parse 전용 버전에서 이전할 때까지 두 SDK를 사용하는 새 버전의 앱을 배포할 수 있습니다.

코드 비교

Parse

ParseConfig.getInBackground(new ConfigCallback() {
    @Override
    public void done(ParseConfig config, ParseException e) {
        if (e == null) {
            Log.d("TAG", "Yay! Config was fetched from the server.");
        } else {
            Log.e("TAG", "Failed to fetch. Using Cached Config.");
            config = ParseConfig.getCurrentConfig();
        }

        // Get the message from config or fallback to default value
        String welcomeMessage = config.getString("welcomeMessage", "Welcome!");
    }
});

Firebase

mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
// Set defaults from an XML resource file stored in res/xml
mFirebaseRemoteConfig.setDefaults(R.xml.remote_config_defaults);

mFirebaseRemoteConfig.fetch()
    .addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            Log.d("TAG", "Yay! Config was fetched from the server.");
            // Once the config is successfully fetched it must be activated before newly fetched
            // values are returned.
            mFirebaseRemoteConfig.activateFetched();
        }
    })
    .addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception exception) {
            Log.e("TAG", "Failed to fetch. Using last fetched or default.");
        }
    })

// ...

// When this is called, the value of the latest fetched and activated config is returned;
// if there's none, the default value is returned.
String welcomeMessage = mFirebaseRemoteConfig.getString("welcomeMessage");