Flutter 개발

Firestore 보안 규칙 실전 설계

규칙 없이 배포하면 벌어지는 일

John Doe
2025년 5월 20일
8분 읽기
48

보안 규칙 없이 배포하면

Firebase 프로젝트를 처음 만들면 테스트 모드로 시작하게 되죠. 모든 읽기/쓰기가 열려있는 상태죠. 개발 중에는 편하지만 이대로 프로덕션에 나가면 누구나 데이터를 읽고 쓸 수 있습니다.

실제로 Firebase 콘솔에서 경고 메일이 날아옵니다. 30일 후 자동 잠금이 걸리기 전에 규칙을 제대로 설계해야 합니다.

기본 구조 이해하기

JavaScript
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 모든 문서에 대한 기본 규칙
    match /{document=**} {
      allow read, write: if false; // 기본: 모두 차단
    }
  }
}
기본 원칙은 '모두 차단 후 필요한 것만 열기'예요. match 경로가 구체적일수록 우선순위가 높습니다. 와일드카드 {document=}는 하위 모든 경로를 포함하는 재귀 매칭입니다.

패턴 1: 사용자 본인 문서만 접근

JavaScript
// 사용자 프로필: 본인만 읽기/쓰기
match /users/{userId} {
  allow read, write: if request.auth != null 
    && request.auth.uid == userId;
}

// 사용자의 하위 컬렉션도 동일 규칙 적용
match /users/{userId}/orders/{orderId} {
  allow read: if request.auth.uid == userId;
  allow create: if request.auth.uid == userId
    && request.resource.data.keys().hasAll(['amount', 'status']);
}
request.auth.uid와 경로의 userId를 비교하는 패턴이 가장 흔합니다. create 시에는 필수 필드 검증도 같이 넣어두면 클라이언트 실수를 서버단에서 잡아줍니다.

패턴 2: 역할 기반 접근 제어

JavaScript
// Custom Claims를 활용한 관리자 권한
function isAdmin() {
  return request.auth.token.admin == true;
}

function isEditor() {
  return request.auth.token.role == 'editor';
}

match /posts/{postId} {
  allow read: if true; // 공개 글은 누구나 읽기
  allow create: if isEditor() || isAdmin();
  allow update: if isAdmin() 
    || (isEditor() && resource.data.authorId == request.auth.uid);
  allow delete: if isAdmin();
}
Custom Claims는 Admin SDK로 설정해요. Cloud Functions에서 사용자 생성 시 기본 역할을 부여하는 방식이 일반적이겠죠. 클라이언트에서는 Claims를 변조할 수 없으니 안전합니다.

패턴 3: 데이터 검증

JavaScript
match /reviews/{reviewId} {
  allow create: if request.auth != null
    // 필수 필드 검사
    && request.resource.data.keys().hasAll(['rating', 'text', 'userId'])
    // 타입 검사
    && request.resource.data.rating is int
    && request.resource.data.rating >= 1
    && request.resource.data.rating <= 5
    // 텍스트 길이 제한
    && request.resource.data.text.size() <= 500
    // 작성자 위조 방지
    && request.resource.data.userId == request.auth.uid;
}
보안 규칙에서 데이터 검증까지 하면 잘못된 데이터가 DB에 들어가는 걸 원천 차단돼요. 클라이언트 검증만 믿으면 안 되죠.

로컬 테스트

bash
# 에뮬레이터로 규칙 테스트
firebase emulators:start --only firestore

# 규칙 유닛 테스트 실행
npm test
배포 전에 반드시 에뮬레이터에서 테스트하세요. Firebase는 @firebase/rules-unit-testing 패키지로 규칙 테스트를 작성하죠. 규칙이 복잡해질수록 테스트 없이는 버그를 잡기 어렵습니다.

규칙 파일은 firestore.rules에 저장하고, firebase deploy --only firestore:rules로 규칙만 따로 배포돼요.
#Firebase
#Firestore
#보안
#Security Rules