Yükleniyor...

Firebase Mimari Tasarım: 10 Best Practice [2026 Kapsamlı Rehber]

Yazar: Burak Balkı | Kategori: Mobile Development | Okuma Süresi: 49 dk

Bu rehber, 2026 itibarıyla Firebase mimari tasarımının temel prensiplerini, ileri düzey tekniklerini ve en iyi uygulamalarını ele alarak, ölçeklenebilir, güv...

### BÖLÜM 1 - Giriş Paragrafı (Hook + Context) Mobil ve web uygulamalarının geliştirme süreci, 2026 yılında dahi karmaşık backend altyapıları nedeniyle sıkça tıkanabiliyor. Bu karmaşıklığı ortadan kaldıran ve geliştiricilere hız kazandıran platformlardan biri olan **Firebase**, günümüzün modern mimarilerinde merkezi bir rol oynuyor. Bu kapsamlı rehberde, Firebase mimari tasarımının temel prensiplerini, ileri düzey tekniklerini ve 2026'nın en iyi uygulamalarını derinlemesine inceleyeceğiz. Amacımız, uygulamanız için ölçeklenebilir, güvenli ve performanslı bir Firebase backend'i inşa etmenize yardımcı olmak. ### BÖLÜM 2 - Firebase Nedir? (Featured Snippet Target) ## Firebase Nedir? Firebase, Google tarafından geliştirilen, mobil ve web uygulamaları için bir BaaS (Backend-as-a-Service) platformudur. Gerçek zamanlı veritabanı, kimlik doğrulama, bulut depolama, barındırma ve sunucusuz fonksiyonlar gibi birçok hizmeti tek bir entegre ekosistemde sunar. Geliştiricilerin backend altyapısı kurma ve yönetme yükünü azaltarak, uygulamanın kullanıcı deneyimine odaklanmalarını sağlar. Firebase, hızlı prototipleme ve global ölçeklenebilirlik sunan, 2026 itibarıyla mobil uygulama geliştirmenin vazgeçilmez araçlarından biridir. Firebase, aslında bir dizi farklı servisi bir araya getiren bir platformdur. Başlangıçta 2011'de bağımsız bir şirket olarak kurulan ve 2014'te Google tarafından satın alınan Firebase, o günden bu yana sürekli gelişerek modern uygulama geliştirme ihtiyaçlarına cevap vermektedir. Amacı, geliştiricilerin backend operasyonları yerine doğrudan uygulama mantığına ve kullanıcı arayüzüne odaklanmalarını sağlamaktır. Bu sayede, geliştirme süreleri kısalır, bakım maliyetleri düşer ve uygulamalar daha hızlı bir şekilde pazara sunulabilir. ### BÖLÜM 3 - Neden Firebase Kullanmalısınız? (Değer Önerisi) Firebase, mobil ve web uygulamaları geliştiren ekipler için 2026 yılında birçok kritik avantaj sunar. Kapsamlı servis seti ve entegrasyon yetenekleri sayesinde geliştirme süreçlerini radikal bir şekilde hızlandırır ve operasyonel yükü azaltır. * **Hızlı Geliştirme ve Prototipleme**: Firebase'in hazır backend servisleri, geliştiricilerin saatler içinde çalışan bir MVP (Minimum Viable Product) oluşturmasını sağlar. Kimlik doğrulama, veritabanı, depolama gibi temel işlevler için sıfırdan kod yazmaya gerek kalmaz. Bu, özellikle startup'lar ve hızlı iterasyon gerektiren projeler için paha biçilmezdir. Ekibimizde Firebase'e geçiş sürecinde, backend geliştirme süresinin ortalama %30 azaldığını gözlemledik. * **Otomatik Ölçeklenebilirlik**: Google'ın altyapısı üzerinde çalıştığı için Firebase servisleri, uygulamanızın trafiği arttıkça otomatik olarak ölçeklenir. Bu, geliştiricilerin altyapı yönetimiyle uğraşmak yerine ürün geliştirmeye odaklanmasını sağlar. Production ortamında yüksek trafikli bir e-ticaret uygulaması kullanırken, Firebase'in ani yük artışlarını sorunsuz yönettiğini gördüm. * **Düşük Operasyonel Maliyet**: Sunucu yönetimi, veritabanı yedeklemesi, güvenlik yamaları gibi operasyonel görevler Firebase tarafından yönetilir. Bu, IT operasyonları için harcanan zamanı ve maliyeti önemli ölçüde azaltır. * **Gerçek Zamanlı Senkronizasyon**: Hem Firestore hem de Realtime Database, verilerin istemciler arasında gerçek zamanlı olarak senkronize edilmesini sağlar. Sohbet uygulamaları, işbirliği araçları ve canlı güncellemeler gerektiren uygulamalar için idealdir. * **Entegre Ekosistem**: Firebase Authentication, Cloud Functions, Cloud Storage, Hosting, Analytics, Crashlytics, Performance Monitoring ve ML Kit gibi servisler birbiriyle sorunsuz entegre çalışır. Bu bütünsel yaklaşım, geliştirme deneyimini basitleştirir. * **Aktif ve Geniş Topluluk**: 2026 itibarıyla Firebase, mobil geliştirici topluluğunda oldukça popülerdir. Geniş dökümantasyon, Stack Overflow'da binlerce soru-cevap ve aktif GitHub depoları, karşılaşılan sorunlara hızlı çözüm bulmayı kolaylaştırır. **Kimler İçin Uygun?** * Hızlı prototipleme yapmak isteyen startup'lar. * Frontend odaklı geliştirme ekipleri. * Mobil ve web tabanlı uygulamalar geliştirenler. * Gerçek zamanlı özelliklere ihtiyaç duyan projeler. **Kimler İçin Uygun Değil?** * Tamamen özel, on-premise bir backend altyapısı gerektiren büyük kurumsal sistemler. * Karmaşık SQL tabanlı ilişki yönetimi gerektiren uygulamalar (NoSQL yapısı nedeniyle). * Google ekosistemi dışında bağımsız bir çözüm arayanlar. ### BÖLÜM 4 - Firebase vs Alternatifler (Karşılaştırma Tablosu) Firebase, BaaS alanında güçlü bir oyuncu olsa da, pazarda farklı ihtiyaçlara hitap eden başka çözümler de bulunmaktadır. En yaygın alternatiflerden ikisi, AWS Amplify ve Supabase'dir. Her birinin kendine özgü avantajları ve dezavantajları vardır. | Özellik | Firebase (2026) | AWS Amplify (2026) | Supabase (2026) | | :---------------- | :------------------------------------------------------------------------------ | :------------------------------------------------------------------------------ | :------------------------------------------------------------------------------- | | **Veritabanı** | Firestore (NoSQL), Realtime DB (NoSQL) | DynamoDB (NoSQL), Aurora (SQL), RDS (SQL) | PostgreSQL (SQL) | | **Kimlik Doğrulama** | Firebase Auth (Email/Pass, OAuth, Phone) | AWS Cognito | Supabase Auth (Email/Pass, OAuth, Magic Link) | | **Sunucusuz Fonksiyonlar** | Cloud Functions (Node.js, Python, Go, Java) | AWS Lambda (Çoklu dil desteği) | Supabase Edge Functions (Deno/TypeScript) | | **Depolama** | Cloud Storage for Firebase | AWS S3 | Supabase Storage | | **Barındırma** | Firebase Hosting (CDN, SSL) | AWS Amplify Hosting, S3 + CloudFront | Kendi barındırma çözümü yok, 3. parti entegrasyonu (Vercel, Netlify) | | **Öğrenme Eğrisi**| Düşük-Orta (Hızlı başlangıç, geniş dökümantasyon) | Orta-Yüksek (Geniş AWS ekosistemi, daha karmaşık) | Düşük-Orta (PostgreSQL bilginiz varsa daha kolay) | | **Ekosistem** | Google Cloud entegrasyonu, ML Kit, Analytics, Crashlytics | Geniş AWS servisleri entegrasyonu | PostgreSQL odaklı, gerçek zamanlı API, depolama, fonksiyonlar | | **Topluluk** | Çok Geniş ve Aktif | Geniş (AWS genel topluluğu) | Hızla Büyüyen, Açık Kaynak Odaklı | | **Kurumsal Destek**| Google Cloud Destek Planları | AWS Destek Planları (Çeşitli seviyelerde) | Topluluk ve Ücretli Destek Planları | | **Kullanım Alanı**| Mobil/Web MVP, Gerçek Zamanlı Uygulamalar, Frontend Odaklı Projeler | Kurumsal Uygulamalar, Büyük Ölçekli Mikroservisler, AWS Ekosistemi Kullanıcıları | SQL Odaklı Projeler, Açık Kaynak Tercih Edenler, Deno Kullanıcıları | **Yorum**: Firebase, özellikle mobil ve web uygulamalarında hızlı geliştirme ve gerçek zamanlı özellikler arayanlar için idealdir. AWS Amplify, daha geniş bir AWS ekosistemine entegre olmak isteyen ve daha fazla esneklik arayan kurumsal projeler için uygundur. Supabase ise PostgreSQL'in gücünü sunucusuz bir yaklaşımla birleştirmek isteyen ve açık kaynak çözümleri tercih eden geliştiricilere hitap eder. Seçim, projenizin spesifik ihtiyaçlarına ve ekibinizin mevcut yetkinliklerine bağlıdır. ### BÖLÜM 5 - Kurulum ve İlk Adımlar (Getting Started) Firebase ile çalışmaya başlamak oldukça basittir. Bu bölümde, bir Firebase projesi oluşturma ve temel yapılandırmayı adım adım ele alacağız. **Ön Gereksinimler:** * Bir Google hesabı. * Node.js (LTS sürümü, 2026 itibarıyla v20.x veya üzeri önerilir) ve npm yüklü olmalı. * Tercihen bir JavaScript/TypeScript projesi (React, Vue, Angular veya Vanilla JS). **Adım 1: Firebase Projesi Oluşturma** 1. Firebase Console'a gidin: [console.firebase.google.com](https://console.firebase.google.com/) 2. "Proje ekle" butonuna tıklayın. 3. Projenize bir isim verin (örn: `firebase-mimari-2026`). 4. Google Analytics'i etkinleştirip etkinleştirmemeyi seçin. (Üretim ortamı için genellikle etkinleştirilir.) 5. Projeniz oluşturulduktan sonra, konsola yönlendirileceksiniz. **Adım 2: Firebase CLI Kurulumu** Firebase CLI (Command Line Interface), projenizi yerel ortamdan yönetmek için kullanılır. ```bash npm install -g firebase-tools@latest ``` > **Pro Tip**: `firebase-tools` paketinin 2026 itibarıyla en güncel sürümünü yüklemek, yeni özelliklere ve güvenlik yamalarına erişmenizi sağlar. Global kurulum, CLI'yı herhangi bir dizinden kullanmanıza olanak tanır. **Adım 3: Firebase Hesabınıza Giriş Yapma** Terminalinizde aşağıdaki komutu çalıştırarak Firebase hesabınızda oturum açın: ```bash firebase login ``` Bu komut sizi tarayıcınıza yönlendirecek ve Google hesabınızla oturum açmanızı isteyecektir. Başarılı bir girişin ardından terminale geri dönebilirsiniz. **Adım 4: Projenizi Başlatma** Uygulama dizininize gidin ve Firebase projenizi başlatın: ```bash cd my-firebase-app # Uygulama dizininiz firebase init ``` `firebase init` komutu size hangi Firebase özelliklerini (Firestore, Functions, Hosting vb.) kullanmak istediğinizi soracaktır. Ok tuşlarıyla seçim yapıp boşluk tuşuyla onaylayın. Ardından, mevcut projenizi seçmeniz veya yeni bir proje oluşturmanız istenecektir. Daha önce oluşturduğunuz `firebase-mimari-2026` projesini seçin. **Adım 5: Uygulamanızı Firebase'e Bağlama (Web için Örnek)** Firebase projenizi oluşturduktan sonra, web uygulamanızı bağlamak için gerekli yapılandırma bilgilerini almanız gerekir. 1. Firebase Console'da projenize gidin. 2. Proje genel bakış sayfasında "Web uygulaması ekle" (``) simgesine tıklayın. 3. Uygulamanıza bir takma ad verin (örn: `my-web-app`). 4. Kaydı tamamladığınızda, Firebase SDK yapılandırma objesi size sunulacaktır. Bu objeyi projenizin ana JavaScript dosyasına (örn: `src/firebase-config.js`) yapıştırın. ```javascript // src/firebase-config.js import { initializeApp } from 'firebase/app'; import { getFirestore } from 'firebase/firestore'; import { getAuth } from 'firebase/auth'; import { getStorage } from 'firebase/storage'; import { getFunctions } from 'firebase/functions'; // 2026 itibarıyla güncel Firebase SDK v9+ modüler API kullanımı const firebaseConfig = { apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", projectId: "your-project-id", storageBucket: "your-storage-bucket", messagingSenderId: "YOUR_MESSAGING_SENDER_ID", appId: "YOUR_APP_ID", measurementId: "YOUR_MEASUREMENT_ID" // Eğer Analytics etkinleştirildiyse }; // Firebase uygulamasını başlat const app = initializeApp(firebaseConfig); // Diğer servisleri dışa aktar export const db = getFirestore(app); export const auth = getAuth(app); export const storage = getStorage(app); export const functions = getFunctions(app); // Cloud Functions için ``` Şimdi uygulamanız Firebase'e bağlı ve temel servisleri kullanmaya hazır. ### BÖLÜM 6 - Temel Kullanım ve Örnekler (Core Usage) Bu bölümde, Firebase'in temel servislerini kullanarak gerçek dünya senaryolarını nasıl uygulayabileceğinizi göstereceğiz. Odak noktamız Firestore, Authentication ve Cloud Storage olacak. **Örnek 1: Kullanıcı Kaydı ve Girişi (Authentication)** **Problem**: Kullanıcıların uygulamanıza e-posta ve şifre ile kaydolmasını ve giriş yapmasını sağlamak. **Çözüm**: Firebase Authentication servisini kullanın. ```javascript // authService.js import { auth } from './firebase-config'; import { createUserWithEmailAndPassword, signInWithEmailAndPassword, signOut } from 'firebase/auth'; // Yeni kullanıcı kaydı export const registerUser = async (email, password) => { try { const userCredential = await createUserWithEmailAndPassword(auth, email, password); console.log('Kullanıcı başarıyla kaydedildi:', userCredential.user); return userCredential.user; } catch (error) { console.error('Kayıt hatası:', error.message); throw error; } }; // Kullanıcı girişi export const loginUser = async (email, password) => { try { const userCredential = await signInWithEmailAndPassword(auth, email, password); console.log('Kullanıcı başarıyla giriş yaptı:', userCredential.user); return userCredential.user; } catch (error) { console.error('Giriş hatası:', error.message); throw error; } }; // Kullanıcı çıkışı export const logoutUser = async () => { try { await signOut(auth); console.log('Kullanıcı başarıyla çıkış yaptı.'); } catch (error) { console.error('Çıkış hatası:', error.message); throw error; } }; ``` **Örnek 2: Firestore'a Veri Ekleme ve Okuma** **Problem**: Bir "yapılacaklar listesi" uygulaması için görevleri Firestore'a kaydetmek ve listelemek. **Çözüm**: Firestore'un `addDoc`, `getDocs` ve `onSnapshot` metodlarını kullanın. ```javascript // todoService.js import { db } from './firebase-config'; import { collection, addDoc, getDocs, query, orderBy, onSnapshot } from 'firebase/firestore'; const todosCollectionRef = collection(db, 'todos'); // Yeni görev ekleme export const addTodo = async (title, userId) => { try { const docRef = await addDoc(todosCollectionRef, { title, completed: false, createdAt: new Date(), userId // Hangi kullanıcının görevi olduğunu belirtmek için }); console.log('Görev eklendi, ID:', docRef.id); return docRef.id; } catch (error) { console.error('Görev ekleme hatası:', error.message); throw error; } }; // Tüm görevleri listeleme (tek seferlik) export const getTodosOnce = async () => { try { const q = query(todosCollectionRef, orderBy('createdAt', 'desc')); const querySnapshot = await getDocs(q); const todos = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); console.log('Tüm görevler (tek seferlik):', todos); return todos; } catch (error) { console.error('Görevleri getirme hatası:', error.message); throw error; } }; // Gerçek zamanlı görev listeleme export const subscribeToTodos = (callback) => { const q = query(todosCollectionRef, orderBy('createdAt', 'desc')); const unsubscribe = onSnapshot(q, (querySnapshot) => { const todos = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); callback(todos); }, (error) => { console.error('Gerçek zamanlı görevleri dinleme hatası:', error.message); }); return unsubscribe; // Dinlemeyi durdurmak için kullanılabilir }; ``` **Örnek 3: Dosya Yükleme (Cloud Storage)** **Problem**: Kullanıcıların profil resmi gibi dosyaları sunucuya yüklemesini sağlamak. **Çözüm**: Firebase Cloud Storage'ı kullanın. ```javascript // storageService.js import { storage } from './firebase-config'; import { ref, uploadBytes, getDownloadURL } from 'firebase/storage'; export const uploadFile = async (file, path) => { try { const storageRef = ref(storage, path); const snapshot = await uploadBytes(storageRef, file); const downloadURL = await getDownloadURL(snapshot.ref); console.log('Dosya yüklendi, URL:', downloadURL); return downloadURL; } catch (error) { console.error('Dosya yükleme hatası:', error.message); throw error; } }; // Kullanım örneği (bir input elementinden dosya seçildiğinde): /* const handleFileUpload = async (event) => { const file = event.target.files[0]; if (file) { const userId = auth.currentUser ? auth.currentUser.uid : 'anonymous'; const filePath = `profile-images/${userId}/${file.name}`; try { const url = await uploadFile(file, filePath); console.log('Profil resmi yüklendi:', url); // Profil resmini Firestore'a veya kullanıcının profil objesine kaydedebilirsiniz. } catch (error) { // Hata yönetimi } } }; */ ``` ### BÖLÜM 7 - İleri Seviye Teknikler (Advanced Patterns) Firebase projelerinizde ölçeklenebilirlik, güvenlik ve sürdürülebilirlik sağlamak için ileri seviye mimari desenleri ve teknikleri kullanmak kritik öneme sahiptir. **1. Sunucusuz Mikroservisler ile Cloud Functions** Büyük ve karmaşık uygulamalarda, tüm iş mantığını istemci tarafında tutmak yerine, Cloud Functions kullanarak sunucusuz mikroservisler oluşturmak performansı ve güvenliği artırır. Örneğin, hassas veritabanı işlemleri, ödeme entegrasyonları veya ağır hesaplama gerektiren görevler için Cloud Functions idealdir. **Problem**: Bir kullanıcının bir gönderi beğenmesi durumunda, gönderinin beğeni sayısını artırmak ve aynı zamanda kullanıcının beğendiği gönderiler listesine eklemek. Bu işlemi atomik ve güvenli bir şekilde yapmak. **Çözüm**: Firestore tetikleyicili bir Cloud Function kullanın. ```javascript // functions/index.js const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp(); const db = admin.firestore(); // Kullanıcı bir gönderiyi beğendiğinde çalışacak HTTP tetikleyicili fonksiyon // Güvenlik için, bu fonksiyonu Firebase Authentication ile korumak önemlidir. exports.likePost = functions.https.onCall(async (data, context) => { // Kullanıcının kimlik doğrulamasını kontrol et if (!context.auth) { throw new functions.https.HttpsError( 'unauthenticated', 'Bu işlemi yapmak için kimlik doğrulaması gereklidir.' ); } const userId = context.auth.uid; const postId = data.postId; if (!postId) { throw new functions.https.HttpsError( 'invalid-argument', 'Gönderi ID\'si eksik.' ); } const postRef = db.collection('posts').doc(postId); const userLikesRef = db.collection('users').doc(userId).collection('likes').doc(postId); // İşlemleri atomik olarak gerçekleştirmek için transaction kullan try { await db.runTransaction(async (transaction) => { const postDoc = await transaction.get(postRef); const userLikeDoc = await transaction.get(userLikesRef); if (!postDoc.exists) { throw new functions.https.HttpsError('not-found', 'Gönderi bulunamadı.'); } if (userLikeDoc.exists) { // Zaten beğenmişse, beğeniyi geri al transaction.update(postRef, { likesCount: admin.firestore.FieldValue.increment(-1) }); transaction.delete(userLikesRef); return { message: 'Beğeni geri alındı.', liked: false }; } else { // Beğen transaction.update(postRef, { likesCount: admin.firestore.FieldValue.increment(1) }); transaction.set(userLikesRef, { likedAt: admin.firestore.FieldValue.serverTimestamp() }); return { message: 'Gönderi beğenildi.', liked: true }; } }); return { success: true }; } catch (error) { console.error('Beğeni işlemi hatası:', error); throw new functions.https.HttpsError('internal', 'Beğeni işlemi sırasında bir hata oluştu.', error.message); } }); ``` **2. Veritabanı Güvenlik Kuralları (Firestore Security Rules)** Güvenlik kuralları, uygulamanızın kalbidir. Kullanıcıların hangi verilere erişebileceğini ve hangi işlemleri yapabileceğini belirler. 2026 itibarıyla, Firebase güvenlik kuralları oldukça esnek ve güçlüdür. **Problem**: Sadece oturum açmış kullanıcıların kendi görevlerini okuyabilmesi, yazabilmesi ve silebilmesi; diğer kullanıcıların görevlerine erişememesi. **Çözüm**: Firestore güvenlik kurallarını yapılandırın. ```firestore // firestore.rules rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // Tüm koleksiyonlar için genel kural match /{document=**} { allow read, write: if false; // Varsayılan olarak her şeyi reddet } // 'users' koleksiyonu: Sadece kendi profilini okuyabilir/yazabilir match /users/{userId} { allow read, update, delete: if request.auth != null && request.auth.uid == userId; allow create: if request.auth != null; // Oturum açmış herkes kendi profilini oluşturabilir } // 'todos' koleksiyonu: Sadece kendi görevlerini okuyabilir/yazabilir match /todos/{todoId} { allow read, write: if request.auth != null && request.auth.uid == resource.data.userId; allow create: if request.auth != null; // Oturum açmış herkes görev oluşturabilir } // 'posts' koleksiyonu: Herkes okuyabilir, sadece kendi gönderilerini yazabilir/güncelleyebilir/silebilir match /posts/{postId} { allow read: if true; allow create: if request.auth != null; allow update, delete: if request.auth != null && request.auth.uid == resource.data.authorId; } } } ``` > **Uyarı**: Güvenlik kurallarını yazarken çok dikkatli olun. Yanlış yapılandırılmış kurallar, verilerinizin yetkisiz erişime veya manipülasyona açık olmasına neden olabilir. Her zaman test edin ve `allow read, write: if true;` gibi genel kurallardan kaçının. ### BÖLÜM 8 - Best Practices & Anti-Patterns Firebase mimari tasarımında başarılı olmak için belirli en iyi uygulamaları takip etmek ve yaygın anti-pattern'lerden kaçınmak önemlidir. **✅ DOĞRU Uygulamalar:** * **Veritabanı Yapısını Dikkatli Tasarlayın**: Özellikle Firestore için, verilerinizi nasıl sorgulayacağınızı düşünerek koleksiyon ve belge yapılarını önceden planlayın. İlişkisel veritabanı mantığından uzaklaşarak, denormalizasyonu ve iç içe koleksiyonları (subcollections) etkin kullanın. Bu, sorgu performansını artırır ve maliyetleri düşürür. * **Güvenlik Kurallarını Titizlikle Yazın**: Her koleksiyon ve belge için minimum yetki prensibini uygulayın. Veri erişimini `request.auth.uid` ve `resource.data` kullanarak sıkıca kontrol edin. Kuralları yerel olarak test edin (`firebase emulators:start`). * **Cloud Functions'ı Stratejik Kullanın**: Hassas iş mantığı, ağır hesaplamalar, üçüncü taraf API entegrasyonları ve veritabanı tetikleyicileri için Cloud Functions'ı tercih edin. İstemci tarafında güvenli olmayan veya maliyetli işlemleri yapmaktan kaçının. * **İstemci Tarafı SDK'larını Modüler İçe Aktarın**: 2026 itibarıyla Firebase SDK v9+, modüler içe aktarımları destekler. Sadece ihtiyacınız olan servisleri içe aktararak uygulama boyutunu küçültün ve yükleme sürelerini optimize edin. (Örn: `import { getFirestore } from 'firebase/firestore';` yerine `import firebase from 'firebase/app';` kaçının.) * **Hata Yakalama ve Loglama**: Cloud Functions'larınızda kapsamlı hata yakalama mekanizmaları uygulayın ve Cloud Logging'i kullanarak fonksiyonlarınızın çalışma durumunu izleyin. Bu, sorun gidermeyi kolaylaştırır. * **Veri Okumalarını Optimize Edin**: Firestore'da belge okumaları maliyetlidir. Yalnızca ihtiyacınız olan verileri okuyun (örn: `select()` ile belirli alanları seçin), gerçek zamanlı dinlemeleri (onSnapshot) sadece gerçekten gerektiğinde kullanın ve sorgu limitlerini uygulayın. * **App Check Kullanın**: Uygulamanızın backend kaynaklarına yalnızca yetkili istemcilerin eriştiğinden emin olmak için Firebase App Check'i kullanın. Bu, kötü niyetli botların ve yetkisiz uygulamaların API'lerinizi kötüye kullanmasını engeller. * **Ortam Değişkenlerini Yönetin**: Hassas API anahtarlarını veya üçüncü taraf servis kimlik bilgilerini Cloud Functions'ta ortam değişkenleri (`functions.config()`) olarak saklayın, kodunuzda sabit kodlamaktan kaçının. **❌ YANLIŞ Uygulamalar (Anti-Patterns):** * **`allow read, write: if true;` Kullanmak**: Bu, uygulamanızın verilerini herkese açık hale getirir ve ciddi güvenlik açıkları oluşturur. Asla üretim ortamında kullanmayın. * **Karmaşık İlişkisel Veri Modelleri Oluşturmaya Çalışmak**: Firestore bir NoSQL veritabanıdır. İlişkisel veritabanı mantığını zorlamaya çalışmak, karmaşık sorgulara, performans sorunlarına ve yüksek maliyetlere yol açar. Denormalizasyon düşünün. * **Tüm İş Mantığını İstemci Tarafında Tutmak**: Güvenlik ve performans nedenleriyle, hassas veya yoğun işlem gerektiren iş mantığını Cloud Functions'a taşıyın. İstemci tarafındaki kod her zaman manipüle edilebilir. * **İstenmeyen Veri Okumaları**: `get()` çağrılarını veya `onSnapshot` dinleyicilerini, sadece ihtiyacınız olan veriyi getirecek şekilde filtrelememek, gereksiz maliyetlere ve performans düşüşüne neden olur. Büyük koleksiyonların tamamını okumaktan kaçının. * **API Anahtarlarını İstemci Tarafında Saklamak**: Firebase yapılandırma objesindeki `apiKey` gizli değildir ve istemci tarafında görünür. Ancak, diğer hassas API anahtarlarını (örn: Stripe gizli anahtarı) istemci tarafında tutmak büyük bir güvenlik riskidir. Bunları yalnızca Cloud Functions'ta veya güvenli bir backend'de saklayın. * **Aşırı İç İçe Koleksiyonlar**: Veritabanı tasarımında aşırı derin iç içe koleksiyonlar (örn: `/users/{userId}/posts/{postId}/comments/{commentId}/replies/{replyId}`) sorgulamayı karmaşıklaştırabilir ve performans sorunlarına yol açabilir. Genellikle 2-3 seviye derinlik idealdir. ### BÖLÜM 9 - Yaygın Hatalar ve Çözümleri (Troubleshooting) Firebase geliştirirken karşılaşılan bazı yaygın hatalar ve bunların çözümleri, geliştirme sürecinizi hızlandıracaktır. **1. Hata: Firestore Güvenlik Kuralları İhlali (`PERMISSION_DENIED`)** * **Problem**: Uygulamanızda Firestore'a yazmaya veya okumaya çalışırken `PERMISSION_DENIED` hatası alıyorsunuz. * **Sebep**: Firebase güvenlik kurallarınız, mevcut kullanıcının istediği işlemi yapmasına izin vermiyor. Bu genellikle ya kullanıcı kimliği doğrulanmamış olduğu için ya da kural mantığı yanlış olduğu için olur. * **Çözüm**: 1. **Kimlik Doğrulamasını Kontrol Edin**: Kullanıcının oturum açtığından emin olun (`firebase.auth().currentUser` objesini kontrol edin). 2. **Kural Mantığını İnceleyin**: Firestore kurallarınızı kontrol edin. Örneğin, `request.auth.uid == resource.data.userId` gibi bir kuralda, `resource.data.userId` alanının gerçekten belgede var olduğundan ve doğru kullanıcı ID'sini içerdiğinden emin olun. 3. **Yerel Emülatörleri Kullanın**: `firebase emulators:start` komutuyla Firebase emülatörlerini çalıştırarak güvenlik kurallarınızı yerel ortamda test edin. Bu, hataları hızlıca tespit etmenizi sağlar. **2. Hata: Cloud Function Zaman Aşımı (`Function execution took X ms, finished with status: 'timeout'`)** * **Problem**: Cloud Function'ınız belirtilen sürede tamamlanmıyor ve zaman aşımına uğruyor. * **Sebep**: Fonksiyonunuz çok uzun sürüyor veya bir sonsuz döngüye girmiş olabilir. Varsayılan zaman aşımı genellikle 60 saniyedir. * **Çözüm**: 1. **Fonksiyonunuzu Optimize Edin**: Ağır hesaplamaları veya uzun süren dış API çağrılarını optimize edin. 2. **Zaman Aşımını Artırın**: Gerekirse, `functions.runWith({ timeoutSeconds: 300 }).https.onCall(...)` gibi bir yapılandırma ile fonksiyonun zaman aşımını artırın (maksimum 540 saniye). Ancak bu, temel problemi çözmez, sadece erteleyebilir. 3. **Asenkron İşlemleri Doğru Yönetin**: Tüm Promise'lerin doğru bir şekilde `await` edildiğinden veya `Promise.all` ile beklendiğinden emin olun. Bir Promise'in çözülmesini beklemeden fonksiyonun sonlanması, beklenmedik davranışlara yol açabilir. **3. Hata: Firebase SDK Init Hatası (`Firebase: No Firebase App '[DEFAULT]' has been created...`)** * **Problem**: Uygulamanızı başlatırken `initializeApp()` çağrısının yapılmadığına dair bir hata alıyorsunuz. * **Sebep**: Firebase SDK'sını kullanmadan önce `initializeApp()` fonksiyonunu çağırmadınız veya yanlış yerde çağırdınız. * **Çözüm**: `firebase-config.js` dosyanızın uygulamanızın ana giriş noktasında (örn: `index.js` veya `App.js`) ilk çağrılan dosyalardan biri olduğundan emin olun. Modüler SDK v9+ kullanırken, her servis için ayrı ayrı `getFirestore(app)`, `getAuth(app)` gibi çağrıları yapmayı unutmayın. **4. Hata: Cloud Functions Dağıtım Hatası (`Error: The Cloud Functions deployment failed.`)** * **Problem**: `firebase deploy --only functions` komutuyla Cloud Functions'ı dağıtırken hata alıyorsunuz. * **Sebep**: Genellikle `package.json` bağımlılıkları eksik veya yanlış, Node.js versiyon uyumsuzluğu ya da kodunuzda syntax hatası var. * **Çözüm**: 1. **Bağımlılıkları Kontrol Edin**: `functions` dizininizdeki `package.json` dosyasında tüm gerekli bağımlılıkların (`firebase-admin`, `firebase-functions` vb.) listelendiğinden ve `npm install` komutuyla yüklendiğinden emin olun. 2. **Node.js Versiyonu**: `functions/package.json` dosyasındaki `engines` alanında desteklenen bir Node.js versiyonu belirttiğinizden emin olun (örn: `"engines": { "node": "18" }`). 2026 itibarıyla Firebase, Node.js 18 ve 20'yi desteklemektedir. 3. **Hata Mesajlarını Okuyun**: Terminaldeki dağıtım hatası mesajları genellikle sorunun kökeni hakkında ipuçları verir. Logları dikkatlice inceleyin. ### BÖLÜM 10 - Performans Optimizasyonu Firebase tabanlı uygulamaların performansını optimize etmek, kullanıcı deneyimini artırmanın ve maliyetleri düşürmenin anahtarıdır. İşte 2026 itibarıyla geçerli bazı kritik optimizasyon stratejileri: 1. **Veritabanı Okumalarını Minimuma İndirgeme**: * **Hedef**: Firestore ve Realtime Database okuma işlemlerinin maliyetini ve gecikmesini azaltmak. * **Strateji**: * **Sorguları Filtreleme**: Yalnızca ihtiyacınız olan verileri getirmek için `where()` ve `limit()` gibi sorgu operatörlerini kullanın. * **Belirli Alanları Seçme**: `select()` metodunu kullanarak sadece gerekli alanları okuyun. Örneğin, bir kullanıcı listesi gösterirken tüm profil verilerini değil, sadece isim ve ID'yi çekin. * **Veri Denormalizasyonu**: Sıkça birlikte erişilen verileri tek bir belgede veya koleksiyonda denormalize ederek birden fazla okuma ihtiyacını ortadan kaldırın. Örneğin, bir gönderi için yazarın adını doğrudan gönderi belgesinde saklamak, yazarın profilini ayrı ayrı okuma ihtiyacını ortadan kaldırır. * **Tek Seferlik Okumalar**: Gerçek zamanlı dinleyiciler (`onSnapshot`) yerine, verilerin nadiren değiştiği durumlarda `get()` metodunu kullanarak tek seferlik okumalar yapın. * **Örnek (Firestore Select):** ```javascript import { collection, query, getDocs, select } from 'firebase/firestore'; import { db } from './firebase-config'; const getUsersLite = async () => { const q = query(collection(db, 'users'), select('name', 'email')); // Sadece isim ve e-posta çek const querySnapshot = await getDocs(q); return querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); }; ``` 2. **Cloud Functions Optimizasyonu**: * **Hedef**: Fonksiyonların daha hı