Firebase Summit에서 발표된 모든 내용을 살펴보고 Firebase로 앱을 빠르게 개발하고 안심하고 앱을 실행하는 방법을 알아보세요. 자세히 알아보기

Cloud Firestore 보안 규칙 작성 조건

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

이 가이드는 보안 규칙 구조화 가이드를 기반으로 Cloud Firestore 보안 규칙에 조건을 추가하는 방법을 보여줍니다. Cloud Firestore 보안 규칙의 기본 사항에 익숙하지 않은 경우 시작 가이드를 참조하세요.

Cloud Firestore 보안 규칙의 기본 구성 요소는 조건입니다. 조건은 특정 작업을 허용할지 또는 거부할지 여부를 결정하는 부울 식입니다. 보안 규칙을 사용하여 사용자 인증을 확인하고 들어오는 데이터의 유효성을 검사하거나 데이터베이스의 다른 부분에 액세스하는 조건을 작성하십시오.

입증

가장 일반적인 보안 규칙 패턴 중 하나는 사용자의 인증 상태에 따라 액세스를 제어하는 ​​것입니다. 예를 들어 앱에서 로그인한 사용자만 데이터 쓰기를 허용할 수 있습니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}

또 다른 일반적인 패턴은 사용자가 자신의 데이터만 읽고 쓸 수 있도록 하는 것입니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}

앱에서 Firebase 인증 또는 Google Cloud Identity Platform 을 사용하는 경우 request.auth 변수에는 데이터를 요청하는 클라이언트에 대한 인증 정보가 포함됩니다. request.auth 에 대한 자세한 내용 은 참조 문서 를 참조하십시오.

데이터 유효성 검사

많은 앱은 액세스 제어 정보를 데이터베이스 문서의 필드로 저장합니다. Cloud Firestore 보안 규칙은 문서 데이터를 기반으로 동적으로 액세스를 허용하거나 거부할 수 있습니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

resource 변수는 요청된 문서를 참조하고 resource.data 는 문서에 저장된 모든 필드 및 값의 맵입니다. resource 변수에 대한 자세한 내용 은 참조 문서 를 참조하십시오.

데이터를 쓸 때 들어오는 데이터를 기존 데이터와 비교할 수 있습니다. 이 경우 규칙 세트가 보류 중인 쓰기를 허용하면 request.resource 변수에 문서의 향후 상태가 포함됩니다. 문서 필드의 하위 집합만 수정하는 update 작업의 경우 request.resource 변수에는 작업 후 보류 중인 문서 상태가 포함됩니다. request.resource 의 필드 값을 확인하여 원치 않거나 일관되지 않은 데이터 업데이트를 방지할 수 있습니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

다른 문서에 액세스

get()exists() 함수를 사용하여 보안 규칙은 데이터베이스의 다른 문서에 대해 들어오는 요청을 평가할 수 있습니다. get()exists() 함수는 모두 완전히 지정된 문서 경로를 예상합니다. 변수를 사용하여 get()exists() 에 대한 경로를 구성할 때 $(variable) 구문을 사용하여 변수를 명시적으로 이스케이프 처리해야 합니다.

아래 예에서 database 변수는 match 문 match /databases/{database}/documents 에 의해 캡처되고 경로를 형성하는 데 사용됩니다.

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}

쓰기의 경우 getAfter() 함수를 사용하여 트랜잭션 또는 일괄 쓰기가 완료된 후 트랜잭션 또는 일괄 커밋되기 전에 문서의 상태에 액세스할 수 있습니다. get() 과 마찬가지로 getAfter() 함수는 완전히 지정된 문서 경로를 사용합니다. getAfter() 를 사용하여 트랜잭션 또는 배치로 함께 발생해야 하는 쓰기 세트를 정의할 수 있습니다.

액세스 통화 제한

