보안 규칙 구조화

Cloud Firestore 보안 규칙을 통해 데이터베이스의 문서 및 컬렉션에 대한 액세스를 제어할 수 있습니다. 유연한 규칙 구문을 사용하면 전체 데이터베이스에 대한 모든 쓰기 작업부터 특정 문서에 대한 작업까지 어떠한 상황에 맞는 규칙이라도 작성할 수 있습니다.

이 가이드에서는 보안 규칙의 기본적인 구문과 구조를 설명합니다. 이 구문과 보안 규칙 조건을 결합하면 완전한 규칙 세트가 만들어집니다.

서비스 및 데이터베이스 선언

Cloud Firestore 보안 규칙은 항상 다음 선언으로 시작됩니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

service cloud.firestore 선언은 규칙의 범위를 Cloud Firestore로 지정하여 Cloud Firestore 보안 규칙과 다른 제품(예: Cloud Storage)에 대한 규칙 간의 충돌을 방지합니다.

match /databases/{database}/documents 선언은 규칙이 프로젝트의 모든 Cloud Firestore 데이터베이스와 일치하도록 지정합니다. 현재 각 프로젝트에는 (default)라는 데이터베이스 하나만 있습니다.

읽기/쓰기 기본 규칙

기본 규칙은 문서 경로를 지정하는 match 명령문과 지정한 데이터를 읽도록 허용할 조건을 지정하는 allow 표현식으로 구성됩니다.

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

모든 match 명령문은 컬렉션이 아닌 문서를 가리켜야 합니다. match 명령문은 match /cities/SF와 같이 특정 문서를 가리킬 수도 있고, match /cities/{city}와 같이 와일드 카드를 사용해 지정한 경로의 모든 문서를 가리킬 수도 있습니다.

위의 예에서는 match 명령문에 {city} 와일드 카드 구문이 사용되었습니다. 따라서 cities 컬렉션에 포함된 /cities/SF, /cities/NYC 등의 모든 문서에 규칙이 적용됩니다. match 명령문의 allow 표현식이 평가될 때 city 변수는 SF, NYC 등의 city 문서 이름으로 확인됩니다.

상세 작업

상황에 따라서는 readwrite를 상세 작업으로 나누는 것이 유용합니다. 예를 들어 앱에서 문서 작성과 문서 삭제에 서로 다른 조건을 적용해야 할 수 있습니다. 또는 단일 문서 읽기는 허용하면서 대규모 쿼리는 거부해야 할 수 있습니다.

read 규칙은 getlist로, write 규칙은 create, update, delete로 나눌 수 있습니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

계층적 데이터

Cloud Firestore의 데이터는 문서 컬렉션으로 정리되며, 각 문서는 하위 컬렉션을 통해 계층구조를 이룰 수 있습니다. 계층적 데이터에 보안 규칙이 어떻게 적용되는지 이해하는 것이 중요합니다.

cities 컬렉션의 각 문서가 landmarks 하위 컬렉션을 포함하는 경우를 예로 들어보겠습니다. 보안 규칙은 일치된 경로에만 적용되므로, cities 컬렉션에 정의된 액세스 제어는 landmarks 하위 컬렉션에 적용되지 않습니다. 따라서 하위 컬렉션의 액세스를 제어하는 명시적 규칙을 작성해야 합니다.

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

match 명령문을 중첩하면 내부 match 명령문의 경로는 항상 외부 match 명령문의 경로를 기준으로 합니다. 따라서 다음 규칙 세트는 서로 동일합니다.

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

임의적으로 깊은 계층구조까지 규칙을 적용하려면 재귀 와일드 카드 구문인 {name=**}를 사용합니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

재귀 와일드 카드 구문을 사용하면 와일드 카드 변수에 일치하는 경로 세그먼트 전체가 포함되며, 깊이 중첩된 하위 컬렉션에 문서가 위치한 경우에도 마찬가지입니다. 예를 들어 위에 나열한 규칙은 /cities/SF/landmarks/coit_tower에 위치한 문서와 일치하며, 이때 document 변수의 값은 SF/landmarks/coit_tower입니다.

재귀 와일드 카드는 빈 경로와 일치할 수 없으므로 match /cities/{city}/{document=**}cities 컬렉션이 아닌 하위 컬렉션에 속한 문서와 일치합니다. 반면, match /cities/{document=**}cities 컬렉션의 문서 및 하위 컬렉션의 문서와 모두 일치합니다.

문서 하나가 둘 이상의 match 명령문과 일치할 수도 있습니다. 요청과 일치하는 allow 표현식이 여러 개인 경우 조건 중 하나라도 true이면 액세스가 허용됩니다.

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

위의 예에서는 cities 컬렉션에 대한 읽기와 쓰기가 모두 허용되는데, 그 이유는 첫 번째 규칙은 항상 false이지만 두 번째 규칙이 항상 true이기 때문입니다.

보안 규칙 한도

보안 규칙을 사용할 때 다음 한도에 유의하시기 바랍니다.

한도 세부정보
검증당 고유한 exists(), get(), getAfter()의 최대 호출 수

각각 3개로 제한되지만 합쳐서 총 5개로 제한됩니다. 동일한 문서에 대한 여러 요청은 개별적인 요청으로 집계되지 않습니다.

트랜잭션이나 일괄 쓰기에서 쓰기 작업이나 쓰기 작업 모음에 대한 규칙을 검증하는 경우에는 쓰기 대상에 대한 요청이 한도에 포함되지 않습니다.

함수 호출 최대 심도 20
재귀 또는 순환 함수 호출의 최대 개수 0&lpar;허용되지 않음&rpar;
규칙 세트의 최대 표현 수 10,000개
규칙 세트의 최대 크기 64KB

다음 단계

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

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