Firebase Realtime Database је облачна JSON база података у реалном времену, покренута од стране Google-а 2012. године за мобилне и веб апликације. Сви подаци се чувају у једном великом JSON стаблу и синхронизују између повезаних клијената у реалном времену преко WebSocket-конекције. Према званичној документацији Firebase, 2025, Realtime Database може да опслужи до 200 000 истовремених конекција и подржава до 1000 истовремених уписа у секунди. База података не захтева серверску инфраструктуру и пружа SDK за iOS, Android, Web и серверске платформе.
Главно
Firebase Realtime Database је облачна NoSQL база података која чува и синхронизује податке у реалном времену између свих повезаних клијената. Покренута 2012. године као Firebase (пре аквизиције од стране Google-а), постала је прва облачна база података у реалном времену за мобилне програмере. Подаци су представљени у JSON формату и организовани у хијерархијско стабло, где сваки чвор има јединствену путању.
Основна вредност Realtime Database је уграђена синхронизација. Када апликација промени податке на било ком уређају, сви остали повезани клијенти тренутно добијају ажурирање преко сталне конекције. То ослобађа програмера имплементације сопственог механизма синхронизације, WebSocket сервера или REST API-ја за пренос података између клијената.
База података пружа SDK за све главне платформе: Android (Java, Kotlin), iOS (Swift, Objective-C), Web (JavaScript) и серверска окружења преко Admin SDK. Према подацима Google-а, Realtime Database се користи у преко 1,5 милиона активних Firebase пројеката широм света. Упркос појави модерније Firestore, Realtime Database остаје популаран избор за пројекте са једноставном структуром података.
За разлику од релационих база података, Realtime Database не користи табеле и редове. Сви подаци представљају једно JSON стабло које личи на угнежђене JavaScript објекте. На пример, за чување корисника и њихових порука креира се хијерархија: users/userId/name и messages/messageId/text. Свака путања у стаблу је стринг и подацима се може приступити директно преко те путање.
{
"users": {
"user1": {
"name": "Иван Петров",
"email": "ivan@example.com"
},
"user2": {
"name": "Марија Соколова",
"email": "maria@example.com"
}
},
"messages": {
"-Nabc123": {
"text": "Здраво!",
"userId": "user1"
}
}
}
Важна карактеристика је да дубоко угнежђење утиче на перформансе. Када апликација чита податке на одређеној путањи, учитава све подређене чворове те путање. Стога се препоручује дизајнирање структуре података што равније, избегавајући угнежђење дубље од 3–4 нивоа. За решавање овог проблема користи се денормализација података — дуплирање информација у различитим чворовима стабла.
Realtime Database и Firestore се често пореде као две облачне базе података у реалном времену од Google-а. Избор између њих зависи од конкретних захтева пројекта: сложености упита, потребне конзистентности и планираног оптерећења. Разумевање предности сваке базе података помаже у доношењу исправне архитектонске одлуке.
Главна предност Realtime Database је ниска латенција синхронизације. Пошто се сви подаци чувају у једном JSON стаблу без додатних слојева апстракције, синхронизација је бржа него у Firestore. За апликације где је брзина испоруке ажурирања критична (четови, онлајн игре, системи за заједничко уређивање), Realtime Database може бити прикладнији избор.
Realtime Database је погоднија за сценарије са једноставном структуром података и високом учесталошћу ажурирања. Типични примери: четови, лајкови у реалном времену, индикатори куцања, статуси присуства корисника. То је такође добар избор за прототипове и пројекте са ограниченим буџетом, јер се цене заснивају на обиму података, а не на броју операција.
С друге стране, за апликације са сложеним упитима (филтрирање по више поља, сортирање, агрегација) Firestore пружа много моћније могућности. Realtime Database подржава само филтрирање по једном параметру и не може да сортира резултате по више поља истовремено. Ако пројекат планира сложену аналитику података на клијентској страни, Firestore ће бити практичнији избор.
Realtime Database користи сталну WebSocket конекцију за двосмерну синхронизацију података. Када клијент позове setValue или updateChildren на одређеној путањи, подаци се шаљу на Firebase сервер преко отвореног канала. Сервер примењује измене и шаље ажурирања свим претплаћеним клијентима у року од милисекунди. Свака конекција се идентификује јединственим кључем сесије.
Механизам претплате функционише преко listener-а. Програмер се може претплатити на промену одређеног чвора (addListenerForSingleValueEvent) или добијати стална ажурирања (addValueEventListener). При свакој промени података позива се callback onDataChange са комплетним снимком података на наведеној путањи. Ово се разликује од Firestore, где стижу само измењени документи — у Realtime Database се увек учитавају сви подаци чвора.
Realtime Database подржава офлајн режим на Android и iOS преко кеширања на диску. SDK чува локалну копију података и наставља да обрађује операције уписа у одсуству мреже. Када се конекција успостави, све акумулиране промене се шаљу на сервер. За решавање конфликата користи се стратегија last-write-wins, али програмер може имплементирати прилагођену логику преко ServerValue.TIMESTAMP за решавање колизија.
val database = FirebaseDatabase.getInstance()
val myRef = database.getReference("messages")
// Упис података
myRef.push().setValue(
hashMapOf(
"text" to "Нова порука",
"timestamp" to ServerValue.TIMESTAMP
)
)
// Читање са сталним ажурирањем
myRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val data = snapshot.getValue()
Log.d("TAG", "Подаци: $data")
}
override fun onCancelled(error: DatabaseError) {
Log.w("TAG", "Грешка: ${error.message}")
}
})
За оптимизацију саобраћаја и перформанси препоручује се употреба child listeners уместо value listeners када треба пратити промене одређених подређених чворова. ChildEventListener пружа одвојене callback-е за додавање, измену, брисање и премештање подређених елемената, што омогућава прецизнију контролу ажурирања UI-ја и избегавање прецртавања свих елемената листе при свакој промени података.
Realtime Database користи декларативни језик правила за контролу приступа подацима. Правила описују ко може читати и уписати податке на свакој путањи JSON стабла. Она се проверавају на Firebase серверу пре сваког захтева и не захтевају серверску логику за ауторизацију. Правила подржавају променљиве, уграђене објекте и функције за флексибилну конфигурацију приступа.
Подразумевано, приступ бази података је забрањен за све кориснике. Програмер постепено отвара приступ користећи правило ".read" и ".write" на различитим нивоима стабла. Услови могу проверавати аутентификацију преко променљиве auth, тип захтева (read/write) и постојеће податке преко објекта data. Поред тога, правила подржавају валидацију уписаних података преко објекта newData.
{
"rules": {
"users": {
"$uid": {
// Само власник може читати своје податке
".read": "$uid === auth.uid",
// Само власник може писати
".write": "$uid === auth.uid",
// Валидација поља при упису
".validate": "newData.hasChildren(['name', 'email'])"
}
},
"messages": {
// Сваки аутентификовани може читати
".read": "auth !== null",
// Само аутентификовани може писати
".write": "auth !== null",
".indexOn": ["timestamp"]
}
}
}
Правила такође подржавају индексирање података преко директиве ".indexOn". Без ње, упити са сортирањем (orderByChild) биће одбијени или извршени неефикасно. Индекси се наводе за сваку путању где се врши сортирање по одређеном пољу. Правила су каскадна: дубља правила поништавају родитељска, а ако на неком нивоу приступ не постоји, сматра се дозвољеним или забрањеним у зависности од родитељског правила.
Realtime Database подржава пет типова података: String, Number, Boolean, Map (објекат) и List (низ). Дубина угнежђења је ограничена на 32 нивоа, а максимална величина једног чвора не сме прелазити 256 MB. За ефикасан рад са базом препоручује се дизајнирање равне структуре података и коришћење денормализације како би се избегли дубоки упити који учитавају велике количине података.
Размотримо практичан пример интеграције Realtime Database у Android апликацију за статусе корисника (online/offline). Апликација ће приказивати листу корисника са њиховим тренутним статусом, ажурираним у реалном времену. За демонстрацију се користе Firebase Authentication за идентификацију корисника и корутине за асинхроне операције.
За почетак додајте зависност firebase-database-ktx у датотеку build.gradle модула апликације. Верзијом библиотеке управља се преко Firebase BoM ради обезбеђивања компатибилности свих компоненти. Након додавања зависности потребно је иницијализовати Firebase у класи Application или кроз лењу иницијализацију у ViewModel.
dependencies {
implementation platform("com.google.firebase:firebase-bom:33.0.0")
implementation "com.google.firebase:firebase-database-ktx"
implementation "com.google.firebase:firebase-auth-ktx"
}
Након конфигурације креира се репозиторијум за рад са корисницима. Сваки корисник је представљен чвором у стаблу /users/{uid} са пољима name, email и status. За праћење статуса користи се onDisconnect — посебан Firebase механизам који аутоматски извршава операцију уписа при прекиду конекције клијента. Ово гарантује да ће се статус корисника променити у "offline" при затварању апликације или губитку мреже без додатног кода на клијентској страни.
class PresenceRepository {
private val database = FirebaseDatabase.getInstance()
private val auth = FirebaseAuth.getInstance()
private val presenceRef = database
.getReference("presence")
fun trackPresence() {
val uid = auth.currentUser?.uid ?: return
val userRef = presenceRef.child(uid)
userRef.onDisconnect().setValue("offline")
userRef.setValue("online")
}
fun getPresenceStream(): Flow<Map<String, String>> =
presenceRef.snapshotFlow()
.map { snapshot ->
(snapshot.value as? Map<*, *>)
?.mapKeys { it.key.toString() }
?.mapValues { it.value.toString() }
?: emptyMap()
}
}
Кључни елемент примера је onDisconnect. Овај механизам омогућава постављање операције уписа која ће се извршити на серверу при прекиду конекције клијента. У овом случају, при одјављивању корисника, његов статус се аутоматски поставља на "offline" без потребе за обрадом догађаја затварања апликације. Ако се апликација неочекивано заврши, Firebase ће сам извршити onDisconnect операцију, а остали корисници ће видети исправан статус.
Често постављана питања
Realtime Database чува податке у једном JSON стаблу и пружа мање кашњење синхронизације. Firestore користи колекције докумената, подржава сложене упите и јаку конзистентност. Realtime Database је боља за једноставне четове и статусе, Firestore — за апликације са сложеном структуром података и аналитиком.
Максимална величина једног чвора Realtime Database износи 256 MB. Дубина угнежђења је ограничена на 32 нивоа. За један Firebase пројекат могуће је креирати више Realtime Database база података (до 5 на Spark плану и до 100 на Blaze плану), што омогућава дистрибуцију података између различитих инстанци.
Realtime Database се интегрише са Firebase Authentication. У сигурносним правилима доступна је променљива auth која садржи uid аутентификованог корисника. Програмер може ограничити приступ на нивоу појединачних чворова JSON стабла, проверавајући подударност uid власника података. Анонимни и неаутентификовани корисници имају auth = null.
Да, Realtime Database подржава трансакције преко метода runTransaction. Трансакција гарантује атомичност операције читања-измене-уписа за један чвор. При истовременим променама трансакција се понавља са актуелним подацима. Ово је корисно за бројаче, оцене и друге сценарије где је конзистентност података важна.
Да, Realtime Database подржава офлајн режим на Android и iOS. SDK кешира податке локално и наставља да обрађује операције уписа у одсуству мреже. Након успостављања конекције, све акумулиране промене се синхронизују са сервером. За укључивање офлајн режима користи се метод keepSynced(true) на одговарајућем чвору.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође