웹 또는 모바일 클라이언트 라이브러리를 사용하여 Firestore 데이터베이스 만들기
이 빠른 시작에서는 Android, Apple 플랫폼, 웹, Unity 또는 C++ 클라이언트 라이브러리를 사용하여 Firestore를 설정하고, 데이터를 추가하고, 데이터를 읽는 방법을 설명합니다.
Firestore 데이터베이스 만들기
Firebase 프로젝트를 아직 만들지 않았다면 Firebase Console에서 프로젝트 추가를 클릭한 후 화면의 안내에 따라 Firebase 프로젝트를 만들거나 기존 GCP 프로젝트에 Firebase 서비스를 추가합니다.
Firebase Console의 탐색창에서 Firestore를 선택한 후 Firestore의 데이터베이스 만들기를 클릭합니다.
Firestore 보안 규칙의 테스트 모드를 선택합니다.
- 테스트 모드
- 모바일 및 웹 클라이언트 라이브러리를 시작할 때 유용하지만 모든 사용자가 데이터를 읽고 덮어쓸 수 있습니다. 테스트 완료 후에 데이터 보안 섹션을 검토해야 합니다.
데이터베이스 위치를 선택합니다.
이 위치 설정이 프로젝트의 기본 Google Cloud Platform(GCP) 리소스 위치입니다. 이 위치는 특히 기본 Cloud Storage 버킷 및 App Engine 앱(Cloud Scheduler 사용 시 필요)과 같이 위치 설정이 필요한 프로젝트의 GCP 서비스에 사용됩니다.
위치를 선택할 수 없다면 프로젝트에 이미 기본 GCP 리소스 위치가 있는 것입니다. 이 위치는 프로젝트 생성 과정이나 위치 설정이 필요한 다른 서비스를 설정할 때 지정한 것입니다.
완료를 클릭합니다.
Firestore를 사용 설정하면 Cloud API Manager의 API도 사용 설정됩니다.
개발 환경 설정
필요한 종속 항목 및 클라이언트 라이브러리를 앱에 추가하세요.
웹 버전 9
- 안내에 따라 Firebase를 웹 앱에 추가합니다.
-
Firebase와 Firestore를 모두 가져옵니다.
import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore";
웹 버전 8
- 안내에 따라 Firebase를 웹 앱에 추가합니다.
- Firebase와 Firestore 라이브러리를 앱에 추가합니다.
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-firestore.js"></script>
Firestore SDK는 npm 패키지로도 제공됩니다.npm install firebase@8.10.1 --save
Firebase와 Firestore를 수동으로 요청해야 합니다.const firebase = require("firebase"); // Required for side-effects require("firebase/firestore");
Apple 플랫폼
안내에 따라 Firebase를 Apple 앱에 추가합니다.
Swift Package Manager를 사용해 Firebase 종속 항목을 설치하고 관리하세요.
- 앱 프로젝트를 연 상태로 Xcode에서 File(파일) > Swift Packages(Swift 패키지) > Add Package Dependency(패키지 종속 항목 추가)로 이동합니다.
- 메시지가 표시되면 Firebase Apple 플랫폼 SDK 저장소를 추가합니다.
- Firestore 라이브러리를 선택합니다.
- 완료되면 Xcode가 백그라운드에서 자동으로 종속 항목을 확인하고 다운로드하기 시작합니다.
https://github.com/firebase/firebase-ios-sdk
자바
Android
- 안내에 따라 Firebase를 Android 앱에 추가합니다.
- 모듈 (앱 수준) Gradle 파일 (일반적으로
app/build.gradle
)에서 Firestore Android 라이브러리의 종속 항목을 선언합니다.implementation 'com.google.firebase:firebase-firestore:24.1.2'
앱에서 여러 Firebase 라이브러리를 사용하는 경우 앱의 Firebase 라이브러리 버전이 항상 호환되도록 Firebase Android BoM을 사용하는 것이 좋습니다.
Kotlin+KTX
Android
- 안내에 따라 Firebase를 Android 앱에 추가합니다.
- 모듈 (앱 수준) Gradle 파일 (일반적으로
app/build.gradle
)에서 Firestore Android 라이브러리의 종속 항목을 선언합니다.implementation 'com.google.firebase:firebase-firestore-ktx:24.1.2'
앱에서 여러 Firebase 라이브러리를 사용하는 경우 앱의 Firebase 라이브러리 버전이 항상 호환되도록 Firebase Android BoM을 사용하는 것이 좋습니다.
Dart
- 아직 구성하지 않았다면 Flutter 앱에서 Firebase를 구성하고 초기화합니다.
- Flutter 프로젝트 루트에서 다음 명령어를 실행하여 플러그인을 설치합니다.
flutter pub add cloud_firestore
- 완료되면 Flutter 애플리케이션을 다시 빌드합니다.
flutter run
C++
- 안내에 따라 Firebase를 C++ 프로젝트에 추가합니다.
- Android용 C++ 인터페이스
- Gradle 종속 항목 모듈(앱 수준) Gradle 파일(일반적으로
app/build.gradle
)에 다음을 추가합니다.android.defaultConfig.externalNativeBuild.cmake { arguments "-DFIREBASE_CPP_SDK_DIR=$gradle.firebase_cpp_sdk_dir" } apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle" firebaseCpp.dependencies { // earlier entries auth firestore }
- 바이너리 종속 항목 마찬가지로 바이너리 종속 항목을 가져올 때 권장되는 방법은
CMakeLists.txt
파일에 다음을 추가하는 것입니다.add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL) set(firebase_libs firebase_auth firebase_firestore firebase_app) # Replace the target name below with the actual name of your target, # for example, "native-lib". target_link_libraries(${YOUR_TARGET_NAME_HERE} "${firebase_libs}")
- 데스크톱 통합을 설정하려면 C++ 프로젝트에 Firebase 추가를 참조하세요.
Unity
- 안내에 따라 Firebase를 Unity 프로젝트에 추가합니다.
- Android용 Unity 인터페이스
- File(파일) > Build Settings(빌드 설정)를 선택합니다.
- ‘Platform(플랫폼)’을 ‘Android’로 전환하고 ‘Switch Platform(플랫폼 전환)’을 클릭합니다.
- ‘Player Settings…(플레이어 설정…)'를 클릭합니다.
- 기본 Unity UI의 ‘Settings for Android(Android 설정)’에서 ‘Publishing Settings(게시 설정)’를 선택합니다.
- ‘Minify’ 섹션에서 Release 및 Debug 설정을 ‘None’에서 ‘ProGuard’로 변경합니다.
Android용으로 빌드할 때 Android DEX 제한을 피하려면 ProGuarding을 사용 설정하세요. 이렇게 하려면 Unity 편집기에서 다음을 수행합니다.
Firestore 초기화
Firestore의 인스턴스를 초기화합니다.
웹 버전 9
// Initialize Firestore through Firebase import { initializeApp } from "firebase/app" import { getFirestore } from "firebase/firestore" const firebaseApp = initializeApp({ apiKey: '### FIREBASE API KEY ###', authDomain: '### FIREBASE AUTH DOMAIN ###', projectId: '### CLOUD FIRESTORE PROJECT ID ###' }); const db = getFirestore();`initializeApp`의 값은 웹 앱의 `firebaseConfig`에서 확인할 수 있습니다. 기기의 연결이 끊겨도 데이터를 유지하려면 오프라인 데이터 사용 설정 문서를 참조하세요.
웹 버전 8
// Initialize Firestore through Firebase firebase.initializeApp({ apiKey: '### FIREBASE API KEY ###', authDomain: '### FIREBASE AUTH DOMAIN ###', projectId: '### CLOUD FIRESTORE PROJECT ID ###' }); var db = firebase.firestore();`initializeApp`의 값은 웹 앱의 `firebaseConfig`에서 확인할 수 있습니다. 기기의 연결이 끊겨도 데이터를 유지하려면 오프라인 데이터 사용 설정 문서를 참조하세요.
Swift
import FirebaseCore import FirebaseFirestore FirebaseApp.configure() let db = Firestore.firestore()
Objective-C
@import FirebaseCore; @import FirebaseFirestore; // Use Firebase library to configure APIs [FIRApp configure]; FIRFirestore *defaultFirestore = [FIRFirestore firestore];
자바
Android
// Access a Firestore instance from your Activity FirebaseFirestore db = FirebaseFirestore.getInstance();
Kotlin+KTX
Android
// Access a Firestore instance from your Activity val db = Firebase.firestore
Dart
db = FirebaseFirestore.instance;
C++
// Make sure the call to `Create()` happens some time before you call Firestore::GetInstance(). App::Create(); Firestore* db = Firestore::GetInstance();
Unity
using Firebase.Firestore; using Firebase.Extensions;
FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
데이터 추가
Firestore는 컬렉션에 저장되는 문서에 데이터를 저장합니다. 문서에 데이터를 처음 추가할 때 Firestore는 암시적으로 컬렉션과 문서를 만듭니다. 컬렉션이나 문서를 명시적으로 만들 필요가 없습니다.
다음 예시 코드를 사용해 새 컬렉션과 문서를 만듭니다.
웹 버전 9
import { collection, addDoc } from "firebase/firestore"; try { const docRef = await addDoc(collection(db, "users"), { first: "Ada", last: "Lovelace", born: 1815 }); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); }
웹 버전 8
db.collection("users").add({ first: "Ada", last: "Lovelace", born: 1815 }) .then((docRef) => { console.log("Document written with ID: ", docRef.id); }) .catch((error) => { console.error("Error adding document: ", error); });
Swift
// Add a new document with a generated ID var ref: DocumentReference? = nil ref = db.collection("users").addDocument(data: [ "first": "Ada", "last": "Lovelace", "born": 1815 ]) { err in if let err = err { print("Error adding document: \(err)") } else { print("Document added with ID: \(ref!.documentID)") } }
Objective-C
// Add a new document with a generated ID __block FIRDocumentReference *ref = [[self.db collectionWithPath:@"users"] addDocumentWithData:@{ @"first": @"Ada", @"last": @"Lovelace", @"born": @1815 } completion:^(NSError * _Nullable error) { if (error != nil) { NSLog(@"Error adding document: %@", error); } else { NSLog(@"Document added with ID: %@", ref.documentID); } }];
자바
Android
// Create a new user with a first and last name Map<String, Object> user = new HashMap<>(); user.put("first", "Ada"); user.put("last", "Lovelace"); user.put("born", 1815); // Add a new document with a generated ID db.collection("users") .add(user) .addOnSuccessListener(new OnSuccessListener<DocumentReference>() { @Override public void onSuccess(DocumentReference documentReference) { Log.d(TAG, "DocumentSnapshot added with ID: " + documentReference.getId()); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.w(TAG, "Error adding document", e); } });
Kotlin+KTX
Android
// Create a new user with a first and last name val user = hashMapOf( "first" to "Ada", "last" to "Lovelace", "born" to 1815 ) // Add a new document with a generated ID db.collection("users") .add(user) .addOnSuccessListener { documentReference -> Log.d(TAG, "DocumentSnapshot added with ID: ${documentReference.id}") } .addOnFailureListener { e -> Log.w(TAG, "Error adding document", e) }
Dart
// Create a new user with a first and last name final user = <String, dynamic>{ "first": "Ada", "last": "Lovelace", "born": 1815 }; // Add a new document with a generated ID db.collection("users").add(user).then((DocumentReference doc) => print('DocumentSnapshot added with ID: ${doc.id}'));
C++
// Add a new document with a generated ID Future<DocumentReference> user_ref = db->Collection("users").Add({{"first", FieldValue::String("Ada")}, {"last", FieldValue::String("Lovelace")}, {"born", FieldValue::Integer(1815)}}); user_ref.OnCompletion([](const Future<DocumentReference>& future) { if (future.error() == Error::kErrorOk) { std::cout << "DocumentSnapshot added with ID: " << future.result()->id() << std::endl; } else { std::cout << "Error adding document: " << future.error_message() << std::endl; } });
Unity
DocumentReference docRef = db.Collection("users").Document("alovelace"); Dictionary<string, object> user = new Dictionary<string, object> { { "First", "Ada" }, { "Last", "Lovelace" }, { "Born", 1815 }, }; docRef.SetAsync(user).ContinueWithOnMainThread(task => { Debug.Log("Added data to the alovelace document in the users collection."); });
이제 users
컬렉션에 다른 문서를 추가합니다. 첫 번째 문서에는 나타나지 않는 키-값 쌍(중간 이름)이 문서에 포함된다는 점에 유의하세요. 컬렉션의 문서에는 다른 정보 집합이 포함될 수 있습니다.
웹 버전 9
// Add a second document with a generated ID. import { addDoc, collection } from "firebase/firestore"; try { const docRef = await addDoc(collection(db, "users"), { first: "Alan", middle: "Mathison", last: "Turing", born: 1912 }); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); }
웹 버전 8
// Add a second document with a generated ID. db.collection("users").add({ first: "Alan", middle: "Mathison", last: "Turing", born: 1912 }) .then((docRef) => { console.log("Document written with ID: ", docRef.id); }) .catch((error) => { console.error("Error adding document: ", error); });
Swift
// Add a second document with a generated ID. ref = db.collection("users").addDocument(data: [ "first": "Alan", "middle": "Mathison", "last": "Turing", "born": 1912 ]) { err in if let err = err { print("Error adding document: \(err)") } else { print("Document added with ID: \(ref!.documentID)") } }
Objective-C
// Add a second document with a generated ID. __block FIRDocumentReference *ref = [[self.db collectionWithPath:@"users"] addDocumentWithData:@{ @"first": @"Alan", @"middle": @"Mathison", @"last": @"Turing", @"born": @1912 } completion:^(NSError * _Nullable error) { if (error != nil) { NSLog(@"Error adding document: %@", error); } else { NSLog(@"Document added with ID: %@", ref.documentID); } }];
자바
Android
// Create a new user with a first, middle, and last name Map<String, Object> user = new HashMap<>(); user.put("first", "Alan"); user.put("middle", "Mathison"); user.put("last", "Turing"); user.put("born", 1912); // Add a new document with a generated ID db.collection("users") .add(user) .addOnSuccessListener(new OnSuccessListener<DocumentReference>() { @Override public void onSuccess(DocumentReference documentReference) { Log.d(TAG, "DocumentSnapshot added with ID: " + documentReference.getId()); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.w(TAG, "Error adding document", e); } });
Kotlin+KTX
Android
// Create a new user with a first, middle, and last name val user = hashMapOf( "first" to "Alan", "middle" to "Mathison", "last" to "Turing", "born" to 1912 ) // Add a new document with a generated ID db.collection("users") .add(user) .addOnSuccessListener { documentReference -> Log.d(TAG, "DocumentSnapshot added with ID: ${documentReference.id}") } .addOnFailureListener { e -> Log.w(TAG, "Error adding document", e) }
Dart
// Create a new user with a first and last name final user = <String, dynamic>{ "first": "Alan", "middle": "Mathison", "last": "Turing", "born": 1912 }; // Add a new document with a generated ID db.collection("users").add(user).then((DocumentReference doc) => print('DocumentSnapshot added with ID: ${doc.id}'));
C++
db->Collection("users") .Add({{"first", FieldValue::String("Alan")}, {"middle", FieldValue::String("Mathison")}, {"last", FieldValue::String("Turing")}, {"born", FieldValue::Integer(1912)}}) .OnCompletion([](const Future<DocumentReference>& future) { if (future.error() == Error::kErrorOk) { std::cout << "DocumentSnapshot added with ID: " << future.result()->id() << std::endl; } else { std::cout << "Error adding document: " << future.error_message() << std::endl; } });
Unity
DocumentReference docRef = db.Collection("users").Document("aturing"); Dictionary<string, object> user = new Dictionary<string, object> { { "First", "Alan" }, { "Middle", "Mathison" }, { "Last", "Turing" }, { "Born", 1912 } }; docRef.SetAsync(user).ContinueWithOnMainThread(task => { Debug.Log("Added data to the aturing document in the users collection."); });
데이터 읽기
Firestore에 추가한 데이터를 빠르게 확인하려면 Firebase Console의 데이터 뷰어를 사용합니다.
get
메서드를 사용하여 전체 컬렉션을 검색할 수도 있습니다.
웹 버전 9
import { collection, getDocs } from "firebase/firestore"; const querySnapshot = await getDocs(collection(db, "users")); querySnapshot.forEach((doc) => { console.log(`${doc.id} => ${doc.data()}`); });
웹 버전 8
db.collection("users").get().then((querySnapshot) => { querySnapshot.forEach((doc) => { console.log(`${doc.id} => ${doc.data()}`); }); });
Swift
db.collection("users").getDocuments() { (querySnapshot, err) in if let err = err { print("Error getting documents: \(err)") } else { for document in querySnapshot!.documents { print("\(document.documentID) => \(document.data())") } } }
Objective-C
[[self.db collectionWithPath:@"users"] getDocumentsWithCompletion:^(FIRQuerySnapshot * _Nullable snapshot, NSError * _Nullable error) { if (error != nil) { NSLog(@"Error getting documents: %@", error); } else { for (FIRDocumentSnapshot *document in snapshot.documents) { NSLog(@"%@ => %@", document.documentID, document.data); } } }];
자바
Android
db.collection("users") .get() .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if (task.isSuccessful()) { for (QueryDocumentSnapshot document : task.getResult()) { Log.d(TAG, document.getId() + " => " + document.getData()); } } else { Log.w(TAG, "Error getting documents.", task.getException()); } } });
Kotlin+KTX
Android
db.collection("users") .get() .addOnSuccessListener { result -> for (document in result) { Log.d(TAG, "${document.id} => ${document.data}") } } .addOnFailureListener { exception -> Log.w(TAG, "Error getting documents.", exception) }
Dart
await db.collection("users").get().then((event) { for (var doc in event.docs) { print("${doc.id} => ${doc.data()}"); } });
C++
Future<QuerySnapshot> users = db->Collection("users").Get(); users.OnCompletion([](const Future<QuerySnapshot>& future) { if (future.error() == Error::kErrorOk) { for (const DocumentSnapshot& document : future.result()->documents()) { std::cout << document << std::endl; } } else { std::cout << "Error getting documents: " << future.error_message() << std::endl; } });
Unity
CollectionReference usersRef = db.Collection("users"); usersRef.GetSnapshotAsync().ContinueWithOnMainThread(task => { QuerySnapshot snapshot = task.Result; foreach (DocumentSnapshot document in snapshot.Documents) { Debug.Log(String.Format("User: {0}", document.Id)); Dictionary<string, object> documentDictionary = document.ToDictionary(); Debug.Log(String.Format("First: {0}", documentDictionary["First"])); if (documentDictionary.ContainsKey("Middle")) { Debug.Log(String.Format("Middle: {0}", documentDictionary["Middle"])); } Debug.Log(String.Format("Last: {0}", documentDictionary["Last"])); Debug.Log(String.Format("Born: {0}", documentDictionary["Born"])); } Debug.Log("Read all data from the users collection."); });
데이터 보안
Firebase 인증과 Firestore 보안 규칙을 사용하여 Firestore의 데이터를 보호합니다.
다음은 시작하는 데 사용할 수 있는 기본 규칙 세트입니다. Firebase Console의 규칙 탭에서 보안 규칙을 수정할 수 있습니다.
인증 필요
// Allow read/write access on all documents to any user signed in to the application
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
잠금 모드
// Deny read/write access to all users under any conditions
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
테스트 모드
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this rule set in production; it allows
// anyone to overwrite your entire database.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
웹, Android 또는 iOS 앱을 프로덕션에 배포하기 전에 앱 클라이언트만 Firestore 데이터에 액세스할 수 있도록 하는 단계를 수행합니다. 앱 체크 문서를 참조하세요.
동영상 가이드 보기
Firestore 모바일 및 웹 클라이언트 라이브러리 시작하기에 대한 자세한 안내는 다음 동영상 가이드 중 하나를 참조하세요.
웹
iOS
Android
그 밖에도 많은 동영상을 Firebase YouTube 채널에서 확인할 수 있습니다.
다음 단계
다음 주제를 자세히 알아보세요.
- Codelab - Android, iOS 또는 웹용 Codelab의 안내를 따라 실제 앱에서 Firestore를 사용하는 방법을 알아보세요.
- 데이터 모델 - 계층적 데이터와 하위 컬렉션을 비롯한 Firestore에서 데이터가 구조화되는 방식을 자세히 알아보세요.
- 데이터 추가 - Firestore에서 데이터를 만들고 업데이트하는 방법을 자세히 알아보세요.
- 데이터 가져오기 - 데이터를 검색하는 방법을 자세히 알아보세요.
- 단순 쿼리 및 복합 쿼리 실행 - 단순 쿼리 및 복합 쿼리 실행 방법을 알아보세요.
- 쿼리 순서 지정 및 제한 - 쿼리에서 반환된 데이터의 순서를 지정하고 제한하는 방법을 알아보세요.