🏝️ Hwani Studio

Home › Guides › 1인 메이커 개발 노트

로그인 없는 공개 폼을 Firestore로 안전하게 받기: 보안 규칙 설계 노트

2026-10-18 · Hwani Studio

출시 알림 신청 폼처럼 로그인 없이 누구나 제출하는 데이터는 서버를 따로 두지 않고 Firestore에 바로 쓰게 하면 편합니다. 대신 보안 규칙을 꼼꼼히 써야 합니다. 이 글은 pocaprint의 대기자 명단(waitlist)과 사용 이벤트(events) 규칙을 예로 듭니다.

원칙: 쓰기는 좁게, 읽기는 관리자만

문서 모양을 규칙으로 검사하기

function validWaitlistDoc(d) {
  return d.keys().hasOnly(['email','product','utm_source',
                           'utm_medium','utm_campaign','referrer','createdAt'])
    && d.keys().hasAll(['email','product','createdAt'])
    && d.email is string
    && d.email.size() > 5 && d.email.size() < 200
    && d.product in ['pocaprint']
    && d.createdAt == request.time;
}
match /waitlist/{docId} {
  allow create: if validWaitlistDoc(request.resource.data);
  allow read: if isAdmin();
  allow update, delete: if false;
}

각 줄이 막는 것은 다음과 같습니다.

이벤트 기록도 같은 방식

Firebase 연결을 켜면 pocaprint는 PDF를 만들 때 용지 종류와 카드 수, 유입 경로(UTM) 값만 기록합니다. 이벤트 규칙은 유형을 pdf_generated로, 용지를 a4나 letter로, 카드 수를 0~100 사이 정수로 제한합니다. 이미지나 파일 이름 같은 개인 정보는 필드 목록에 아예 없으므로 저장될 수 없습니다.

규칙이 막지 못하는 것

보안 규칙은 문서 하나하나의 모양은 검사하지만, 같은 사람이 짧은 시간에 수천 건을 넣는 것까지 막지는 못합니다. 남용이 걱정되면 App Check로 정상 앱에서 온 요청인지 확인하거나, 서버 함수를 거쳐 제출 빈도를 제한하는 방법을 추가로 검토하세요. 이메일 형식 검사도 규칙에서는 간단한 정규식 수준만 가능합니다.

한 프로젝트를 여러 앱이 쓸 때

Firestore 보안 규칙은 프로젝트(데이터베이스)마다 파일 하나입니다. 앱 A의 저장소에서 규칙을 배포하고, 다음에 앱 B의 저장소에서 규칙을 배포하면 B의 규칙이 A의 규칙을 통째로 덮어씁니다. A의 컬렉션이 갑자기 "모두 거부"가 되는 사고가 여기서 생깁니다.

  1. 프로젝트를 쓰는 모든 앱의 컬렉션 목록을 먼저 정리합니다.
  2. 모든 match 블록과 공용 함수(isAdmin() 등)를 파일 하나로 합칩니다.
  3. 합친 파일 하나만 배포 기준으로 삼고, 다른 저장소의 firebase.json에서는 firestore 항목을 빼서 실수로 배포하지 않게 합니다.
  4. 배포 전에 에뮬레이터나 콘솔의 규칙 시뮬레이터로 각 앱의 읽기·쓰기를 확인합니다.

관리자 UID로 쓰기를 여는 부분은 Firebase Auth UID 게이트 글에서 다뤘습니다.