규칙 집합 평가당 문서 액세스 호출에는 제한이 있습니다.

  • 단일 문서 요청 및 쿼리 요청의 경우 10입니다.
  • 다중 문서 읽기, 트랜잭션 및 일괄 쓰기의 경우 20입니다. 이전 제한인 10도 각 작업에 적용됩니다.

    예를 들어 3개의 쓰기 작업으로 일괄 쓰기 요청을 생성하고 보안 규칙이 2개의 문서 액세스 호출을 사용하여 각 쓰기의 유효성을 검사한다고 가정합니다. 이 경우 각 쓰기는 10개의 액세스 호출 중 2개를 사용하고 일괄 쓰기 요청은 20개의 액세스 호출 중 6개를 사용합니다.

한도를 초과하면 권한 거부 오류가 발생합니다. 일부 문서 액세스 호출은 캐시될 수 있으며 캐시된 호출은 제한에 포함되지 않습니다.

이러한 제한이 트랜잭션 및 일괄 쓰기에 미치는 영향에 대한 자세한 설명은 원자적 작업 보안 가이드를 참조하세요.

액세스 통화 및 가격

이러한 기능을 사용하면 데이터베이스에서 읽기 작업이 실행됩니다. 즉, 규칙에서 요청을 거부하더라도 문서 읽기에 대한 비용이 청구됩니다. 보다 구체적인 청구 정보는 Cloud Firestore 가격 책정 을 참조하세요.

맞춤 기능

보안 규칙이 더 복잡해짐에 따라 규칙 세트 전체에서 재사용할 수 있는 함수에서 조건 세트를 래핑할 수 있습니다. 보안 규칙은 사용자 지정 기능을 지원합니다. 사용자 지정 함수의 구문은 JavaScript와 약간 비슷하지만 보안 규칙 함수는 몇 가지 중요한 제한 사항이 있는 도메인별 언어로 작성됩니다.

  • 함수는 단일 return 문만 포함할 수 있습니다. 추가 논리를 포함할 수 없습니다. 예를 들어 루프를 실행하거나 외부 서비스를 호출할 수 없습니다.
  • 함수는 정의된 범위에서 함수 및 변수에 자동으로 액세스할 수 있습니다. 예를 들어 service cloud.firestore 범위 내에서 정의된 함수는 resource 변수와 get()exists() 같은 기본 제공 함수에 액세스할 수 있습니다.
  • 함수는 다른 함수를 호출할 수 있지만 재귀할 수는 없습니다. 총 호출 스택 깊이는 10으로 제한됩니다.
  • 규칙 버전 v2 에서 함수는 let 키워드를 사용하여 변수를 정의할 수 있습니다. 함수는 최대 10개의 let 바인딩을 가질 수 있지만 return 문으로 끝나야 합니다.

함수는 function 키워드로 정의되며 0개 이상의 인수를 사용합니다. 예를 들어 위의 예에서 사용된 두 가지 유형의 조건을 단일 함수로 결합할 수 있습니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }

    match /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

보안 규칙에서 기능을 사용하면 규칙의 복잡성이 증가함에 따라 유지 관리가 더 쉬워집니다.

규칙은 필터가 아닙니다.

데이터를 보호하고 쿼리 작성을 시작한 후에는 보안 규칙이 필터가 아님을 명심하십시오. 컬렉션의 모든 문서에 대한 쿼리를 작성할 수 없으며 Cloud Firestore가 현재 클라이언트에 액세스 권한이 있는 문서만 반환할 것으로 예상할 수 없습니다.

예를 들어 다음 보안 규칙을 따르십시오.

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

거부됨 : 이 규칙은 visibilitypublic 되지 않은 문서를 결과 집합에 포함할 수 있기 때문에 다음 쿼리를 거부합니다.

편물
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

Allowed : 이 규칙은 where("visibility", "==", "public") 절이 결과 집합이 규칙의 조건을 충족함을 보장하기 때문에 다음 쿼리를 허용합니다.

편물
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

Cloud Firestore 보안 규칙은 잠재적 결과에 대해 각 쿼리를 평가하고 클라이언트가 읽을 수 있는 권한이 없는 문서를 반환할 수 있는 경우 요청에 실패합니다. 쿼리는 보안 규칙에서 설정한 제약 조건을 따라야 합니다. 보안 규칙 및 쿼리에 대한 자세한 내용은 안전한 데이터 쿼리를 참조하세요.

다음 단계