데이터 저장

시작하기 전에

Firebase 실시간 데이터베이스를 사용하려면 우선 Firebase 프로젝트를 만들고 Unity 프로젝트에 Firebase Unity SDK 패키지를 추가해야 합니다.

설정:

기본 요건

Android

iOS

  • Unity 5.0 이상
  • Xcode 8.0 이상

Unity 프로젝트를 준비하지 않았다면 빠른 시작 샘플 중 하나를 다운로드하여 특정 Firebase 기능을 시험해 볼 수 있습니다. 빠른 시작을 사용한다면 프로젝트 설정에서 번들 식별자를 확인해야 합니다. 다음 단계에서 이 식별자가 필요합니다.

Firebase 콘솔에서 앱 설정

앱에 Firebase를 추가하려면 Firebase 프로젝트 및 앱의 Firebase 구성 파일이 필요합니다.

Firebase 프로젝트를 만드는 방법은 다음과 같습니다.

  1. Firebase 콘솔로 이동합니다.

  2. 프로젝트 추가를 클릭한 다음, 프로젝트 이름을 선택하거나 입력합니다.

    • 앱에 연결된 기존 Google 프로젝트가 있으면 프로젝트 이름 드롭다운 메뉴에서 프로젝트를 선택합니다.
    • 기존 Google 프로젝트가 없으면 새 프로젝트 이름을 입력합니다.
  3. (선택사항) 프로젝트 ID를 수정합니다.

    Firebase는 Firebase 프로젝트에 자동으로 고유한 ID를 할당합니다. 이 식별자는 공개적으로 표시되는 Firebase 서비스에 나타납니다. 예를 들면 다음과 같습니다.

    • 기본 데이터베이스 URL — your-project-id.firebaseio.com
    • 기본 호스팅 하위 도메인 — your-project-id.firebaseapp.com
  4. 나머지 설정 단계를 따른 다음 프로젝트 만들기(또는 기존 Google 프로젝트를 사용하는 경우 Firebase 추가)를 클릭합니다.

Firebase에서 Firebase 프로젝트용 리소스를 자동으로 프로비저닝합니다. 이 프로세스는 일반적으로 몇 분 정도 걸립니다. 프로세스가 완료되면 Firebase 콘솔에서 Firebase 프로젝트의 개요 페이지로 이동됩니다.

Android

  1. Android 앱에 Firebase 추가를 클릭하고 설정 단계를 따릅니다. 기존 Google 프로젝트를 가져오면 이 단계가 자동으로 이루어지므로 구성 파일만 다운로드하면 됩니다.
  2. 메시지가 표시되면 앱의 패키지 이름을 입력합니다. 앱에서 사용하는 패키지 이름을 입력해야 합니다. 이 설정은 Firebase 프로젝트에 앱을 추가할 때만 가능합니다.
  3. 이 과정에서 google-services.json 파일을 다운로드하게 됩니다. 언제든지 다시 이 파일을 다운로드할 수 있습니다.
  4. 초기화 코드를 추가한 후 앱을 실행하여 Firebase를 성공적으로 설치했다는 확인을 Firebase 콘솔에 보냅니다.

iOS

  1. iOS 앱에 Firebase 추가를 클릭하고 설정 단계를 따릅니다. 기존 Google 프로젝트를 가져오면 이 단계가 자동으로 이루어지므로 구성 파일만 다운로드하면 됩니다.
  2. 메시지가 표시되면 앱의 번들 ID를 입력합니다. 앱에서 사용하는 번들 ID를 입력해야 합니다. 이 설정은 Firebase 프로젝트에 앱을 추가할 때만 가능합니다.
  3. 이 과정에서 GoogleService-Info.plist 파일을 다운로드하게 됩니다. 언제든지 다시 이 파일을 다운로드할 수 있습니다.
  4. 초기화 코드를 추가한 후 앱을 실행하여 Firebase를 성공적으로 설치했다는 확인을 Firebase 콘솔에 보냅니다.
  5. Firebase 콘솔에서 다운로드한 GoogleService-Info.plist를 드래그하여 Unity 프로젝트의 원하는 폴더에 넣습니다.

앱에 Firebase Unity SDK 추가

  1. Firebase Unity SDK를 다운로드합니다.
  2. 애셋 > 패키지 가져오기 > 맞춤 패키지 메뉴 항목을 선택합니다.
  3. 사용하는 Unity 버전과 일치하는 디렉토리에서 FirebaseDatabase.unitypackage 를 가져옵니다.
    • Unity 5.x 이전 버전에서는 .NET 3.x 프레임워크를 사용하므로 dotnet3/FirebaseDatabase.unitypackage 패키지를 가져와야 합니다.
    • Unity 2017.x 이상 버전에서는 .NET 4.x 프레임워크를 사용할 수 있습니다. 프로젝트가 .NET 4.x를 사용하도록 구성된 경우 dotnet4/FirebaseDatabase.unitypackage 패키지를 가져옵니다.
  4. Unity 패키지 가져오기 창이 나타나면 가져오기 버튼을 클릭합니다.

