• 30.10.2026 19:08:59
  • İbrahim Gökyar

Ember.js uygulamalarında veritabanı etkileşimini yönetmek için Ember Data kullanımı, ilişki modelleme, sorgulama stratejileri ve performans iyileştirmeleri. Offline, cache ve modern alternatiflere geçiş önerileri.

Ember Data ile Veritabanı Modelleri, İlişkiler ve Performans İyileştirme

Bu makalede Ember.js ile veritabanı katmanını yönetirken sıklıkla karşılaşılan modeller, ilişki türleri, sorgulama stratejileri ve performans optimizasyonlarını ele alacağım. Hedef kitle çalışan yazılımcılar olduğundan gerçek dünya problemlerine odaklanacağız: N+1 sorguları, lazy vs eager loading, cache ve offline kullanım senaryoları. Ayrıca Ember Data dışındaki modern alternatifler ve geçiş stratejilerinden de bahsedeceğim.

Ember Data temelleri: Model, adapter ve serializer

Ember Data, Ember uygulamaları için resmi veri yönetimi katmanıdır ve model, adapter, serializer üçlüsü etrafında çalışır. Model (DS.Model veya @ember-data/model) uygulama tarafında veri yapısını tanımlar; adapter sunucu bağlantısını (örn. REST/JSON:API) yönetir; serializer ise istek/yanıt dönüşümlerini yapar.

Basit bir örnek: bir Post modeli oluşturduğunuzda, ilişkilendirilen Comment modelleri ile nasıl bir yapı kurduğunuz performansı doğrudan etkiler. Aşağıdaki örnek JSON:API kullanımı için tipik bir model tanımıdır:

<!-- app/models/post.js -->
import Model, { attr, hasMany } from '@ember-data/model';

export default class PostModel extends Model {
  @attr('string') title;
  @attr('string') body;
  @hasMany('comment') comments;
}

<!-- app/models/comment.js -->
import Model, { attr, belongsTo } from '@ember-data/model';

export default class CommentModel extends Model {
  @attr('string') text;
  @belongsTo('post') post;
}

İlişkiler: async vs sync, yükleme stratejileri

Ember Data'da ilişkiler genellikle async (lazy) olarak tanımlanır; yani ilişkiye ilk erişildiğinde sunucu çağrısı yapılabilir. Bu davranış küçük veri setleri için uygun olsa da, büyük listelerde N+1 sorgu problemlerine neden olabilir. Bu yüzden eager loading (side-loading) ve server-side include parametrelerini kullanmak iyi bir pratik olur.

JSON:API kullanıyorsanız server-side include ile ilişkileri tek istekle alabilirsiniz. Backend'iniz destekliyorsa /posts?include=comments gibi bir istek yaparak hem post'ları hem ilişkili comment'leri tek seferde alabilirsiniz. Ember tarafında adapter/serializer ayarlarının JSON:API standardına uygun olduğundan emin olun.

Sorgulama stratejileri ve performans

Ember Data'daki findRecord, findAll, query ve queryRecord metodlarını kullanım amaçlarına göre seçmelisiniz. Büyük veri setleri için sayfalama (pagination), filtreleme ve sunucu tarafı sıralama tavsiye edilir. Client-side'da fazla filtreleme yapmak hem bellek tüketimini artırır hem de kullanıcının beklemesine neden olur.

Örnek: sayfalama uygulamak için backend'den paged response dönen bir endpoint'e query ile istek atabilirsiniz. Ember uygulamasında ise model hook veya route içindeki load fonksiyonunda uygun query parametreleri gönderilir:

// route
this.store.query('post', { page: { number: 1, size: 20 }, sort: '-createdAt' });

// controller veya component
let posts = await this.store.query('post', { filter: { tag: 'ember' } });

Ayrıca store.peekAll ve cache mekanizmalarını akıllıca kullanın. peekAll, zaten yüklenmiş kayıtları getirir; yeniden fetch etmez. Özellikle listeler için önbellek tuzaklarından kaçınmak adına TTL veya manuel invalidate stratejileri belirleyin.

Offline, cache ve tutarlılık yönetimi

Offline desteği veya arabellek (staging) senaryoları için tam kontrol gereklidir. Ember Data tek başına offline-first bir çözüm değildir, ama lokal persistence için IndexedDB kullanan ember-pouch veya custom adapter'lar ile birleştirilebilir. Burada anahtar konular conflict resolution ve eventual consistency'dir.

Eşzamanlı düzenleme (concurrent editing) senaryolarında optimistic update ile kullanıcı deneyimini iyileştirebilirsiniz; fakat backend onay sürecinde hata dönerse rollback mekanizması sağlamalısınız. Ember Data'nın record.rollbackAttributes() veya record.save().catch(...) gibi API'leri bu noktada işinize yarar.

// optimistic update örneği
let post = this.store.peekRecord('post', 42);
post.title = 'Yeni başlık';
post.save().catch((err) => {
  post.rollbackAttributes();
  // hata işleme
});

Profiling, debug ve araçlar

Performans sorunlarını tespit etmek için network profilini, Ember Inspector'ı ve adapter/serializer çıktısını birlikte kullanın. N+1 sorgularını tespit etmek için backend log'larını da inceleyin; client tarafında ise ilişkilerin ne zaman fetch edildiğini Ember Inspector üzerinden görebilirsiniz.

Ayrıca karmaşık serializer dönüşümlerinde serde (serialization/deserialization) maliyeti yüksek olabilir. Büyük payload'ları minimize etmek için sadece gerekli alanları ve ilişki bilgilerini döndürün. Partial responses (sadece ihtiyacınız olan alanları dönmek) API tarafında destekleniyorsa kullanın.

Ember Data mı, modern alternatifler mi?

Ember ve Ember Data güçlü bir bütünlük sunar: konvansiyonlar, router ve resmi data katmanı bir arada çalışır. Bununla birlikte takımınız veya projenizin ihtiyaçları farklıysa modern alternatifleri değerlendirmek mantıklıdır. Örneğin React ekosisteminde React Query veya SWR + ORM/normalizr kombinasyonları benzer işlevleri sunar. SvelteKit veya Solid gibi daha hafif framework'ler de UI performansı avantajı sağlar.

Geçiş kararı verirken dikkat edilmesi gerekenler: ekip yetkinliği, mevcut kod tabanının büyüklüğü, third-party entegrasyonlar ve veri model karmaşıklığı. Kademeli geçiş stratejisi, backend API'lerini standartlaştırma (ör. JSON:API veya GraphQL) ve adapter/contract'ları sabitleme ile daha güvenli olur. GraphQL kullanımı, istemci tarafında ihtiyaç duyulan veriyi tam olarak çekme imkanı vererek N+1 problemlerini azaltabilir; ancak sunucu tarafı resolver optimizasyonları gerektirir.

Sık Sorulan Sorular

Ember Data şart mı yoksa kendi veri katmanımı yazabilir miyim?

Ember Data zorunlu değildir; kendi store/adapter/serializer katmanınızı yazabilirsiniz. Ancak Ember Data, birçok ortak senaryoyu kapsar ve Ember konvansiyonlarıyla iyi çalışır. Küçük veya özel ihtiyaçlar için custom çözümler daha uygun olabilir.

N+1 sorgularını nasıl kesin olarak engellerim?

En etkili yol backend tarafında ilişkileri tek istekte dönecek şekilde (include/side-loading veya GraphQL ile gerekli alanları bir sorguda) desteklemektir. Ember tarafında async ilişkileri kontrol edip, gerektiğinde ilişki fetch'lerini önceden tetikleyerek de risk azaltılabilir.

Offline desteği eklemek zor mu?

Offline desteği eklemek, sadece veri depolamaktan daha fazlasını gerektirir: conflict çözümü, senkronizasyon stratejileri ve UI durum yönetimi gerekir. Ember ekosisteminde ember-pouch gibi adapter'lar işinizi kolaylaştırır; yine de senkronizasyon mantığını proje bazlı planlamalısınız.

Sonuç

Ember Data, Ember uygulamaları için güçlü ve konvansiyonel bir veri yönetim katmanı sağlar. Ancak performans ve ölçeklenebilirlik konusunda bilinçli olmak gerekir: ilişkiler, sorgulama stratejileri, cache yönetimi ve offline senaryolar dikkatle tasarlanmalıdır. Alternatifler değerlendirildiğinde API standardizasyonu (JSON:API veya GraphQL) ve kademeli geçiş stratejileri projeler için en az riskli yaklaşımlardır. Bu makaledeki pratikler ve örnekler, gerçek dünyadaki veri problemlerini tespit edip çözmeniz için bir başlangıç noktası sunar.