Firestore Enterprise vs Standard: 새 앱은 Enterprise로 시작하세요
Firestore 데이터베이스를 만들 때 고르는 에디션(Standard 또는 Enterprise)은 나중에 바꿀 수 없습니다. Enterprise 에디션의 Native 모드가 2026년 4월 정식 버전(GA)이 된 지금, 새 앱은 Enterprise로 시작하는 편이 낫습니다. 단, 인덱스와 클라이언트 접근을 직접 챙긴다는 조건에서입니다.
요약
- 나중에 덜 막히는 쪽을 고르세요. Standard의 한계는 데이터를 옮겨야 풀리고, Enterprise의 문제는 대개 인덱스를 배포하면 풀립니다. 이유
- 코드는 그대로, 쿼리는 더 많이. 실시간 리스너, 오프라인, 보안 규칙이 Standard와 같고, 검색·집계·조인을 하는 Pipeline 쿼리가 더해집니다. 더해지는 것
- 인덱스를 건 읽기는 더 쌉니다. 4KiB 이하 문서를 ID로 읽으면 Standard의 6분의 1입니다. 쓰기는 인덱스가 많을수록 비싸지고, 삭제는 늘 더 비쌉니다. 요금 비교
- 인덱스와 접근은 직접 챙깁니다. 인덱스가 없는 쿼리는 에러 없이 컬렉션 전체를 읽고, 남이 일부러 그렇게 만들 수도 있습니다. 지킬 것
Enterprise가 기본값인 이유
1. 바꿀 수 없으니, 덜 막히는 쪽으로
에디션은 데이터베이스를 만들 때 정해지고 바뀌지 않습니다. 바꾸려면 새 데이터베이스로 데이터를 옮기고, 인덱스와 TTL·백업 설정을 다시 만들고, 앱이 새 데이터베이스를 보도록 새 버전을 배포해야 합니다(이전 가이드).
그러니 나중에 덜 막히는 쪽으로 시작해야 합니다. Standard에서 막히는 것은 검색, 집계, 조인 같은 기능이라 이전하거나 구조를 바꿔 우회해야 합니다. Enterprise에서 막히는 것은 대개 빠진 인덱스라, 코드와 데이터는 두고 인덱스만 배포하면 됩니다.
2. 같은 코드에 쿼리가 더해집니다
Enterprise의 Native 모드는 Standard와 같은 Firebase SDK와 같은 쿼리(Core 연산)를 씁니다. where(), orderBy(), onSnapshot() 리스너, 오프라인 캐시, 보안 규칙이 그대로 동작하고, 로컬 에뮬레이터, Cloud Functions(2nd gen) 트리거, 서울(asia-northeast3)을 포함한 같은 리전, Spark 요금제의 무료 사용량도 지원합니다. 다른 점은 정렬입니다. 정렬 값이 같은 문서끼리의 순서를 문서 ID로 정해 주지 않으므로, 커서로 페이지를 넘긴다면 orderBy에 문서 ID를 덧붙이세요.
그 위에 Pipeline 쿼리가 더해집니다. Standard에서는 우회해야 했던 일이 쿼리 하나가 됩니다.
| 하고 싶은 일 | Standard | Enterprise |
|---|---|---|
| 본문 텍스트 검색 | 외부 검색 서비스(Algolia 등)에 동기화 | 텍스트 검색 |
| 반경 안의 장소 찾기 | geohash 필드를 만들어 범위 쿼리 | 지리 검색 |
| 글자 일부·정규식으로 찾기 | 앞부분 일치만 가능 | str_contains, regex_match |
| 그룹별 합계, 고유값 개수 | 그룹마다 따로 집계하거나 카운터 문서 유지 | aggregate 한 단계 |
| 다른 컬렉션과 합쳐 읽기 | 비정규화하거나 여러 번 읽기 | 서브쿼리 조인 |
| 조건에 맞는 문서 일괄 수정·삭제 | 읽어서 배치로 쓰는 스크립트 | update·delete 단계 |
| 같은 값 중복 막기 | 그 값을 ID로 쓰는 문서와 트랜잭션 | 유니크 인덱스 |
텍스트·지리 검색과 일괄 수정·삭제(DML)는 2026년 10월에 정식 버전이 됐습니다. 다만 Pipeline은 한 번 실행하고 끝나는 조회라 실시간 리스너와 오프라인이 없고, 보안 규칙은 Pipeline에서 상수와 비교하는 단순한 필터만 알아봅니다. 화면의 목록과 실시간 갱신은 Core 쿼리로, 검색·집계·리포트는 Pipeline으로 나누고, 복잡한 Pipeline은 서버(Admin SDK, Cloud Functions)에서 돌리세요.
3. 인덱스를 건 읽기는 더 쌉니다
Standard는 문서 개수로, Enterprise는 읽고 쓴 바이트로 요금을 셉니다. us-central1 기준, 2026년 11월의 단가입니다.
| Standard | Enterprise | |
|---|---|---|
| 읽기 | 문서 100만 개 $0.30 | 4KiB마다 1유닛, 100만 유닛 $0.05 |
| 쓰기 | 문서 100만 개 $0.90, 인덱스 갱신은 무료 | 1KiB마다 1유닛, 100만 유닛 $0.26. 인덱스 항목마다 1유닛 더 |
| 삭제 | 문서 100만 개 $0.10 | 쓰기 유닛(문서 + 인덱스 항목) |
| 실시간 업데이트 | 읽기로 계산, 100만 개 $0.30 | 4KiB마다 1유닛, 100만 유닛 $0.30. 4KiB 이하 문서는 같은 값 |
| 저장 | GiB당 월 약 $0.15. 모든 필드의 자동 인덱스도 용량에 포함 | GiB당 월 약 $0.23. 직접 만든 인덱스만 포함 |
| 하루 무료 사용량 | 읽기 5만, 쓰기 2만, 삭제 2만 | 읽기 5만, 쓰기 4만, 실시간 5만 유닛 |
- 읽기: 4KiB 이하 문서를 ID로 읽으면 Enterprise가 6분의 1이고, 24KiB까지는 같거나 쌉니다. 쿼리는 인덱스를 읽는 값이 더해져, 결과가 1건이면 3분의 1이고 많을수록 6분의 1에 가까워집니다.
- 쓰기: 1KiB 문서를 새로 쓸 때 인덱스 항목이 2개까지면 Enterprise가 싸고(100만 건에 $0.78), 3개부터 비쌉니다($1.04). 인덱스가 걸린 필드를 바꾸는 업데이트는 바뀌는 항목마다 2유닛이라 더 빨리 비싸집니다.
- 삭제: 가장 작은 문서도 1유닛($0.26)이라 Standard($0.10)보다 늘 비쌉니다.
읽기가 쓰기보다 훨씬 많은 앱이라면 Enterprise가 쌉니다. 쓰기와 삭제가 많은 앱은 문서 크기와 인덱스 개수로 먼저 계산해 보세요.
대가: 인덱스와 접근은 직접 챙겨야 합니다
Standard는 인덱스를 타는 쿼리만 실행합니다. 필드마다 인덱스가 자동으로 생기고, 복합 인덱스가 필요한 쿼리는 그 인덱스를 만드는 링크와 함께 에러를 냅니다. 그래서 쿼리 비용은 결과 개수만 따라갑니다.
Enterprise는 인덱스를 자동으로 만들지 않고, 인덱스가 없어도 쿼리를 실행합니다. 대신 컬렉션 전체를 읽고 읽은 바이트만큼 요금을 내며, 정렬도 메모리에서 하므로 쿼리당 메모리 한도(128MiB)에 걸릴 수 있습니다. 에러가 없으니 문서가 수십 개인 개발 중에는 티가 나지 않다가, 데이터가 쌓이면서 드러납니다.
사용자 이름으로 1명을 찾는 쿼리를 100만 번 실행할 때의 요금입니다. 문서는 2KiB이고, 첫 줄은 Google의 요금 예시, 둘째 줄은 같은 계산을 문서 10만 개로 늘린 것입니다.
| 컬렉션 | Standard(자동 인덱스) | Enterprise(인덱스 있음) | Enterprise(인덱스 없음) |
|---|---|---|---|
| 문서 100개 | $0.30 | $0.10 | $2.50 |
| 문서 10만 개 | $0.30 | $0.10 | $2,500 |
인덱스 하나로 같은 쿼리의 요금이 2만 5천 배 차이 납니다(10만 × 2KiB ÷ 4KiB = 쿼리 한 번에 5만 유닛).
이 차이는 남도 쓸 수 있습니다. 클라이언트가 목록을 읽을 수 있는 컬렉션이면, 누구든 인덱스 없는 필드로 필터를 붙여 읽을 수 있는 범위 전체를 스캔시킬 수 있습니다. 맞는 문서가 없으니 limit도 소용없고, 보안 규칙은 쿼리에 덧붙인 필터를 막지 못합니다. Standard에서는 이런 쿼리가 에러로 끝납니다.
지킬 것 네 가지
- 쿼리를 쓸 때 인덱스도 같이 씁니다. 계속 커지는 컬렉션에 거는
where·orderBy조합마다 인덱스를firestore.indexes.json에 적고firebase deploy --only firestore:indexes로 배포합니다. Standard가 자동으로 만들던 필드 하나짜리 인덱스도 직접 적습니다. 문서 ID로 읽을 때는 인덱스가 필요 없습니다. 아래는where('authorId', '==', uid).orderBy('createdAt', 'desc')에 맞는 인덱스입니다.{ "indexes": [ { "collectionGroup": "posts", "queryScope": "COLLECTION", "fields": [ { "fieldPath": "authorId", "order": "ASCENDING" }, { "fieldPath": "createdAt", "order": "DESCENDING" } ] } ] } - 배포 전에 Query Explain으로 확인합니다. Firebase 콘솔 Firestore의 데이터 탭에서 쿼리 편집기(Query Editor)로 같은 조건을 실행하고 Query Explain 탭을 엽니다. 실행 트리 맨 아래가
TableScan이면 인덱스 없이 컬렉션 전체를 읽은 것입니다. - 클라이언트 접근을 묶습니다. App Check를 강제해 앱이 아닌 곳에서 오는 요청을 막고, 보안 규칙으로 목록 읽기를
resource.data.ownerId == request.auth.uid처럼 인덱스가 있는 필드의 같음 조건에 묶습니다. 그러면 스캔이 일어나도 그 사용자의 문서 안에서 끝납니다. - Query Insights와 예산 알림을 켜 둡니다. Query Insights는 자주 도는 쿼리와 그 성능을 보여 주어 인덱스가 필요한 곳을 찾게 해 줍니다. Blaze 요금제라면 Cloud Billing 예산 알림도 걸어 두세요.
Enterprise로 시작하기
Firebase 콘솔의 Firestore에서 데이터베이스 만들기(Create database)를 누르고 Enterprise와 Native 모드를 고른 뒤 ID와 위치를 정합니다. 실시간 업데이트(Realtime Updates)는 켠 채로 두세요(기본값). 나중에 바꿀 수 없어서, 끄고 만들면 리스너를 쓸 수 없는 데이터베이스가 됩니다. 그다음 세 가지가 Standard와 다릅니다.
- 코드에 데이터베이스 ID를 넘깁니다. Enterprise 데이터베이스는 직접 이름을 붙인 데이터베이스이고,
(default)는 Standard에만 있습니다. SDK는 따로 말하지 않으면(default)에 붙습니다.// Web const db = getFirestore(app, 'app-db'); // Android (Kotlin) val db = FirebaseFirestore.getInstance("app-db") // iOS (Swift) let db = Firestore.firestore(database: "app-db") // Flutter final db = FirebaseFirestore.instanceFor( app: Firebase.app(), databaseId: 'app-db'); - firebase.json에 데이터베이스와 에디션을 적습니다. 규칙과 인덱스가 그 데이터베이스로 배포되고, 에뮬레이터도 Enterprise로 뜹니다. 데이터베이스는 콘솔에서 먼저 만드세요. 적힌 데이터베이스가 없으면
firebase deploy가 대신 만드는데, Firebase CLI 15.12는 이때 Firebase SDK가 쓸 수 없는 MongoDB 호환 모드로 만듭니다.{ "firestore": { "database": "app-db", "edition": "enterprise", "rules": "firestore.rules", "indexes": "firestore.indexes.json" } } - 무료 사용량은 먼저 만든 데이터베이스 하나에만 붙습니다. 쓰지 않는 Standard 데이터베이스가 프로젝트에 있다면 그것을 지운 뒤에 Enterprise를 만드세요. 그래야 무료 사용량이 Enterprise로 갑니다.
Standard가 여전히 나은 경우
- 이미 Standard로 돌고 있는 앱. Pipeline이 꼭 필요해지기 전에는 옮기지 마세요.
- 쿼리와 인덱스를 챙길 사람이 없는 프로젝트. 인덱스 없는 쿼리를 아예 실행하지 않는 Standard가 안전장치입니다.
- 큰 공개 컬렉션을 클라이언트가 직접 읽는 앱. 규칙으로 범위를 묶을 수 없는 공개 목록은 누구나 전체 스캔을 일으킬 수 있습니다.
- 쓰기·삭제가 많거나 큰 문서를 주로 읽는 앱. 위의 손익분기를 넘으면 Standard가 쌉니다.
(default)데이터베이스나 Cloud Functions 1st gen을 전제로 한 도구를 써야 할 때. Enterprise는 이름 있는 데이터베이스이고, 1st gen 트리거를 지원하지 않습니다.
출처
- Firestore 에디션, Native 모드의 에디션 비교, Enterprise Native 모드 개요: 기능, 인덱스, 정렬, 스캔의 차이
- Enterprise 요금, 쿼리 요금 예시, 쓰기·삭제 요금 예시, Firebase 요금제: 단가와 무료 사용량
- Standard에서 Enterprise로 이전, Firestore 출시 노트
- Enterprise 시작하기, 데이터베이스 관리, 데이터베이스 설정(REST), 위치, 한도와 무료 사용량
- Enterprise 인덱스, 인덱스 JSON 형식, Query Explain, Query Insights
- Pipeline 보안 규칙, App Check, Cloud Functions 트리거, 에뮬레이터
