Firebase Realtime Database에서 성능을 최적화하고 데이터를 확장하는 가장 좋은 방법은 데이터를 여러 개의 Realtime Database 인스턴스로 분할하는 데이터베이스 샤딩입니다. 이 방법으로 부하 분산 및 성능 최적화 외에도 개별 데이터베이스 인스턴스에 적용되는 한도를 초과하여 확장할 수 있는 유연성을 확보할 수 있습니다.
데이터를 샤딩해야 하는 경우
Realtime Database를 사용하며 다음과 같은 시나리오에 해당하는 경우 데이터를 여러 데이터베이스로 샤딩할 수 있습니다.
- 단일 데이터베이스 인스턴스의 동시 연결 한도 200,000개, 초당 쓰기 작업 1,000개 또는 기타 한도를 초과하여 확장하려고 합니다.
- 예를 들어 별도의 독립적인 사용자 그룹을 지원하는 채팅 앱을 위해 개별적인 여러 데이터 세트의 성능을 최적화하려고 합니다.
- 여러 데이터베이스로 부하를 분산시켜 업타임을 개선하고 단일 데이터베이스 인스턴스에 과부하가 발생할 위험을 줄이려고 합니다.
데이터 샤딩 방법
데이터를 샤딩하려면 다음 단계를 따르세요. 아래에 더 자세한 설명이 제공됩니다.
- 앱의 구체적인 요구사항에 따라 데이터를 여러 데이터베이스로 매핑합니다.
- 여러 데이터베이스 인스턴스를 만듭니다.
- 각 데이터 세트에 필요한 Realtime Database 인스턴스에 연결되도록 앱을 구성합니다.
데이터 매핑
데이터를 여러 데이터베이스에 매핑할 때는 다음 조건을 충족하도록 합니다.
- 각 쿼리는 단일 데이터베이스 인스턴스만을 대상으로 실행됩니다. Realtime Database는 여러 데이터베이스 인스턴스에 대한 쿼리를 지원하지 않습니다.
- 데이터베이스 인스턴스 간에 데이터가 공유되거나 중복되지 않습니다. 또는 공유나 중복을 최소한으로 유지합니다.
- 각 앱 인스턴스는 특정 시점에 하나의 데이터베이스에만 연결됩니다.
데이터를 매핑할 때는 다음과 같은 전략을 적용해 보세요.
'마스터 샤드' 만들기
데이터베이스 인스턴스 간에 데이터가 저장되는 방법을 나타낸 맵을 저장하세요. 그러면 연결되는 클라이언트에 해당하는 데이터베이스 인스턴스를 프로그래매틱 방식으로 조회할 수 있습니다. 단, 필요할 때 원하는 특정 데이터베이스 인스턴스에 직접 연결하는 것보다 많은 오버헤드가 발생할 수 있습니다.
카테고리별 또는 고객별로 데이터 버킷 만들기
사용자 또는 데이터 유형별로 그룹화하여 데이터를 서로 격리된 데이터베이스 인스턴스로 저장하세요. 예를 들어 여러 조직을 지원하는 채팅 애플리케이션을 구축하는 경우 각 조직에 데이터베이스 인스턴스를 만들고 모든 채팅 데이터를 고유한 데이터베이스 인스턴스에 저장할 수 있습니다.
이 경우 조직 A와 조직 B는 데이터를 공유하지 않으며 데이터베이스에 중복 데이터가 없고 단일 데이터베이스 인스턴스만을 대상으로 쿼리를 수행합니다. 또한 각 조직의 사용자는 채팅 앱을 사용할 때 조직의 데이터베이스에만 연결됩니다.
그러면 미리 여러 개의 데이터베이스 인스턴스를 만들고 조직 ID를 사용해 팀을 데이터베이스 인스턴스에 매핑하면 됩니다. 예를 들어 조직 A는 실시간 데이터베이스 A에 매핑합니다.
앱의 데이터를 매핑하는 방법은 사용 사례에 따라 달라지지만 위에서 설명한 조건과 전략을 참고하면 데이터에 적합한 방법을 정하는 데 도움이 될 수 있습니다.
여러 개의 Realtime Database 인스턴스 만들기
Blaze 요금제를 사용 중인 경우 동일한 Firebase 프로젝트에서 데이터베이스 인스턴스를 최대 1,000개까지 만들 수 있습니다.
데이터베이스 섹션의 컨텍스트 메뉴를 사용하여 Firebase Console에서 데이터베이스 만들기" />
- Firebase Console에서 개발 > 데이터베이스 섹션의 데이터 탭으로 이동합니다.
- Realtime Database 섹션의 메뉴에서 새 데이터베이스 만들기를 선택합니다.
- 데이터베이스 참조 및 보안 규칙을 맞춤설정한 후 확인을 클릭합니다.
이 프로세스를 반복하여 필요한 만큼 데이터베이스 인스턴스를 만듭니다. 데이터베이스 인스턴스마다 고유한 Firebase Realtime Database Security Rules 세트를 사용하므로 데이터 액세스를 세밀하게 조정할 수 있습니다.
FirebaseFirebaseConsole 또는 Realtime Database Management REST API를 사용하여 데이터베이스 인스턴스를 만들고 관리할 수 있습니다.
각 인스턴스의 Realtime Database Security Rules 수정 및 배포
Realtime Database Security Rules이 프로젝트의 각 데이터베이스 인스턴스에 적절한 액세스 권한을 허용하는지 확인해야 합니다. 각 데이터베이스에서 보유한 자체 규칙 세트를 Firebase Console에서 수정 및 배포할 수 있고 Firebase CLI를 사용하여 대상을 배포할 수 있습니다.
Firebase Console에서 규칙을 수정하고 배포하려면 다음 단계를 따르세요.
- 개발 > 데이터베이스 섹션의 규칙 탭으로 이동합니다.
- 수정할 데이터베이스를 선택하고 규칙을 수정합니다.
Firebase CLI에서 규칙을 수정하고 배포하려면 다음 단계를 따르세요.
- 데이터베이스 인스턴스의 규칙 파일에서 규칙을 수정합니다(예:
foo.rules.json
). - 배포 대상을 만들고 적용하여 동일한 규칙 파일을 사용하는 데이터베이스를 연결합니다. 예를 들면 다음과 같습니다.
firebase target:apply database main my-db-1 my-db-2
firebase target:apply database other my-other-db-3
firebase.json
구성 파일을 배포 대상으로 업데이트합니다.{ "database": [ {"target": "main", "rules": "foo.rules.json"}, {"target": "other", "rules": "bar.rules.json"} ] }
배포 명령어를 실행합니다.
firebase deploy
- 데이터베이스 인스턴스의 규칙 파일에서 규칙을 수정합니다(예:
항상 같은 위치에서 규칙을 수정하고 배포해야 합니다. Firebase CLI에서 규칙을 배포하면 Firebase Console에서 수정한 내용이 모두 재정의되고 Firebase Console에서 규칙을 직접 수정하면 Firebase CLI를 통해 배포한 최근 변경사항이 모두 재정의됩니다.
앱을 여러 데이터베이스 인스턴스에 연결
데이터베이스 참조를 사용하여 보조 데이터베이스 인스턴스에 저장된 데이터에 액세스하세요. URL 또는 앱으로 특정 데이터베이스 인스턴스에 대한 참조를 가져올 수 있습니다. URL을 지정하지 않으면 앱의 기본 데이터베이스 인스턴스에 대한 참조가 제공됩니다.
Web
import { initializeApp } from "firebase/app"; import { getDatabase } from "firebase/database"; const app1 = initializeApp({ databaseURL: "https://testapp-1234-1.firebaseio.com" }); const app2 = initializeApp({ databaseURL: "https://testapp-1234-2.firebaseio.com" }, 'app2'); // Get the default database instance for an app1 const database1 = getDatabase(app1); // Get a database instance for app2 const database2 = getDatabase(app2);
Web
const app1 = firebase.initializeApp({ databaseURL: "https://testapp-1234-1.firebaseio.com" }); const app2 = firebase.initializeApp({ databaseURL: "https://testapp-1234-2.firebaseio.com" }, 'app2'); // Get the default database instance for an app1 var database1 = firebase.database(); // Get a database instance for app2 var database2 = firebase.database(app2);
Swift
// Get the default database instance for an appvar ref: DatabaseReference! ref = Database.database().reference()// 다음 URL로 보조 데이터베이스 인스턴스를 가져옵니다. var ref: DatabaseReference! ref = Database.database("https://testapp-1234.firebaseio.com").reference()
Objective-C
// Get the default database instance for an app@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];// 다음 URL을 통해 보조 데이터베이스 인스턴스를 가져옵니다. @property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase databaseWithURL:@"https://testapp-1234.firebaseio.com"] reference];
Kotlin+KTX
// Get the default database instance for an app val primary = Firebase.database.reference // Get a secondary database instance by URL val secondary = Firebase.database("https://testapp-1234.firebaseio.com").reference
Java
// Get the default database instance for an app DatabaseReference primary = FirebaseDatabase.getInstance() .getReference(); // Get a secondary database instance by URL DatabaseReference secondary = FirebaseDatabase.getInstance("https://testapp-1234.firebaseio.com") .getReference();
Firebase CLI 사용 시 인스턴스 지정
--instance
옵션을 사용하여 Firebase CLI 명령어를 적용할 Firebase Realtime Database를 지정합니다. 예를 들어 my-example-shard.firebaseio.com
이라는 데이터베이스 인스턴스에 대한 프로파일러를 실행하려면 다음 명령어를 사용합니다.
firebase database:profile --instance "my-example-shard"
각 데이터베이스의 연결 최적화
세션 도중 각 클라이언트를 여러 데이터베이스에 연결해야 할 경우 필요할 때만 각 데이터베이스 인스턴스에 연결해 각 데이터베이스 인스턴스에 대한 동시 연결 수를 줄일 수 있습니다.
추가 조언
데이터를 여러 데이터베이스 인스턴스로 샤딩하는 데 도움이 필요하면 Slack 채널 또는 Stack Overflow에서 Firebase 전문가에게 문의하세요.