Cloud Firestore에서 접속 상태 구현

개발하는 앱 유형에 따라 어떠한 사용자 또는 기기가 현재 온라인 상태인지를 확인하면 유용할 수 있습니다. 이러한 기능을 '접속 상태' 감지라고 합니다.

예를 들어 소셜 네트워크와 같은 앱을 빌드하거나 여러 IoT 기기를 배포할 경우 이 정보를 사용하여 채팅 가능한 온라인 상태인 친구 목록을 표시하거나 IoT 기기를 '최종 접속 시간' 순으로 정렬할 수 있습니다.

Cloud Firestore에서 기본적으로 인기척을 지원하지 않지만 다음 방법을 사용할 수 있습니다. 다른 Firebase 제품을 활용하여 접속 상태 시스템 구축

솔루션: Cloud Functions 및 실시간 데이터베이스

Cloud Firestore를 Firebase 실시간 데이터베이스의 네이티브에 연결 Cloud Functions를 사용하세요

실시간 데이터베이스를 사용하여 연결 상태를 보고한 후 Cloud Functions를 사용하여 다음을 수행합니다. 이 데이터를 Cloud Firestore에 미러링합니다.

실시간 데이터베이스에서 접속 상태 사용

먼저 실시간 데이터베이스의 기본 접속 상태 시스템을 살펴보겠습니다.

// Fetch the current user's ID from Firebase Authentication.
var uid = firebase.auth().currentUser.uid;

// Create a reference to this user's specific status node.
// This is where we will store data about being online/offline.
var userStatusDatabaseRef = firebase.database().ref('/status/' + uid);

// We'll create two constants which we will write to 
// the Realtime database when this device is offline
// or online.
var isOfflineForDatabase = {
    state: 'offline',
    last_changed: firebase.database.ServerValue.TIMESTAMP,
};

var isOnlineForDatabase = {
    state: 'online',
    last_changed: firebase.database.ServerValue.TIMESTAMP,
};

// Create a reference to the special '.info/connected' path in 
// Realtime Database. This path returns `true` when connected
// and `false` when disconnected.
firebase.database().ref('.info/connected').on('value', function(snapshot) {
    // If we're not currently connected, don't do anything.
    if (snapshot.val() == false) {
        return;
    };

    // If we are currently connected, then use the 'onDisconnect()' 
    // method to add a set which will only trigger once this 
    // client has disconnected by closing the app, 
    // losing internet, or any other means.
    userStatusDatabaseRef.onDisconnect().set(isOfflineForDatabase).then(function() {
        // The promise returned from .onDisconnect().set() will
        // resolve as soon as the server acknowledges the onDisconnect() 
        // request, NOT once we've actually disconnected:
        // https://firebase.google.com/docs/reference/js/firebase.database.OnDisconnect

        // We can now safely set ourselves as 'online' knowing that the
        // server will mark us as offline once we lose connection.
        userStatusDatabaseRef.set(isOnlineForDatabase);
    });
});

이 예시는 완전한 실시간 데이터베이스 접속 상태 시스템으로 여러 연결 해제, 비정상 종료 등을 처리합니다.

Cloud Firestore에 연결 중

Cloud Firestore에서 유사한 솔루션을 구현하려면 다음을 사용하세요. 실시간 데이터베이스 코드로 처리하고 Cloud Functions를 사용하여 실시간 데이터베이스 및 Cloud Firestore 동기화됨

프로젝트에 실시간 데이터베이스를 아직 추가하지 않았다면 지금 추가하고 위의 접속 상태 솔루션을 포함합니다.

다음으로 현재 상태를 Cloud Firestore에 동기화합니다. 다음과 같은 메서드를 지원합니다.

  1. 로컬에서 오프라인 기기의 Cloud Firestore 캐시에 저장 오프라인 상태임을 알 수 있습니다.
  2. 전역적으로 Cloud 함수를 사용하여 Cloud Firestore님은 이 기기가 오프라인 상태임을 알고 있습니다.

Cloud Firestore의 로컬 캐시 업데이트

첫 번째 문제인 Cloud Firestore의 로컬 캐시

// ...
var userStatusFirestoreRef = firebase.firestore().doc('/status/' + uid);

// Firestore uses a different server timestamp value, so we'll 
// create two more constants for Firestore state.
var isOfflineForFirestore = {
    state: 'offline',
    last_changed: firebase.firestore.FieldValue.serverTimestamp(),
};

var isOnlineForFirestore = {
    state: 'online',
    last_changed: firebase.firestore.FieldValue.serverTimestamp(),
};

firebase.database().ref('.info/connected').on('value', function(snapshot) {
    if (snapshot.val() == false) {
        // Instead of simply returning, we'll also set Firestore's state
        // to 'offline'. This ensures that our Firestore cache is aware
        // of the switch to 'offline.'
        userStatusFirestoreRef.set(isOfflineForFirestore);
        return;
    };

    userStatusDatabaseRef.onDisconnect().set(isOfflineForDatabase).then(function() {
        userStatusDatabaseRef.set(isOnlineForDatabase);

        // We'll also add Firestore set here for when we come online.
        userStatusFirestoreRef.set(isOnlineForFirestore);
    });
});

이러한 변경을 통해 이제 로컬 Cloud Firestore 상태가 항상 기기의 온라인/오프라인 상태를 반영합니다. 즉, 사용자는 /status/{uid} 문서를 만들고 이 데이터를 사용하여 연결을 반영하도록 UI를 변경합니다. 있습니다.

userStatusFirestoreRef.onSnapshot(function(doc) {
    var isOnline = doc.data().state == 'online';
    // ... use isOnline
});

전역적으로 Cloud Firestore 업데이트 중

애플리케이션이 온라인 상태를 올바르게 보고하지만 이 상태는 '오프라인'으로 인해 다른 Cloud Firestore 앱에서는 아직 정확하지 않습니다. 상태 쓰기는 로컬에서만 이루어지며 연결이 복원될 때 동기화되지 않습니다. 반론할 대상 status/{uid} 경로를 실시간으로 감시하는 Cloud 함수를 사용합니다. 데이터베이스. 실시간 데이터베이스 값이 변경되면 값이 Cloud Firestore에 동기화됩니다. 모든 사용자의 있는지 확인합니다.

Node.js

firebase.firestore().collection('status')
    .where('state', '==', 'online')
    .onSnapshot(function(snapshot) {
        snapshot.docChanges().forEach(function(change) {
            if (change.type === 'added') {
                var msg = 'User ' + change.doc.id + ' is online.';
                console.log(msg);
                // ...
            }
            if (change.type === 'removed') {
                var msg = 'User ' + change.doc.id + ' is offline.';
                console.log(msg);
                // ...
            }
        });
    });

이 함수를 배포하면 완전한 접속 상태 시스템이 실행됩니다. Cloud Firestore를 사용합니다. 다음은 PII를 사용하는 사용자를 모니터링하는 where() 쿼리를 사용하여 온라인 또는 오프라인으로 전환할 수 있습니다.

firebase.firestore().collection('status')
    .where('state', '==', 'online')
    .onSnapshot(function(snapshot) {
        snapshot.docChanges().forEach(function(change) {
            if (change.type === 'added') {
                var msg = 'User ' + change.doc.id + ' is online.';
                console.log(msg);
                // ...
            }
            if (change.type === 'removed') {
                var msg = 'User ' + change.doc.id + ' is offline.';
                console.log(msg);
                // ...
            }
        });
    });

제한사항

실시간 데이터베이스를 사용하여 Cloud Firestore 앱에 접속 상태를 추가하는 작업은 다음과 같습니다. 확장 가능하고 효과적이지만 몇 가지 제한사항이 있습니다.

  • 디바운싱 - Cloud Firestore인 경우 이 솔루션은 여러 개의 있습니다. 이러한 변경사항으로 인해 이벤트가 너무 많이 트리거되는 경우 수동으로 Cloud Firestore 이벤트를 디바운싱합니다.
  • 연결 - 이 구현은 Realtime에 대한 연결을 측정합니다. Cloud Firestore가 아닌 데이터베이스입니다. 각 데이터베이스에 대한 연결 상태가 동일하지 않으면 이 솔루션은 정확하지 않은 접속 상태를 보고할 수 있습니다.
  • Android - Android에서 실시간 데이터베이스는 비활성 상태가 60초간 지속되면 백엔드에서 연결을 끊습니다. 비활성 상태란 열린 상태의 리스너나 대기 중인 작업이 없다는 의미입니다. 연결을 열린 상태로 유지하려면 값 이벤트 리스너를 .info/connected 외의 경로에 추가하는 것이 좋습니다. 예를 들어 각 세션 시작 시 FirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced()를 실행하는 방법이 있습니다. 자세한 내용은 연결 상태 감지를 참조하세요.