Cloud Storage용 보안 규칙 언어의 핵심 구문 알아보기

Cloud Storage용 Firebase 보안 규칙을 사용하면 Cloud Storage 버킷에 저장된 객체에 대한 액세스를 제어할 수 있습니다. 유연한 규칙 구문을 사용하면 Cloud Storage 버킷에 대한 모든 쓰기부터 특정 파일에 대한 작업까지 모든 작업을 제어하는 규칙을 작성할 수 있습니다.

이 가이드에서는 전체 규칙 세트를 생성하기 위한 Cloud Storage 보안 규칙의 기본적인 구문과 구조를 설명합니다.

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

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

service firebase.storage {
    // ...
}

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

읽기/쓰기 기본 규칙

기본 규칙은 Cloud Storage 버킷을 식별하는 match 문, 파일 이름을 지정하는 match 문, 지정된 데이터를 읽을 수 있는 조건에 관한 allow 표현식으로 구성됩니다. allow 표현식은 관련된 액세스 방법(예: 읽기, 쓰기)과 액세스가 허용되거나 거부되는 조건을 지정합니다.

기본 규칙 세트의 첫 번째 match 문은 {bucket} 와일드 카드 표현식을 사용하여 프로젝트의 모든 버킷에 적용되는 규칙을 나타냅니다. 다음 섹션에서는 와일드 카드 일치의 개념에 대해 자세히 알아보겠습니다.

service firebase.storage {
  // The {bucket} wildcard indicates we match files in all Cloud Storage buckets
  match /b/{bucket}/o {
    // Match filename
    match /filename {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

모든 match 문은 파일을 가리킵니다. match 문은 match /images/profilePhoto.png와 같이 특정 파일을 가리킬 수 있습니다.

와일드 카드 일치

규칙은 단일 파일을 가리키는 것 외에도 match /images/{imageId}와 같이 와일드 카드를 사용해 이름에 슬래시를 포함한 지정된 문자열 프리픽스가 있는 모든 파일을 가리킬 수 있습니다.

위의 예시에서는 match 문에 {imageId} 와일드 카드 구문이 사용되었습니다. 따라서 이름 시작 부분에 /images/가 있는 모든 파일(예: /images/profilePhoto.png 또는 /images/croppedProfilePhoto.png)에 규칙이 적용됩니다. match 문의 allow 표현식이 평가될 때 imageId 변수는 profilePhoto.png 또는 croppedProfilePhoto.png 등의 이미지 파일 이름으로 확인됩니다.

match 내에서 와일드 카드 변수를 참조하여 파일 이름 또는 경로에 대한 승인을 제공할 수 있습니다.

// Another way to restrict the name of a file
match /images/{imageId} {
  allow read: if imageId == "profilePhoto.png";
}

계층적 데이터

앞에서 설명한 것처럼 Cloud Storage 버킷 내에 계층 구조는 없습니다. 그러나 파일 이름에 슬래시가 포함된 파일 이름 지정 규칙을 사용하면 중첩된 디렉터리 및 하위 디렉터리와 같은 구조를 모방할 수 있습니다. 파일 이름에 Firebase 보안 규칙이 어떻게 적용되는지 이해하는 것이 중요합니다.

이름이 모두 /images/ 스템으로 시작하는 파일 세트를 예로 들어보겠습니다. Firebase 보안 규칙은 일치된 파일 이름에만 적용되므로, /images/ 스템에 정의된 액세스 제어는 /mp3s/ 스템에 적용되지 않습니다. 따라서 다음과 같이 다른 파일 이름 패턴과 일치하는 명시적 규칙을 작성해야 합니다.

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      allow read, write: if <condition>;
    }

    // Explicitly define rules for the 'mp3s' pattern
    match /mp3s/{mp3Id} {
      allow read, write: if <condition>;
    }
  }
}

match 문을 중첩하면 내부 match 문의의 경로는 항상 외부 match 문의 경로에 추가됩니다. 따라서 다음 두 규칙 세트는 서로 동일합니다.

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      // Exact match for "images/profilePhoto.png"
      match /profilePhoto.png {
        allow write: if <condition>;
      }
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    // Exact match for "images/profilePhoto.png"
    match /images/profilePhoto.png {
      allow write: if <condition>;
      }
  }
}

재귀 와일드 카드 일치

파일 이름 끝에 문자열을 일치시켜 반환하는 와일드 카드 외에도 {path=**}와 같이 와일드 카드 이름에 =**를 추가하면 다중 세그먼트 와일드 카드를 선언할 수 있습니다.

// Partial match for files that start with "images"
match /images {

  // Exact match for "images/**"
  // e.g. images/users/user:12345/profilePhoto.png is matched
  // images/profilePhoto.png is also matched!
  match /{allImages=**} {
    // This rule matches one or more path segments (**)
    // allImages is a path that contains all segments matched
    allow read: if <other_condition>;
  }
}

여러 규칙이 파일 하나와 일치하면 모든 규칙 판정의 결과를 OR로 결합한 결과가 적용됩니다. 즉, 파일과 일치하는 규칙이 하나라도 true로 판정되면 결과는 true입니다.

위 규칙에서는 condition 또는 other_condition이 true로 판정되면 'images/profilePhoto.png' 파일을 읽을 수 있지만 'images/users/user:12345/profilePhoto.png' 파일은 other_condition의 결과가 true일 때만 읽을 수 있습니다.

