Firestore Security Rules 문법 정리: match, allow, request.auth
Firestore Security Rules는 클라이언트 코드와 별개로, 서버에서 최종 접근 권한을 검증하는 정책입니다. 이 글은 특정 서비스 규칙 예시가 아니라, 실제 작성에 필요한 문법과 구조를 중심으로 정리합니다.
1. 기본 구조
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// 규칙 작성 영역
}
}
rules_version = '2';: Firestore 규칙 문법 버전 선언service cloud.firestore: Firestore에 적용되는 규칙 블록match /databases/{database}/documents: Firestore 문서 경로의 루트
2. match 문법: 경로 지정
match는 “어떤 경로에” 규칙을 적용할지 정합니다.
match /profiles/{uid} {
// uid는 경로 변수
}
{uid}처럼 중괄호로 선언한 값은 경로 변수- 요청 경로의 실제 값이 변수에 바인딩됨
하위 전체를 한 번에 다루려면 재귀 와일드카드를 사용합니다.
match /projects/{projectId}/{docPath=**} {
// projectId 아래의 모든 하위 문서 경로에 매칭
}
{docPath=**}: 깊이에 상관없이 하위 문서 전체 매칭
3. allow 문법: 동작 권한 지정
allow read, write: if <조건식>;
read:get,list요청 포함write:create,update,delete요청 포함
필요하면 동작별로 분리할 수 있습니다.
allow create: if <조건식>;
allow update: if <조건식>;
allow delete: if <조건식>;
4. request/auth/resource 핵심 객체
Rules에서 가장 자주 쓰는 객체는 아래 4개입니다.
request.auth: 인증 정보request.resource.data: 쓰기 요청으로 들어온 새 데이터resource.data: 현재 저장된 기존 데이터request.time: 요청 시각
예시:
allow read: if request.auth != null;
- 로그인 사용자만 읽기 허용
allow update: if request.auth != null
&& request.resource.data.ownerUid == resource.data.ownerUid;
- 기존 소유자 필드를 임의 변경하지 못하도록 방어
5. 자주 쓰는 조건식 패턴
5-1. 본인 데이터만 접근
allow read, write: if request.auth != null
&& request.auth.uid == uid;
5-2. 특정 필드 존재/타입 검증
allow create: if request.resource.data.keys().hasAll(['title', 'createdAt'])
&& request.resource.data.title is string;
5-3. 업데이트 가능한 필드 제한
allow update: if request.resource.data.diff(resource.data)
.changedKeys()
.hasOnly(['displayName', 'photoURL']);
6. 작성 시 주의할 점
- 기본값은 거부이므로 필요한 경로만 명시적으로 허용
match범위를 넓게 잡을수록 조건식을 더 엄격하게 작성write를 한 번에 열기보다create/update/delete분리 권장- 클라이언트 검증만 믿지 말고 Rules에서 최종 검증
7. 운영 팁
- 배포 전 Rules Playground 또는 Emulator로 시나리오 테스트
- “로그인 안 함 / 본인 / 타인” 케이스를 최소 세트로 검증
- 컬렉션 구조 변경 시 규칙도 함께 수정하는 습관 필요
8. create/update/delete 분리 템플릿
아래는 문서 생성/수정/삭제 권한을 분리해서 관리하는 기본 템플릿입니다.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
// 읽기는 공개
allow read: if true;
// 생성은 로그인 사용자만 가능, 작성자 UID는 본인으로 고정
allow create: if request.auth != null
&& request.resource.data.ownerUid == request.auth.uid
&& request.resource.data.keys().hasAll(['title', 'ownerUid', 'createdAt']);
// 수정은 작성자만 가능, ownerUid는 변경 불가
allow update: if request.auth != null
&& resource.data.ownerUid == request.auth.uid
&& request.resource.data.ownerUid == resource.data.ownerUid;
// 삭제는 작성자만 가능
allow delete: if request.auth != null
&& resource.data.ownerUid == request.auth.uid;
}
}
}
핵심 포인트:
create: 필수 필드 존재 검증 + 작성자 UID 강제update: 작성자 본인만 수정 + 소유자 필드 불변delete: 작성자 본인만 삭제
Firestore Security Rules는 길게 쓰는 것보다, 경로와 조건을 정확히 좁혀 쓰는 것이 핵심입니다.
상황별로 create/update/delete를 분리하면 권한 실수를 크게 줄일 수 있습니다.