Cloud Firestore에 저장된 데이터 검색 방법에는 세 가지가 있습니다. 문서, 문서 컬렉션 또는 쿼리 결과에 다음 메서드 중 하나를 사용할 수 있습니다.
- 메서드를 호출하여 데이터를 한 번 가져옵니다.
- 데이터 변경 이벤트를 수신하는 리스너를 설정합니다.
- 데이터 번들을 통해 외부 소스에서 Firestore 스냅샷 데이터를 일괄 로드합니다. 자세한 내용은 번들 문서를 참조하세요.
리스너를 설정하면 Cloud Firestore는 리스너에 데이터의 초기 스냅샷을 전송한 후 문서가 변경될 때마다 다른 스냅샷을 전송합니다.
시작하기 전에
Cloud Firestore 데이터베이스를 만들려면 Cloud Firestore 시작하기를 참조하세요.Cloud Firestore 초기화
Cloud Firestore의 인스턴스를 초기화합니다.
Web
import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; // TODO: Replace the following with your app's Firebase project configuration // See: https://support.google.com/firebase/answer/7015592 const firebaseConfig = { FIREBASE_CONFIGURATION }; // Initialize Firebase const app = initializeApp(firebaseConfig); // Initialize Cloud Firestore and get a reference to the service const db = getFirestore(app);
FIREBASE_CONFIGURATION을 웹 앱의 firebaseConfig
로 바꿉니다.
기기의 연결이 끊겨도 데이터를 유지하려면 오프라인 데이터 사용 설정 문서를 참조하세요.
Web
import firebase from "firebase/app"; import "firebase/firestore"; // TODO: Replace the following with your app's Firebase project configuration // See: https://support.google.com/firebase/answer/7015592 const firebaseConfig = { FIREBASE_CONFIGURATION }; // Initialize Firebase firebase.initializeApp(firebaseConfig); // Initialize Cloud Firestore and get a reference to the service const db = firebase.firestore();
FIREBASE_CONFIGURATION을 웹 앱의 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];
Kotlin
// Access a Cloud Firestore instance from your Activity
val db = Firebase.firestore
Java
// Access a Cloud Firestore instance from your Activity
FirebaseFirestore db = FirebaseFirestore.getInstance();
Dart
db = FirebaseFirestore.instance;
자바
Cloud Firestore SDK는 환경에 따라 다양한 방식으로 초기화됩니다. 가장 일반적인 방법은 아래와 같습니다. 전체 참조를 보려면 Admin SDK 초기화를 참조하세요.import com.google.auth.oauth2.GoogleCredentials; import com.google.cloud.firestore.Firestore; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; // Use the application default credentials GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); FirebaseOptions options = new FirebaseOptions.Builder() .setCredentials(credentials) .setProjectId(projectId) .build(); FirebaseApp.initializeApp(options); Firestore db = FirestoreClient.getFirestore();
자체 서버에서 Firebase Admin SDK를 사용하려면 서비스 계정을 사용합니다.
Google Cloud 콘솔에서 IAM 및 관리자 > 서비스 계정으로 이동합니다. 새 비공개 키를 생성하고 JSON 파일을 저장합니다. 그런 다음 이 파일을 사용하여 SDK를 초기화합니다.
import com.google.auth.oauth2.GoogleCredentials; import com.google.cloud.firestore.Firestore; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; // Use a service account InputStream serviceAccount = new FileInputStream("path/to/serviceAccount.json"); GoogleCredentials credentials = GoogleCredentials.fromStream(serviceAccount); FirebaseOptions options = new FirebaseOptions.Builder() .setCredentials(credentials) .build(); FirebaseApp.initializeApp(options); Firestore db = FirestoreClient.getFirestore();
Python
Cloud Firestore SDK는 환경에 따라 다양한 방식으로 초기화됩니다. 가장 일반적인 방법은 아래와 같습니다. 전체 참조를 보려면 Admin SDK 초기화를 참조하세요.import firebase_admin from firebase_admin import firestore # Application Default credentials are automatically created. app = firebase_admin.initialize_app() db = firestore.client()
기존 애플리케이션 기본 사용자 인증 정보를 사용하여 SDK를 초기화할 수도 있습니다.
import firebase_admin from firebase_admin import credentials from firebase_admin import firestore # Use the application default credentials. cred = credentials.ApplicationDefault() firebase_admin.initialize_app(cred) db = firestore.client()
자체 서버에서 Firebase Admin SDK를 사용하려면 서비스 계정을 사용합니다.
Google Cloud 콘솔에서 IAM 및 관리자 > 서비스 계정으로 이동합니다. 새 비공개 키를 생성하고 JSON 파일을 저장합니다. 그런 다음 이 파일을 사용하여 SDK를 초기화합니다.
import firebase_admin from firebase_admin import credentials from firebase_admin import firestore # Use a service account. cred = credentials.Certificate('path/to/serviceAccount.json') app = firebase_admin.initialize_app(cred) db = firestore.client()
Python
Cloud Firestore SDK는 환경에 따라 다양한 방식으로 초기화됩니다. 가장 일반적인 방법은 아래와 같습니다. 전체 참조를 보려면 Admin SDK 초기화를 참조하세요.import firebase_admin from firebase_admin import firestore_async # Application Default credentials are automatically created. app = firebase_admin.initialize_app() db = firestore_async.client()
기존 애플리케이션 기본 사용자 인증 정보를 사용하여 SDK를 초기화할 수도 있습니다.
import firebase_admin from firebase_admin import credentials from firebase_admin import firestore_async # Use the application default credentials. cred = credentials.ApplicationDefault() firebase_admin.initialize_app(cred) db = firestore_async.client()
자체 서버에서 Firebase Admin SDK를 사용하려면 서비스 계정을 사용합니다.
Google Cloud 콘솔에서 IAM 및 관리자 > 서비스 계정으로 이동합니다. 새 비공개 키를 생성하고 JSON 파일을 저장합니다. 그런 다음 이 파일을 사용하여 SDK를 초기화합니다.
import firebase_admin from firebase_admin import credentials from firebase_admin import firestore_async # Use a service account. cred = credentials.Certificate('path/to/serviceAccount.json') app = firebase_admin.initialize_app(cred) db = firestore_async.client()
C++
// Make sure the call to `Create()` happens some time before you call Firestore::GetInstance(). App::Create(); Firestore* db = Firestore::GetInstance();
Node.js
Cloud Firestore SDK는 환경에 따라 다양한 방식으로 초기화됩니다. 가장 일반적인 방법은 아래와 같습니다. 전체 참조를 보려면 Admin SDK 초기화를 참조하세요.- Cloud Functions에서 초기화
const { initializeApp, applicationDefault, cert } = require('firebase-admin/app'); const { getFirestore, Timestamp, FieldValue, Filter } = require('firebase-admin/firestore');
initializeApp(); const db = getFirestore();
- Google Cloud에서 초기화
const { initializeApp, applicationDefault, cert } = require('firebase-admin/app'); const { getFirestore, Timestamp, FieldValue, Filter } = require('firebase-admin/firestore');
initializeApp({ credential: applicationDefault() }); const db = getFirestore();
- 자체 서버에서 초기화
자체 서버(또는 다른 Node.js 환경)에서 Firebase Admin SDK를 사용하려면 서비스 계정을 사용합니다. Google Cloud 콘솔에서 IAM 및 관리자 > 서비스 계정으로 이동합니다. 새 비공개 키를 생성하고 JSON 파일을 저장합니다. 그런 다음 이 파일을 사용하여 SDK를 초기화합니다.
const { initializeApp, applicationDefault, cert } = require('firebase-admin/app'); const { getFirestore, Timestamp, FieldValue, Filter } = require('firebase-admin/firestore');
const serviceAccount = require('./path/to/serviceAccountKey.json'); initializeApp({ credential: cert(serviceAccount) }); const db = getFirestore();
Go
Cloud Firestore SDK는 환경에 따라 다양한 방식으로 초기화됩니다. 가장 일반적인 방법은 아래와 같습니다. 전체 참조를 보려면 Admin SDK 초기화를 참조하세요.import ( "log" firebase "firebase.google.com/go" "google.golang.org/api/option" ) // Use the application default credentials ctx := context.Background() conf := &firebase.Config{ProjectID: projectID} app, err := firebase.NewApp(ctx, conf) if err != nil { log.Fatalln(err) } client, err := app.Firestore(ctx) if err != nil { log.Fatalln(err) } defer client.Close()
자체 서버에서 Firebase Admin SDK를 사용하려면 서비스 계정을 사용합니다.
Google Cloud 콘솔에서 IAM 및 관리자 > 서비스 계정으로 이동합니다. 새 비공개 키를 생성하고 JSON 파일을 저장합니다. 그런 다음 이 파일을 사용하여 SDK를 초기화합니다.
import ( "log" firebase "firebase.google.com/go" "google.golang.org/api/option" ) // Use a service account ctx := context.Background() sa := option.WithCredentialsFile("path/to/serviceAccount.json") app, err := firebase.NewApp(ctx, nil, sa) if err != nil { log.Fatalln(err) } client, err := app.Firestore(ctx) if err != nil { log.Fatalln(err) } defer client.Close()
PHP
PHP
Cloud Firestore 클라이언트 설치 및 생성에 관한 자세한 내용은 Cloud Firestore 클라이언트 라이브러리를 참조하세요.
Unity
using Firebase.Firestore; using Firebase.Extensions;
FirebaseFirestore db = FirebaseFirestore.DefaultInstance;
C#
C#
Cloud Firestore 클라이언트 설치 및 생성에 관한 자세한 내용은 Cloud Firestore 클라이언트 라이브러리를 참조하세요.
Ruby
예시 데이터
우선 도시에 관한 데이터를 작성하고 다양한 방식으로 이 데이터를 불러오는 방법에 대해 살펴보세요.
Web
import { collection, doc, setDoc } from "firebase/firestore"; const citiesRef = collection(db, "cities"); await setDoc(doc(citiesRef, "SF"), { name: "San Francisco", state: "CA", country: "USA", capital: false, population: 860000, regions: ["west_coast", "norcal"] }); await setDoc(doc(citiesRef, "LA"), { name: "Los Angeles", state: "CA", country: "USA", capital: false, population: 3900000, regions: ["west_coast", "socal"] }); await setDoc(doc(citiesRef, "DC"), { name: "Washington, D.C.", state: null, country: "USA", capital: true, population: 680000, regions: ["east_coast"] }); await setDoc(doc(citiesRef, "TOK"), { name: "Tokyo", state: null, country: "Japan", capital: true, population: 9000000, regions: ["kanto", "honshu"] }); await setDoc(doc(citiesRef, "BJ"), { name: "Beijing", state: null, country: "China", capital: true, population: 21500000, regions: ["jingjinji", "hebei"] });
Web
var citiesRef = db.collection("cities"); citiesRef.doc("SF").set({ name: "San Francisco", state: "CA", country: "USA", capital: false, population: 860000, regions: ["west_coast", "norcal"] }); citiesRef.doc("LA").set({ name: "Los Angeles", state: "CA", country: "USA", capital: false, population: 3900000, regions: ["west_coast", "socal"] }); citiesRef.doc("DC").set({ name: "Washington, D.C.", state: null, country: "USA", capital: true, population: 680000, regions: ["east_coast"] }); citiesRef.doc("TOK").set({ name: "Tokyo", state: null, country: "Japan", capital: true, population: 9000000, regions: ["kanto", "honshu"] }); citiesRef.doc("BJ").set({ name: "Beijing", state: null, country: "China", capital: true, population: 21500000, regions: ["jingjinji", "hebei"] });
Swift
let citiesRef = db.collection("cities") citiesRef.document("SF").setData([ "name": "San Francisco", "state": "CA", "country": "USA", "capital": false, "population": 860000, "regions": ["west_coast", "norcal"] ]) citiesRef.document("LA").setData([ "name": "Los Angeles", "state": "CA", "country": "USA", "capital": false, "population": 3900000, "regions": ["west_coast", "socal"] ]) citiesRef.document("DC").setData([ "name": "Washington D.C.", "country": "USA", "capital": true, "population": 680000, "regions": ["east_coast"] ]) citiesRef.document("TOK").setData([ "name": "Tokyo", "country": "Japan", "capital": true, "population": 9000000, "regions": ["kanto", "honshu"] ]) citiesRef.document("BJ").setData([ "name": "Beijing", "country": "China", "capital": true, "population": 21500000, "regions": ["jingjinji", "hebei"] ])
Objective-C
FIRCollectionReference *citiesRef = [self.db collectionWithPath:@"cities"]; [[citiesRef documentWithPath:@"SF"] setData:@{ @"name": @"San Francisco", @"state": @"CA", @"country": @"USA", @"capital": @(NO), @"population": @860000, @"regions": @[@"west_coast", @"norcal"] }]; [[citiesRef documentWithPath:@"LA"] setData:@{ @"name": @"Los Angeles", @"state": @"CA", @"country": @"USA", @"capital": @(NO), @"population": @3900000, @"regions": @[@"west_coast", @"socal"] }]; [[citiesRef documentWithPath:@"DC"] setData:@{ @"name": @"Washington D.C.", @"country": @"USA", @"capital": @(YES), @"population": @680000, @"regions": @[@"east_coast"] }]; [[citiesRef documentWithPath:@"TOK"] setData:@{ @"name": @"Tokyo", @"country": @"Japan", @"capital": @(YES), @"population": @9000000, @"regions": @[@"kanto", @"honshu"] }]; [[citiesRef documentWithPath:@"BJ"] setData:@{ @"name": @"Beijing", @"country": @"China", @"capital": @(YES), @"population": @21500000, @"regions": @[@"jingjinji", @"hebei"] }];
Kotlin
val cities = db.collection("cities") val data1 = hashMapOf( "name" to "San Francisco", "state" to "CA", "country" to "USA", "capital" to false, "population" to 860000, "regions" to listOf("west_coast", "norcal"), ) cities.document("SF").set(data1) val data2 = hashMapOf( "name" to "Los Angeles", "state" to "CA", "country" to "USA", "capital" to false, "population" to 3900000, "regions" to listOf("west_coast", "socal"), ) cities.document("LA").set(data2) val data3 = hashMapOf( "name" to "Washington D.C.", "state" to null, "country" to "USA", "capital" to true, "population" to 680000, "regions" to listOf("east_coast"), ) cities.document("DC").set(data3) val data4 = hashMapOf( "name" to "Tokyo", "state" to null, "country" to "Japan", "capital" to true, "population" to 9000000, "regions" to listOf("kanto", "honshu"), ) cities.document("TOK").set(data4) val data5 = hashMapOf( "name" to "Beijing", "state" to null, "country" to "China", "capital" to true, "population" to 21500000, "regions" to listOf("jingjinji", "hebei"), ) cities.document("BJ").set(data5)
Java
CollectionReference cities = db.collection("cities"); Map<String, Object> data1 = new HashMap<>(); data1.put("name", "San Francisco"); data1.put("state", "CA"); data1.put("country", "USA"); data1.put("capital", false); data1.put("population", 860000); data1.put("regions", Arrays.asList("west_coast", "norcal")); cities.document("SF").set(data1); Map<String, Object> data2 = new HashMap<>(); data2.put("name", "Los Angeles"); data2.put("state", "CA"); data2.put("country", "USA"); data2.put("capital", false); data2.put("population", 3900000); data2.put("regions", Arrays.asList("west_coast", "socal")); cities.document("LA").set(data2); Map<String, Object> data3 = new HashMap<>(); data3.put("name", "Washington D.C."); data3.put("state", null); data3.put("country", "USA"); data3.put("capital", true); data3.put("population", 680000); data3.put("regions", Arrays.asList("east_coast")); cities.document("DC").set(data3); Map<String, Object> data4 = new HashMap<>(); data4.put("name", "Tokyo"); data4.put("state", null); data4.put("country", "Japan"); data4.put("capital", true); data4.put("population", 9000000); data4.put("regions", Arrays.asList("kanto", "honshu")); cities.document("TOK").set(data4); Map<String, Object> data5 = new HashMap<>(); data5.put("name", "Beijing"); data5.put("state", null); data5.put("country", "China"); data5.put("capital", true); data5.put("population", 21500000); data5.put("regions", Arrays.asList("jingjinji", "hebei")); cities.document("BJ").set(data5);
Dart
final cities = db.collection("cities"); final data1 = <String, dynamic>{ "name": "San Francisco", "state": "CA", "country": "USA", "capital": false, "population": 860000, "regions": ["west_coast", "norcal"] }; cities.doc("SF").set(data1); final data2 = <String, dynamic>{ "name": "Los Angeles", "state": "CA", "country": "USA", "capital": false, "population": 3900000, "regions": ["west_coast", "socal"], }; cities.doc("LA").set(data2); final data3 = <String, dynamic>{ "name": "Washington D.C.", "state": null, "country": "USA", "capital": true, "population": 680000, "regions": ["east_coast"] }; cities.doc("DC").set(data3); final data4 = <String, dynamic>{ "name": "Tokyo", "state": null, "country": "Japan", "capital": true, "population": 9000000, "regions": ["kanto", "honshu"] }; cities.doc("TOK").set(data4); final data5 = <String, dynamic>{ "name": "Beijing", "state": null, "country": "China", "capital": true, "population": 21500000, "regions": ["jingjinji", "hebei"], }; cities.doc("BJ").set(data5);
자바
Python
class City: def __init__(self, name, state, country, capital=False, population=0, regions=[]): self.name = name self.state = state self.country = country self.capital = capital self.population = population self.regions = regions @staticmethod def from_dict(source): # ... def to_dict(self): # ... def __repr__(self): return f"City(\ name={self.name}, \ country={self.country}, \ population={self.population}, \ capital={self.capital}, \ regions={self.regions}\ )"
cities_ref = db.collection("cities") cities_ref.document("BJ").set( City("Beijing", None, "China", True, 21500000, ["hebei"]).to_dict() ) cities_ref.document("SF").set( City( "San Francisco", "CA", "USA", False, 860000, ["west_coast", "norcal"] ).to_dict() ) cities_ref.document("LA").set( City( "Los Angeles", "CA", "USA", False, 3900000, ["west_coast", "socal"] ).to_dict() ) cities_ref.document("DC").set( City("Washington D.C.", None, "USA", True, 680000, ["east_coast"]).to_dict() ) cities_ref.document("TOK").set( City("Tokyo", None, "Japan", True, 9000000, ["kanto", "honshu"]).to_dict() )
Python
C++
CollectionReference cities = db->Collection("cities"); cities.Document("SF").Set({ {"name", FieldValue::String("San Francisco")}, {"state", FieldValue::String("CA")}, {"country", FieldValue::String("USA")}, {"capital", FieldValue::Boolean(false)}, {"population", FieldValue::Integer(860000)}, {"regions", FieldValue::Array({FieldValue::String("west_coast"), FieldValue::String("norcal")})}, }); cities.Document("LA").Set({ {"name", FieldValue::String("Los Angeles")}, {"state", FieldValue::String("CA")}, {"country", FieldValue::String("USA")}, {"capital", FieldValue::Boolean(false)}, {"population", FieldValue::Integer(3900000)}, {"regions", FieldValue::Array({FieldValue::String("west_coast"), FieldValue::String("socal")})}, }); cities.Document("DC").Set({ {"name", FieldValue::String("Washington D.C.")}, {"state", FieldValue::Null()}, {"country", FieldValue::String("USA")}, {"capital", FieldValue::Boolean(true)}, {"population", FieldValue::Integer(680000)}, {"regions", FieldValue::Array({FieldValue::String("east_coast")})}, }); cities.Document("TOK").Set({ {"name", FieldValue::String("Tokyo")}, {"state", FieldValue::Null()}, {"country", FieldValue::String("Japan")}, {"capital", FieldValue::Boolean(true)}, {"population", FieldValue::Integer(9000000)}, {"regions", FieldValue::Array({FieldValue::String("kanto"), FieldValue::String("honshu")})}, }); cities.Document("BJ").Set({ {"name", FieldValue::String("Beijing")}, {"state", FieldValue::Null()}, {"country", FieldValue::String("China")}, {"capital", FieldValue::Boolean(true)}, {"population", FieldValue::Integer(21500000)}, {"regions", FieldValue::Array({FieldValue::String("jingjinji"), FieldValue::String("hebei")})}, });
Node.js
Go
PHP
PHP
Cloud Firestore 클라이언트 설치 및 생성에 관한 자세한 내용은 Cloud Firestore 클라이언트 라이브러리를 참조하세요.
Unity
CollectionReference citiesRef = db.Collection("cities"); citiesRef.Document("SF").SetAsync(new Dictionary<string, object>(){ { "Name", "San Francisco" }, { "State", "CA" }, { "Country", "USA" }, { "Capital", false }, { "Population", 860000 } }).ContinueWithOnMainThread(task => citiesRef.Document("LA").SetAsync(new Dictionary<string, object>(){ { "Name", "Los Angeles" }, { "State", "CA" }, { "Country", "USA" }, { "Capital", false }, { "Population", 3900000 } }) ).ContinueWithOnMainThread(task => citiesRef.Document("DC").SetAsync(new Dictionary<string, object>(){ { "Name", "Washington D.C." }, { "State", null }, { "Country", "USA" }, { "Capital", true }, { "Population", 680000 } }) ).ContinueWithOnMainThread(task => citiesRef.Document("TOK").SetAsync(new Dictionary<string, object>(){ { "Name", "Tokyo" }, { "State", null }, { "Country", "Japan" }, { "Capital", true }, { "Population", 9000000 } }) ).ContinueWithOnMainThread(task => citiesRef.Document("BJ").SetAsync(new Dictionary<string, object>(){ { "Name", "Beijing" }, { "State", null }, { "Country", "China" }, { "Capital", true }, { "Population", 21500000 } }) );
C#
Ruby
문서 가져오기
다음 예시에서는 get()
을 사용하여 단일 문서의 내용을 검색하는 방법을 보여줍니다.
Web
import { doc, getDoc } from "firebase/firestore"; const docRef = doc(db, "cities", "SF"); const docSnap = await getDoc(docRef); if (docSnap.exists()) { console.log("Document data:", docSnap.data()); } else { // docSnap.data() will be undefined in this case console.log("No such document!"); }
Web
var docRef = db.collection("cities").doc("SF"); docRef.get().then((doc) => { if (doc.exists) { console.log("Document data:", doc.data()); } else { // doc.data() will be undefined in this case console.log("No such document!"); } }).catch((error) => { console.log("Error getting document:", error); });
Swift
let docRef = db.collection("cities").document("SF") do { let document = try await docRef.getDocument() if document.exists { let dataDescription = document.data().map(String.init(describing:)) ?? "nil" print("Document data: \(dataDescription)") } else { print("Document does not exist") } } catch { print("Error getting document: \(error)") }
Objective-C
FIRDocumentReference *docRef = [[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"]; [docRef getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) { if (snapshot.exists) { // Document data may be nil if the document exists but has no keys or values. NSLog(@"Document data: %@", snapshot.data); } else { NSLog(@"Document does not exist"); } }];
Kotlin
val docRef = db.collection("cities").document("SF") docRef.get() .addOnSuccessListener { document -> if (document != null) { Log.d(TAG, "DocumentSnapshot data: ${document.data}") } else { Log.d(TAG, "No such document") } } .addOnFailureListener { exception -> Log.d(TAG, "get failed with ", exception) }
Java
DocumentReference docRef = db.collection("cities").document("SF"); docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() { @Override public void onComplete(@NonNull Task<DocumentSnapshot> task) { if (task.isSuccessful()) { DocumentSnapshot document = task.getResult(); if (document.exists()) { Log.d(TAG, "DocumentSnapshot data: " + document.getData()); } else { Log.d(TAG, "No such document"); } } else { Log.d(TAG, "get failed with ", task.getException()); } } });
Dart
final docRef = db.collection("cities").doc("SF"); docRef.get().then( (DocumentSnapshot doc) { final data = doc.data() as Map<String, dynamic>; // ... }, onError: (e) => print("Error getting document: $e"), );
자바
Python
Python
C++
DocumentReference doc_ref = db->Collection("cities").Document("SF"); doc_ref.Get().OnCompletion([](const Future<DocumentSnapshot>& future) { if (future.error() == Error::kErrorOk) { const DocumentSnapshot& document = *future.result(); if (document.exists()) { std::cout << "DocumentSnapshot id: " << document.id() << std::endl; } else { std::cout << "no such document" << std::endl; } } else { std::cout << "Get failed with: " << future.error_message() << std::endl; } });
Node.js
Go
PHP
PHP
Cloud Firestore 클라이언트 설치 및 생성에 관한 자세한 내용은 Cloud Firestore 클라이언트 라이브러리를 참조하세요.
Unity
DocumentReference docRef = db.Collection("cities").Document("SF"); docRef.GetSnapshotAsync().ContinueWithOnMainThread(task => { DocumentSnapshot snapshot = task.Result; if (snapshot.Exists) { Debug.Log(String.Format("Document data for {0} document:", snapshot.Id)); Dictionary<string, object> city = snapshot.ToDictionary(); foreach (KeyValuePair<string, object> pair in city) { Debug.Log(String.Format("{0}: {1}", pair.Key, pair.Value)); } } else { Debug.Log(String.Format("Document {0} does not exist!", snapshot.Id)); } });
C#
Ruby
소스 옵션
오프라인에서 작동되는 플랫폼의 경우 source
옵션을 설정하여 get
호출이 오프라인 캐시를 사용하는 방법을 제어할 수 있습니다.
기본적으로 get
호출은 데이터베이스에서 최신 문서 스냅샷 가져오기를 시도합니다. 오프라인 작동이 지원되는 플랫폼에서 클라이언트 라이브러리가 네트워크를 사용할 수 없거나 요청 시간이 초과되면 오프라인 캐시를 사용합니다.
get()
호출에서 source
옵션을 지정하면 기본 동작을 변경할 수 있습니다. 데이터베이스에서만 가져와서 오프라인 캐시를 무시하거나 오프라인 캐시에서만 가져올 수 있습니다. 예를 들면 다음과 같습니다.
Web
import { doc, getDocFromCache } from "firebase/firestore"; const docRef = doc(db, "cities", "SF"); // Get a document, forcing the SDK to fetch from the offline cache. try { const doc = await getDocFromCache(docRef); // Document was found in the cache. If no cached document exists, // an error will be returned to the 'catch' block below. console.log("Cached document data:", doc.data()); } catch (e) { console.log("Error getting cached document:", e); }
Web
var docRef = db.collection("cities").doc("SF"); // Valid options for source are 'server', 'cache', or // 'default'. See https://firebase.google.com/docs/reference/js/v8/firebase.firestore.GetOptions // for more information. var getOptions = { source: 'cache' }; // Get a document, forcing the SDK to fetch from the offline cache. docRef.get(getOptions).then((doc) => { // Document was found in the cache. If no cached document exists, // an error will be returned to the 'catch' block below. console.log("Cached document data:", doc.data()); }).catch((error) => { console.log("Error getting cached document:", error); });
Swift
let docRef = db.collection("cities").document("SF") do { // Force the SDK to fetch the document from the cache. Could also specify // FirestoreSource.server or FirestoreSource.default. let document = try await docRef.getDocument(source: .cache) if document.exists { let dataDescription = document.data().map(String.init(describing:)) ?? "nil" print("Cached document data: \(dataDescription)") } else { print("Document does not exist in cache") } } catch { print("Error getting document: \(error)") }
Objective-C
FIRDocumentReference *docRef = [[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"]; // Force the SDK to fetch the document from the cache. Could also specify // FIRFirestoreSourceServer or FIRFirestoreSourceDefault. [docRef getDocumentWithSource:FIRFirestoreSourceCache completion:^(FIRDocumentSnapshot *snapshot, NSError *error) { if (snapshot != NULL) { // The document data was found in the cache. NSLog(@"Cached document data: %@", snapshot.data); } else { // The document data was not found in the cache. NSLog(@"Document does not exist in cache: %@", error); } }];
Kotlin
val docRef = db.collection("cities").document("SF") // Source can be CACHE, SERVER, or DEFAULT. val source = Source.CACHE // Get the document, forcing the SDK to use the offline cache docRef.get(source).addOnCompleteListener { task -> if (task.isSuccessful) { // Document found in the offline cache val document = task.result Log.d(TAG, "Cached document data: ${document?.data}") } else { Log.d(TAG, "Cached get failed: ", task.exception) } }
Java
DocumentReference docRef = db.collection("cities").document("SF"); // Source can be CACHE, SERVER, or DEFAULT. Source source = Source.CACHE; // Get the document, forcing the SDK to use the offline cache docRef.get(source).addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() { @Override public void onComplete(@NonNull Task<DocumentSnapshot> task) { if (task.isSuccessful()) { // Document found in the offline cache DocumentSnapshot document = task.getResult(); Log.d(TAG, "Cached document data: " + document.getData()); } else { Log.d(TAG, "Cached get failed: ", task.getException()); } } });
Dart
final docRef = db.collection("cities").doc("SF"); // Source can be CACHE, SERVER, or DEFAULT. const source = Source.cache; docRef.get(const GetOptions(source: source)).then( (res) => print("Successfully completed"), onError: (e) => print("Error completing: $e"), );
자바
자바 SDK에서는 지원되지 않습니다.
Python
Python SDK에서는 지원되지 않습니다.
C++
DocumentReference doc_ref = db->Collection("cities").Document("SF"); Source source = Source::kCache; doc_ref.Get(source).OnCompletion([](const Future<DocumentSnapshot>& future) { if (future.error() == Error::kErrorOk) { const DocumentSnapshot& document = *future.result(); if (document.exists()) { std::cout << "Cached document id: " << document.id() << std::endl; } else { } } else { std::cout << "Cached get failed: " << future.error_message() << std::endl; } });
Node.js
Node.js SDK에서는 지원되지 않습니다.
Go
Go SDK에서는 지원되지 않습니다.
PHP
PHP SDK에서는 지원되지 않습니다.
Unity
Unity SDK에서는 지원되지 않습니다.
C#
C# SDK에서는 지원되지 않습니다.
Ruby
Ruby SDK에서는 지원되지 않습니다.
커스텀 객체
이전 예시에서는 문서의 내용을 맵으로 가져왔지만, 일부 언어는 커스텀 객체 유형을 사용하는 것이 더 편리할 수 있습니다. 데이터 추가 가이드에서 각 도시를 정의하는 데 필요한 City
클래스를 정의했습니다. 다음과 같이 문서를 City
객체로 되돌릴 수 있습니다.
커스텀 객체를 사용하려면 클래스에 FirestoreDataConverter 함수를 정의해야 합니다. 예를 들면 다음과 같습니다.
Web
class City { constructor (name, state, country ) { this.name = name; this.state = state; this.country = country; } toString() { return this.name + ', ' + this.state + ', ' + this.country; } } // Firestore data converter const cityConverter = { toFirestore: (city) => { return { name: city.name, state: city.state, country: city.country }; }, fromFirestore: (snapshot, options) => { const data = snapshot.data(options); return new City(data.name, data.state, data.country); } };
커스텀 객체를 사용하려면 클래스에 FirestoreDataConverter 함수를 정의해야 합니다. 예를 들면 다음과 같습니다.
Web
class City { constructor (name, state, country ) { this.name = name; this.state = state; this.country = country; } toString() { return this.name + ', ' + this.state + ', ' + this.country; } } // Firestore data converter var cityConverter = { toFirestore: function(city) { return { name: city.name, state: city.state, country: city.country }; }, fromFirestore: function(snapshot, options){ const data = snapshot.data(options); return new City(data.name, data.state, data.country); } };
읽기 작업으로 데이터 변환기를 호출합니다. 변환 후에는 커스텀 객체 메서드에 액세스할 수 있습니다.
Web
import { doc, getDoc} from "firebase/firestore"; const ref = doc(db, "cities", "LA").withConverter(cityConverter); const docSnap = await getDoc(ref); if (docSnap.exists()) { // Convert to City object const city = docSnap.data(); // Use a City instance method console.log(city.toString()); } else { console.log("No such document!"); }
읽기 작업으로 데이터 변환기를 호출합니다. 변환 후에는 커스텀 객체 메서드에 액세스할 수 있습니다.
Web
db.collection("cities").doc("LA") .withConverter(cityConverter) .get().then((doc) => { if (doc.exists){ // Convert to City object var city = doc.data(); // Use a City instance method console.log(city.toString()); } else { console.log("No such document!"); }}).catch((error) => { console.log("Error getting document:", error); });
Swift
Swift에서 자동 유형 직렬화를 지원하려면 유형이 코딩 가능한 프로토콜을 준수해야 합니다.
let docRef = db.collection("cities").document("BJ") do { let city = try await docRef.getDocument(as: City.self) print("City: \(city)") } catch { print("Error decoding city: \(error)") }
Objective-C
Objective-C에서는 이 작업을 수동으로 수행해야 합니다.
FIRDocumentReference *docRef = [[self.db collectionWithPath:@"cities"] documentWithPath:@"BJ"]; [docRef getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) { FSTCity *city = [[FSTCity alloc] initWithDictionary:snapshot.data]; if (city != nil) { NSLog(@"City: %@", city); } else { NSLog(@"Document does not exist"); } }];
Kotlin
val docRef = db.collection("cities").document("BJ") docRef.get().addOnSuccessListener { documentSnapshot -> val city = documentSnapshot.toObject<City>() }
Java
중요: 각 커스텀 클래스에는 인수를 사용하지 않는 공개 생성자가 있어야 합니다. 또한 각 속성의 공개 getter가 클래스에 포함되어야 합니다.
DocumentReference docRef = db.collection("cities").document("BJ"); docRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() { @Override public void onSuccess(DocumentSnapshot documentSnapshot) { City city = documentSnapshot.toObject(City.class); } });
Dart
커스텀 객체를 사용하려면 클래스에 Firestore 데이터 변환 함수를 정의해야 합니다. 예를 들면 다음과 같습니다.
class City { final String? name; final String? state; final String? country; final bool? capital; final int? population; final List<String>? regions; City({ this.name, this.state, this.country, this.capital, this.population, this.regions, }); factory City.fromFirestore( DocumentSnapshot<Map<String, dynamic>> snapshot, SnapshotOptions? options, ) { final data = snapshot.data(); return City( name: data?['name'], state: data?['state'], country: data?['country'], capital: data?['capital'], population: data?['population'], regions: data?['regions'] is Iterable ? List.from(data?['regions']) : null, ); } Map<String, dynamic> toFirestore() { return { if (name != null) "name": name, if (state != null) "state": state, if (country != null) "country": country, if (capital != null) "capital": capital, if (population != null) "population": population, if (regions != null) "regions": regions, }; } }
그런 다음 데이터 변환 함수를 사용하여 문서 참조를 만듭니다. 이 참조를 사용하여 수행하는 읽기 작업은 커스텀 클래스의 인스턴스를 반환합니다.
final ref = db.collection("cities").doc("LA").withConverter( fromFirestore: City.fromFirestore, toFirestore: (City city, _) => city.toFirestore(), ); final docSnap = await ref.get(); final city = docSnap.data(); // Convert to City object if (city != null) { print(city); } else { print("No such document."); }
자바
각 커스텀 클래스에는 인수를 사용하지 않는 공개 생성자가 있어야 합니다. 또한 각 속성의 공개 getter가 클래스에 포함되어야 합니다.
Python
Python
C++
// This is not yet supported.
Node.js
Node.js는 자바스크립트 객체를 사용합니다.
Go
PHP
PHP
Cloud Firestore 클라이언트 설치 및 생성에 관한 자세한 내용은 Cloud Firestore 클라이언트 라이브러리를 참조하세요.
Unity
DocumentReference docRef = db.Collection("cities").Document("BJ"); docRef.GetSnapshotAsync().ContinueWith((task) => { var snapshot = task.Result; if (snapshot.Exists) { Debug.Log(String.Format("Document data for {0} document:", snapshot.Id)); City city = snapshot.ConvertTo<City>(); Debug.Log(String.Format("Name: {0}", city.Name)); Debug.Log(String.Format("State: {0}", city.State)); Debug.Log(String.Format("Country: {0}", city.Country)); Debug.Log(String.Format("Capital: {0}", city.Capital)); Debug.Log(String.Format("Population: {0}", city.Population)); } else { Debug.Log(String.Format("Document {0} does not exist!", snapshot.Id)); } });
C#
Ruby
Ruby에는 적용되지 않습니다.
컬렉션에서 여러 문서 가져오기
컬렉션의 문서를 쿼리하여 하나의 요청으로 여러 문서를 검색할 수도 있습니다. 예를 들어 where()
를 사용하여 특정 조건을 충족하는 모든 문서를 쿼리하고 get()
을 사용하여 결과를 가져올 수 있습니다.
Web
import { collection, query, where, getDocs } from "firebase/firestore"; const q = query(collection(db, "cities"), where("capital", "==", true)); const querySnapshot = await getDocs(q); querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); });
Web
db.collection("cities").where("capital", "==", true) .get() .then((querySnapshot) => { querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); }); }) .catch((error) => { console.log("Error getting documents: ", error); });
Swift
do { let querySnapshot = try await db.collection("cities").whereField("capital", isEqualTo: true) .getDocuments() for document in querySnapshot.documents { print("\(document.documentID) => \(document.data())") } } catch { print("Error getting documents: \(error)") }
Objective-C
[[[self.db collectionWithPath:@"cities"] queryWhereField:@"capital" isEqualTo:@(YES)] getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error getting documents: %@", error); } else { for (FIRDocumentSnapshot *document in snapshot.documents) { NSLog(@"%@ => %@", document.documentID, document.data); } } }];
Kotlin
db.collection("cities") .whereEqualTo("capital", true) .get() .addOnSuccessListener { documents -> for (document in documents) { Log.d(TAG, "${document.id} => ${document.data}") } } .addOnFailureListener { exception -> Log.w(TAG, "Error getting documents: ", exception) }
Java
db.collection("cities") .whereEqualTo("capital", true) .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.d(TAG, "Error getting documents: ", task.getException()); } } });
Dart
db.collection("cities").where("capital", isEqualTo: true).get().then( (querySnapshot) { print("Successfully completed"); for (var docSnapshot in querySnapshot.docs) { print('${docSnapshot.id} => ${docSnapshot.data()}'); } }, onError: (e) => print("Error completing: $e"), );
자바
Python
Python
C++
db->Collection("cities") .WhereEqualTo("capital", FieldValue::Boolean(true)) .Get() .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; } });
Node.js
Go
PHP
PHP
Cloud Firestore 클라이언트 설치 및 생성에 관한 자세한 내용은 Cloud Firestore 클라이언트 라이브러리를 참조하세요.
Unity
Query capitalQuery = db.Collection("cities").WhereEqualTo("Capital", true); capitalQuery.GetSnapshotAsync().ContinueWithOnMainThread(task => { QuerySnapshot capitalQuerySnapshot = task.Result; foreach (DocumentSnapshot documentSnapshot in capitalQuerySnapshot.Documents) { Debug.Log(String.Format("Document data for {0} document:", documentSnapshot.Id)); Dictionary<string, object> city = documentSnapshot.ToDictionary(); foreach (KeyValuePair<string, object> pair in city) { Debug.Log(String.Format("{0}: {1}", pair.Key, pair.Value)); } // Newline to separate entries Debug.Log(""); }; });
C#
Ruby
기본적으로 Cloud Firestore는 쿼리를 만족하는 모든 문서를 문서 ID에 따라 오름차순으로 검색하지만, 반환되는 데이터를 정렬하고 제한할 수 있습니다.
컬렉션의 모든 문서 가져오기
where()
필터를 완전히 생략하여 컬렉션의 모든 문서를 검색할 수도 있습니다.
Web
import { collection, getDocs } from "firebase/firestore"; const querySnapshot = await getDocs(collection(db, "cities")); querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); });
Web
db.collection("cities").get().then((querySnapshot) => { querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); }); });
Swift
do { let querySnapshot = try await db.collection("cities").getDocuments() for document in querySnapshot.documents { print("\(document.documentID) => \(document.data())") } } catch { print("Error getting documents: \(error)") }
Objective-C
[[self.db collectionWithPath:@"cities"] getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error getting documents: %@", error); } else { for (FIRDocumentSnapshot *document in snapshot.documents) { NSLog(@"%@ => %@", document.documentID, document.data); } } }];
Kotlin
db.collection("cities") .get() .addOnSuccessListener { result -> for (document in result) { Log.d(TAG, "${document.id} => ${document.data}") } } .addOnFailureListener { exception -> Log.d(TAG, "Error getting documents: ", exception) }
Java
db.collection("cities") .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.d(TAG, "Error getting documents: ", task.getException()); } } });
Dart
db.collection("cities").get().then( (querySnapshot) { print("Successfully completed"); for (var docSnapshot in querySnapshot.docs) { print('${docSnapshot.id} => ${docSnapshot.data()}'); } }, onError: (e) => print("Error completing: $e"), );
자바
Python
Python
C++
db->Collection("cities").Get().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; } });
Node.js
Go
PHP
PHP
Cloud Firestore 클라이언트 설치 및 생성에 관한 자세한 내용은 Cloud Firestore 클라이언트 라이브러리를 참조하세요.
Unity
Query allCitiesQuery = db.Collection("cities"); allCitiesQuery.GetSnapshotAsync().ContinueWithOnMainThread(task => { QuerySnapshot allCitiesQuerySnapshot = task.Result; foreach (DocumentSnapshot documentSnapshot in allCitiesQuerySnapshot.Documents) { Debug.Log(String.Format("Document data for {0} document:", documentSnapshot.Id)); Dictionary<string, object> city = documentSnapshot.ToDictionary(); foreach (KeyValuePair<string, object> pair in city) { Debug.Log(String.Format("{0}: {1}", pair.Key, pair.Value)); } // Newline to separate entries Debug.Log(""); } });
C#
Ruby
하위 컬렉션의 모든 문서 가져오기
하위 컬렉션에서 모든 문서를 검색하려면 해당 하위 컬렉션의 전체 경로가 포함된 참조를 만듭니다.
Web
const { collection, getDocs } = require("firebase/firestore"); // Query a reference to a subcollection const querySnapshot = await getDocs(collection(db, "cities", "SF", "landmarks")); querySnapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); });
Web
// Snippet not available
Swift
do { let querySnapshot = try await db.collection("cities/SF/landmarks").getDocuments() for document in querySnapshot.documents { print("\(document.documentID) => \(document.data())") } } catch { print("Error getting documents: \(error)") }
Objective-C
[[self.db collectionWithPath:@"cities/SF/landmarks"] getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error getting documents: %@", error); } else { for (FIRDocumentSnapshot *document in snapshot.documents) { NSLog(@"%@ => %@", document.documentID, document.data); } } }];
Kotlin
db.collection("cities") .document("SF") .collection("landmarks") .get() .addOnSuccessListener { result -> for (document in result) { Log.d(TAG, "${document.id} => ${document.data}") } } .addOnFailureListener { exception -> Log.d(TAG, "Error getting documents: ", exception) }
Java
db.collection("cities") .document("SF") .collection("landmarks") .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.d(TAG, "Error getting documents: ", task.getException()); } } });
Dart
db.collection("cities").doc("SF").collection("landmarks").get().then( (querySnapshot) { print("Successfully completed"); for (var docSnapshot in querySnapshot.docs) { print('${docSnapshot.id} => ${docSnapshot.data()}'); } }, onError: (e) => print("Error completing: $e"), );
자바
// Snippet not available
Python
// Snippet not available
Python
// Snippet not available
C++
// Snippet not available
Node.js
// Snippet not available
Go
// Snippet not available
PHP
// Snippet not available
Unity
// Snippet not available
C#
// Snippet not available
Ruby
// Snippet not available
컬렉션 그룹에서 여러 문서 가져오기
컬렉션 그룹은 ID가 동일한 모든 컬렉션으로 구성됩니다. 예를 들어 cities
컬렉션의 각 문서에 landmarks
라는 하위 컬렉션에 있다면 모든 landmarks
하위 컬렉션이 동일한 컬렉션 그룹에 속합니다. 기본적으로 쿼리는 데이터베이스의 단일 컬렉션에서 결과를 검색합니다. 단일 컬렉션 대신 컬렉션 그룹에서 결과를 검색하려면 컬렉션 그룹 쿼리를 사용하세요.
문서의 하위 컬렉션 나열
Cloud Firestore 서버 클라이언트 라이브러리의 listCollections()
메서드는 문서 참조의 모든 하위 컬렉션을 나열합니다.
모바일 또는 웹 클라이언트 라이브러리로는 컬렉션 목록을 가져올 수 없습니다. 신뢰할 수 있는 서버 환경에서 관리 작업의 일부로만 컬렉션 이름을 조회해야 합니다. 모바일 또는 웹 클라이언트 라이브러리에 이 기능이 필요하다면 하위 컬렉션 이름을 예측할 수 있도록 데이터를 재구성하는 것이 좋습니다.
웹
웹 클라이언트 라이브러리에서는 사용할 수 없습니다.
Swift
Swift 클라이언트 라이브러리에서는 사용할 수 없습니다.
Objective-C
Objective-C 클라이언트 라이브러리에서는 사용할 수 없습니다.
Kotlin
Android 클라이언트 라이브러리에서는 사용할 수 없습니다.
Java
Android 클라이언트 라이브러리에서는 사용할 수 없습니다.
Dart
Flutter 클라이언트 라이브러리에서는 사용할 수 없습니다.
자바
Python
Python
C++
C++ 클라이언트 라이브러리에서는 사용할 수 없습니다.
Node.js
Go
PHP
PHP
Cloud Firestore 클라이언트 설치 및 생성에 관한 자세한 내용은 Cloud Firestore 클라이언트 라이브러리를 참조하세요.
Unity
// This is not yet supported in the Unity SDK.
C#
Ruby
다양한 쿼리 유형에 대해 자세히 알아보세요.
오류 코드 및 데이터를 가져올 때 지연 시간 문제를 해결하는 방법에 대한 자세한 내용은 문제 해결 페이지를 참고하세요.