SDK 초기화

Google Play 서비스가 최신 상태여야 Android의 Firebase Unity SDK를 사용할 수 있습니다. Firebase Unity SDK에서 다른 메소드를 호출하기 전에 애플리케이션의 시작 부분에 다음 코드를 추가하여 Google Play 서비스를 확인하고 필요한 경우 SDK에 필요한 버전으로 업데이트해야 합니다.

Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
  var dependencyStatus = task.Result;
  if (dependencyStatus == Firebase.DependencyStatus.Available) {
    // Create and hold a reference to your FirebaseApp, i.e.
    //   app = Firebase.FirebaseApp.DefaultInstance;
    // where app is a Firebase.FirebaseApp property of your application class.

    // Set a flag here indicating that Firebase is ready to use by your
    // application.
  } else {
    UnityEngine.Debug.LogError(System.String.Format(
      "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
    // Firebase Unity SDK is not safe to use here.
  }
});

앱 빌드

Android

  1. File(파일) > Build Settings(빌드 설정) 메뉴 옵션을 선택합니다.
  2. Platform(플랫폼) 목록에서 Android를 선택합니다.
  3. Switch Platform(플랫폼 전환)을 클릭하여 타겟 플랫폼으로 Android를 선택합니다.
  4. Unity 상태 표시줄 오른쪽 하단의 스피너(컴파일) 아이콘이 멈추기를 기다립니다.
  5. Build and Run(빌드 및 실행)을 클릭합니다.

iOS

  1. File(파일) > Build Settings(빌드 설정) 메뉴 옵션을 선택합니다.
  2. Platform(플랫폼) 목록에서 iOS를 선택합니다.
  3. Switch Platform(플랫폼 전환)을 클릭하여 타겟 플랫폼으로 iOS를 선택합니다.
  4. Unity 상태 표시줄 오른쪽 하단의 스피너(컴파일) 아이콘이 멈추기를 기다립니다.
  5. Build and Run(빌드 및 실행)을 클릭합니다.

데이터 저장

Firebase 실시간 데이터베이스에 데이터를 쓰는 메소드는 다음과 같이 5가지입니다.

메소드 일반적인 용도
SetValueAsync() 정의된 경로(예: users/<user-id>/<username>)에 데이터를 쓰거나 대체합니다.
SetRawJsonValueAsync() 원시 JSON(예: users/<user-id>/<username>)으로 데이터를 쓰거나 대체합니다.
Push() 데이터 목록에 추가합니다. Push()를 호출할 때마다 Firebase에서 고유 식별자로도 사용할 수 있는 고유 키(예: user-scores/<user-id>/<unique-score-id>)를 생성합니다.
UpdateChildrenAsync() 정의된 경로에서 모든 데이터를 대체하지 않고 일부 키를 업데이트합니다.
RunTransaction() 동시 업데이트에 의해 손상될 수 있는 복잡한 데이터를 업데이트합니다.

DatabaseReference 가져오기

데이터베이스에 데이터를 쓰려면 DatabaseReference의 인스턴스가 필요합니다.

using Firebase;
using Firebase.Database;
using Firebase.Unity.Editor;

public class MyScript: MonoBehaviour {
  void Start() {
    // Set up the Editor before calling into the realtime database.
    FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://YOUR-FIREBASE-APP.firebaseio.com/");

    // Get the root reference location of the database.
    DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
  }
}

참조 위치에서 데이터 쓰기, 업데이트 또는 삭제

기본 쓰기 작업

기본 쓰기 작업의 경우 SetValueAsync()를 사용하여 지정된 참조에 데이터를 저장하고 기존 경로의 모든 데이터를 대체할 수 있습니다. 이 메소드를 통해 사용 가능한 JSON 유형에 해당하는 다음과 같은 유형을 전달할 수 있습니다.

  • string
  • long
  • double
  • bool
  • Dictionary<string, Object>
  • List<Object>

형식이 지정된 C# 객체를 사용하는 경우, 기본 제공된 JsonUtility.ToJson()을 사용하여 객체를 원시 JSON으로 변환하고 SetRawJsonValueAsync()를 호출할 수 있습니다. 예를 들어 다음과 같은 User 클래스가 있다고 가정해 보겠습니다.

