보안 규칙 조건 작성

보안 규칙 구조화 가이드를 바탕으로 이 가이드에서는 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.uid != null;
    }
  }
}

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

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches the 'author_id' field
    // of the document
    match /users/{user} {
      allow read, update, delete: if request.auth.uid == resource.data.author_id;
      allow create: if request.auth.uid != null;
    }
  }
}

앱에서 Firebase 인증을 사용하는 경우 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) 구문을 사용하여 변수를 명시적으로 이스케이프해야 합니다.

아래 예에서는 match /databases/{database}/documents 비교 명령문으로 database 변수를 캡처하여 경로를 구성하는 데 사용합니다.

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 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 get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}

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

맞춤 함수

보안 규칙이 복잡해지면 조건 세트를 함수로 묶어 규칙 세트 전체에서 재사용할 수 있습니다. 보안 규칙에서는 맞춤 함수를 지원합니다. 맞춤 함수의 구문은 자바스크립트와 비슷하지만, 보안 규칙 함수는 도메인 언어로 작성되며 다음과 같은 중요한 제한사항이 있습니다.

  • 함수는 return 명령문 하나만 포함할 수 있습니다. 다른 로직은 포함할 수 없습니다. 예를 들어 임시 변수를 만들거나, 루프를 실행하거나, 외부 서비스를 호출할 수 없습니다.
  • 함수는 정의된 범위에 속하는 함수와 변수에 자동으로 액세스할 수 있습니다. 예를 들어 service cloud.firestore 범위 안에 정의된 함수는 resource 변수 및 get(), exists() 등의 내장 함수에 액세스할 수 있습니다.
  • 함수는 다른 함수를 호출할 수 있지만 재귀 호출은 금지됩니다. 호출 스택 깊이는 최대 10으로 제한됩니다.

함수는 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();
    }
  }
}

보안 규칙에서 함수를 사용하면 규칙이 복잡해져도 쉽게 관리할 수 있습니다. 개발자 정의 함수의 자세한 내용은 참조 문서를 확인하세요.

다음 단계

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

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