Cloud Storage 보안 규칙은 하위로 전파되지 않으며, 규칙이 지정된 경로와 요청 경로가 일치할 때만 규칙이 판정됩니다.

버전 1

Firebase 보안 규칙은 기본적으로 버전 1을 사용합니다. 버전 1에서는 재귀 와일드 카드가 0개 이상의 요소가 아닌 하나 이상의 파일 이름 요소와 일치합니다. 따라서 match /images/{filenamePrefixWildcard}/{imageFilename=**}은 /images/profilePics/profile.png와 같은 파일 이름과 일치하지만 /images/badge.png와는 일치하지 않습니다. 대신 /images/{imagePrefixorFilename=**}을 사용합니다.

재귀 와일드 카드는 match 문 끝에 와야 합니다.

더 강력한 기능을 사용하려면 버전 2를 사용하는 것이 좋습니다.

버전 2

Firebase 보안 규칙 버전 2에서 재귀 와일드 카드는 0개 이상의 경로 항목과 일치합니다. 따라서 /images/{filenamePrefixWildcard}/{imageFilename=**}은 파일 이름 /images/profilePics/profile.png 및 /images/badge.png와 일치합니다.

보안 규칙 상단에 rules_version = '2';를 추가하여 버전 2를 선택해야 합니다.

rules_version = '2';
service cloud.storage {
  match /b/{bucket}/o {
   ...
 }
}

match 문당 최대 1개의 재귀 와일드 카드를 사용할 수 있지만 버전 2에서는 match 문의 어디에나 이 와일드 카드를 배치할 수 있습니다. 예를 들면 다음과 같습니다.

rules_version = '2';
service firebase.storage {
 match /b/{bucket}/o {
   // Matches any file in a songs "subdirectory" under the
   // top level of your Cloud Storage bucket.
   match /{prefixSegment=**}/songs/{mp3filenames} {
     allow read, write: if <condition>;
   }
  }
}

상세 작업

상황에 따라서는 readwrite를 상세 작업으로 나누는 것이 유용합니다. 예를 들어 앱에서 파일 작성과 파일 삭제에 서로 다른 조건을 적용해야 할 수 있습니다.

read 작업은 get, list로 나눌 수 있습니다.

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

service firebase.storage {
  match /b/{bucket}/o {
    // A read rule can be divided into read and list rules
    match /images/{imageId} {
      // Applies to single file read requests
      allow get: if <condition>;
      // Applies to list and listAll requests (Rules Version 2)
      allow list: if <condition>;

    // A write rule can be divided into create, update, and delete rules
    match /images/{imageId} {
      // Applies to writes to file contents
      allow create: if <condition>;

      // Applies to updates to (pre-existing) file metadata
      allow update: if <condition>;

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

중첩 match 문

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

service firebase.storage {
  match b/{bucket}/o {
    // Matches file names directly inside of '/images/'.
    match /images/{imageId} {
      allow read, write: if false;
    }

    // Matches file names anywhere under `/images/`
    match /images/{imageId=**} {
      allow read, write: if true;
    }
  }
}

위의 예시에서는 이름이 /images/로 시작되는 파일에 대한 모든 읽기와 쓰기가 허용됩니다. 그 이유는 첫 번째 규칙이 false인 경우에도 두 번째 규칙이 항상 true이기 때문입니다.

규칙과 필터의 차이

데이터를 보호하고 파일 작업을 수행하기 시작하면 보안 규칙이 필터가 아니라는 사실에 유의하세요. 파일 이름 패턴과 일치하는 파일 세트에서 작업을 수행할 수 없으며 Cloud Storage에서는 현재 클라이언트에 액세스 권한이 있는 파일에만 액세스할 수 있는 것으로 예상됩니다.

예를 들어 다음 보안 규칙을 따르세요.

service firebase.storage {
  match /b/{bucket}/o {
    // Allow the client to read files with contentType 'image/png'
    match /aFileNamePrefix/{aFileName} {
      allow read: if resource.contentType == 'image/png';
    }
  }
}

거부되는 쿼리: 다음 요청의 경우 결과 세트에 contentTypeimage/png가 아닌 파일이 포함될 수 있으므로 규칙에서 거부됩니다.

filesRef = storage.ref().child("aFilenamePrefix");

filesRef.listAll()
    .then(function(result) {
      console.log("Success: ", result.items);
    })
});

Cloud Storage 보안 규칙의 규칙이 잠재적 결과를 기준으로 각 쿼리를 평가하고 클라이언트가 읽을 수 없는 파일이 반환될 가능성이 있으면 요청이 실패합니다. 액세스 요청은 규칙에 의해 설정된 제약조건을 따라야 합니다.

다음 단계

Cloud Storage용 Firebase 보안 규칙에 대한 이해도를 높일 수 있습니다.

  • 규칙 언어의 주요 개념인 동적 조건에 대해 알아보세요. 동적 조건을 사용하면 규칙을 통해 사용자 승인을 확인하고, 기존 데이터와 수신 데이터를 비교하고, 수신 데이터를 검증할 수 있습니다.

  • 일반적인 보안 사용 사례와 이를 해결하는 Firebase 보안 규칙 정의를 알아보세요.

Cloud Storage 관련 Firebase 보안 규칙 사용 사례를 살펴볼 수 있습니다.