public class User {
    public string username;
    public string email;

    public User() {
    }

    public User(string username, string email) {
        this.username = username;
        this.email = email;
    }
}

SetRawJsonValueAsync()로 다음과 같이 사용자를 추가할 수 있습니다.

private void writeNewUser(string userId, string name, string email) {
    User user = new User(name, email);
    string json = JsonUtility.ToJson(user);

    mDatabaseRef.Child("users").Child(userId).SetRawJsonValueAsync(json);
}

이와 같이 SetValueAsync() 또는 SetRawJsonValueAsync()를 사용하면 하위 노드를 포함하여 지정된 위치의 데이터를 덮어쓰게 됩니다. 그러나 전체 개체를 다시 쓰지 않고도 하위 항목을 업데이트하는 방법이 있습니다. 사용자가 프로필을 업데이트하도록 허용하려면 다음과 같이 사용자 이름을 업데이트할 수 있습니다.

mDatabaseRef.Child("users").Child(userId).Child("username").SetValueAsync(name);

데이터 목록에 추가

멀티 사용자 애플리케이션에서 Push() 메소드를 사용하여 목록에 데이터를 추가합니다. Push() 메소드는 지정된 Firebase 참조에 새 하위 항목이 추가될 때마다 고유 키를 생성합니다. 목록의 새 요소마다 이러한 자동 생성 키를 사용하면 여러 클라이언트에서 쓰기 충돌 없이 동시에 같은 위치에 하위 항목을 추가할 수 있습니다. Push()가 생성하는 고유 키는 타임스탬프에 기초하므로 목록 항목은 시간순으로 자동 정렬됩니다.

Push() 메소드가 반환하는 새 데이터에 대한 참조를 사용하여 하위 항목의 자동 생성 키 값을 가져오거나 하위 데이터를 설정할 수 있습니다. Push() 참조에 대해 Key를 호출하면 자동 생성 키 값이 반환됩니다.

특정 필드 업데이트

다른 하위 노드를 덮어쓰지 않고 특정 하위 노드에 동시에 쓰려면 UpdateChildrenAsync() 메소드를 사용합니다.

UpdateChildrenAsync() 호출 시 키의 경로를 지정하여 하위 수준 값을 업데이트할 수 있습니다. 확장성을 위해 여러 위치에 데이터가 저장된 경우 데이터 팬아웃을 사용하여 해당 데이터의 모든 인스턴스를 업데이트할 수 있습니다. 예를 들어 게임은 다음과 같이 LeaderboardEntry 클래스를 사용할 수 있습니다.

public class LeaderboardEntry {
    public string uid;
    public int score = 0;

    public LeaderboardEntry() {
    }

    public LeaderboardEntry(string uid, int score) {
        this.uid = uid;
        this.score = score;
    }

    public Dictionary&ltstring, Object&gt ToDictionary() {
        Dictionary&ltstring, Object&gt result = new Dictionary&ltstring, Object&gt();
        result["uid"] = uid;
        result["score"] = score;

        return result;
    }
}

LeaderboardEntry를 만들고 최근 점수 피드 및 사용자의 점수 목록을 동시에 업데이트하려는 경우 게임은 다음과 같은 코드를 사용합니다.

private void WriteNewScore(string userId, int score) {
    // Create new entry at /user-scores/$userid/$scoreid and at
    // /leaderboard/$scoreid simultaneously
    string key = mDatabase.Child("scores").Push().Key;
    LeaderBoardEntry entry = new LeaderBoardEntry(userId, score);
    Dictionary&ltstring, Object&gt entryValues = entry.ToDictionary();

    Dictionary&ltstring, Object&gt childUpdates = new Dictionary&ltstring, Object&gt();
    childUpdates["/scores/" + key] = entryValues;
    childUpdates["/user-scores/" + userId + "/" + key] = entryValues;

    mDatabase.UpdateChildrenAsync(childUpdates);
}

이 예에서는 Push()를 사용하여 모든 사용자의 항목을 포함하는 노드(/scores/$key)에 항목을 만드는 동시에 Key로 키를 검색합니다. 그런 다음 이 키로 사용자의 점수 목록(/user-scores/$userid/$key)에 두 번째 항목을 만듭니다.

이러한 경로를 사용하면 이 예에서 두 위치에 새 항목을 만든 것처럼 UpdateChildrenAsync()를 한 번만 호출하여 JSON 트리의 여러 위치에 동시에 업데이트할 수 있습니다. 이러한 동시 업데이트는 원자적 성격을 갖습니다. 즉, 모든 업데이트가 한꺼번에 성공하거나 실패합니다.

데이터 삭제

데이터를 삭제하는 가장 간단한 방법은 해당 데이터 위치의 참조에 대해 RemoveValue()를 호출하는 것입니다.

SetValueAsync() 또는 UpdateChildrenAsync() 등의 다른 쓰기 작업에 null 값을 지정하여 삭제할 수도 있습니다. UpdateChildrenAsync()에 이 방법을 사용하면 API를 한 번 호출하여 여러 하위 항목을 삭제할 수 있습니다.

데이터가 커밋되는 시점 알기

Firebase 실시간 데이터베이스 서버에 데이터가 커밋되는 시점을 파악하려면 지속 개체를 추가합니다. SetValueAsync()UpdateChildrenAsync()는 작업 완료 시점을 알려주는 Task를 반환합니다. 이유를 불문하고 호출에 실패하면 IsFaulted 작업이 true가 되고 Exception 속성은 실패 이유를 지정합니다.

데이터를 트랜잭션으로 저장

증가 카운터와 같이 동시 수정으로 인해 손상될 수 있는 데이터를 다루는 경우 트랜잭션 작업을 사용할 수 있습니다. 이 작업에 Func를 부여하면 됩니다. 이 업데이트 Func는 데이터의 현재 상태를 인수로 취하고 새로 기록하려는 상태를 반환합니다. 새 값이 기록되기 전에 다른 클라이언트에서 해당 위치에 기록하면 업데이트 함수가 새로운 현재 값으로 다시 호출되고 쓰기가 다시 시도됩니다.

예를 들어 게임에서 사용자가 최고 점수 5개로 리더보드를 업데이트하도록 허용할 수 있습니다.

private void AddScoreToLeaders(string email,
                               long score,
                               DatabaseReference leaderBoardRef) {

    leaderBoardRef.RunTransaction(mutableData =&gt {
      List&ltobject&gt leaders = mutableData.Value as List&ltobject>

      if (leaders == null) {
        leaders = new List&ltobject&gt();
      } else if (mutableData.ChildrenCount &gt= MaxScores) {
        long minScore = long.MaxValue;
        object minVal = null;
        foreach (var child in leaders) {
          if (!(child is Dictionary&ltstring, object&gt)) continue;
          long childScore = (long)
                      ((Dictionary&ltstring, object&gt)child)["score"];
          if (childScore &lt minScore) {
            minScore = childScore;
            minVal = child;
          }
        }
        if (minScore &gt score) {
          // The new score is lower than the existing 5 scores, abort.
          return TransactionResult.Abort();
        }

        // Remove the lowest score.
        leaders.Remove(minVal);
      }

      // Add the new high score.
      Dictionary&ltstring, object&gt newScoreMap =
                       new Dictionary&ltstring, object&gt();
      newScoreMap["score"] = score;
      newScoreMap["email"] = email;
      leaders.Add(newScoreMap);
      mutableData.Value = leaders;
      return TransactionResult.Success(mutableData);
    });
}

트랜잭션을 사용하면 여러 사용자가 동시에 점수를 기록하거나 클라이언트 데이터의 동기화가 어긋나도 리더보드가 잘못되지 않습니다. 트랜잭션이 거부되면 서버에서 현재 값을 클라이언트에 반환하며, 클라이언트는 업데이트된 값으로 트랜잭션을 다시 실행합니다. 트랜잭션이 수락되거나 시도가 일정 횟수를 초과할 때까지 이 과정이 반복됩니다.

오프라인으로 데이터 쓰기

클라이언트의 네트워크 연결이 끊겨도 앱은 계속 정상적으로 작동합니다.

Firebase 데이터베이스에 연결된 모든 클라이언트는 자체적으로 활성 데이터의 내부 버전을 유지합니다. 데이터를 쓰면 우선 로컬 버전에 기록됩니다. 그런 다음 Firebase 클라이언트가 해당 데이터를 원격 데이터베이스 서버 및 다른 클라이언트와 '최선을 다해' 동기화합니다.

이와 같이 데이터베이스에 대한 모든 쓰기 작업은 로컬 이벤트를 즉시 발생시키며, 그 이후에 서버에 데이터가 기록됩니다. 따라서 앱은 네트워크 지연 또는 연결 여부에 관계없이 응답성을 유지합니다.

네트워크에 다시 연결되면 앱에서 적절한 이벤트 세트를 수신하여 클라이언트와 현재 서버 상태를 동기화하므로 맞춤 코드를 별도로 작성할 필요가 없습니다.

다음 단계

다음에 대한 의견 보내기...

도움이 필요하시나요? 지원 페이지를 방문하세요.