Tab'lar Arası Veri Eşleme: BroadcastChannel API
Web uygulamalarının karmaşıklığı gün geçtikçe artarken, kullanıcıların aynı web uygulamasını aynı anda birden fazla tarayıcı sekmesinde açık tutması oldukça yaygın bir kullanım alışkanlığı haline geldi. Bir e-ticaret platformunda kullanıcının bir sekmede sepetine ürün eklemesi, bir başka sekmede oturumu kapatması veya bir yönetim panelinde bildirimleri okundu olarak işaretlemesi durumunda, bu eylemlerin diğer açık sekmelere anında yansıması gerekir. Sekmeler arası durum senkronizasyonu sağlanmadığında kullanıcı deneyimi ciddi şekilde zarar görür ve tutarsız veri durumları ortaya çıkar.
localStorage Event Hack'lerinin Maliyeti ve Sınırları
Yıllardır istemci tarafı web geliştirmede bu senkronizasyon ihtiyacını karşılamak adına geliştiriciler sıklıkla localStorage mekanizmasına başvurmuşlardır. Bir sekmede localStorage.setItem('logout-event', Date.now()) şeklinde bir anahtar-değer çifti yazılır ve diğer sekmelerde tanımlanan window.addEventListener('storage', ...) olay dinleyicisi ile bu değişiklik yakalanmaya çalışılır. Bu yaklaşım yüzeysel olarak çalışan bir mesajlaşma veriyolu (message bus) hissi uyandırsa da, özünde depolama amacıyla tasarlanmış bir yapının iletişim amacıyla kötüye kullanılmasıdır (hack).
Teknik açıdan incelendiğinde, localStorage senkron (synchronous) çalışan ve verileri doğrudan istemcinin diskine (SSD/HDD) yazan bir depolama alanıdır. Sekmeler arası basit bir mesaj iletmek istediğinizde bile tarayıcıyı disk I/O (Girdi/Çıktı) operasyonu yapmaya zorlarsınız. Yüksek frekansta veri güncellenen karmaşık uygulamalarda bu senkron disk erişimleri ana iş parçacığını (main thread) bloke edebilir ve arayüzde takılmalara yol açabilir. Ayrıca karmaşık JavaScript nesnelerini iletebilmek için veriyi JSON.stringify ile serileştirmek ve alıcı sekmede JSON.parse ile çözmek gerekir, bu da ekstra bir CPU maliyeti getirir.
Bunun da ötesinde storage olayı sadece olayı tetikleyen sekmenin haricindeki diğer sekmelerde çalışır. Eğer mevcut sekmede de aynı mantığın çalışmasını istiyorsanız ek bir kod yazmanız ve kendi durumunuzu manuel tetiklemeniz gerekir. Yaklaşık 5 MB ile sınırlı depolama alanı ve tarayıcı tabanlı kota aşımları da cabasıdır. Sonuç olarak, mesajlaşma ihtiyacı için localStorage kullanmak zamanla sürdürülebilirliği düşük, teknik borcu yüksek bir mimari ortaya çıkarır.
BroadcastChannel API İle Doğrudan Bellek İletişimi
Modern web standartlarında bu problemi çözmek için native olarak geliştirilen BroadcastChannel API, HTML5 spesifikasyonu ile hayatımıza giren ve günümüzde tüm modern tarayıcılarda varsayılan olarak desteklenen bir iletişim arayüzüdür. Aynı orijine (same-origin: protokol, alan adı ve port kombinasyonu aynı olan) sahip tarayıcı bağlamları arasında (sekmeler, iframe'ler, açılır pencereler ve Web Worker'lar) doğrudan mesajlaşma imkanı sunar.
BroadcastChannel, temel olarak Publish/Subscribe (Yayıncı/Abone) tasarım desenini uygular. En büyük avantajı, verileri diske yazmadan tamamen bellek (RAM) seviyesinde tarayıcının süreçler arası iletişim (Inter-Process Communication - IPC) mekanizmalarını kullanarak iletmesidir. Bu sayede senkron disk I/O yükü tamamen ortadan kalkar ve haberleşme milisaniyeler mertebesinde gerçekleşir.
BroadcastChannel API, bellek içi mesajlaşma yapısı sayesinde senkron disk I/O yükünü tamamen ortadan kaldırarak sekmeler arası haberleşmeyi milisaniyeler mertebesine indirir ve veri serileştirme yükünü Structured Clone algoritmasıyla hafifletir.
Ayrıca BroadcastChannel veri transferi yaparken arka planda HTML standardının bir parçası olan Structured Clone algoritmasını kullanır. Bu algoritma sayesinde JSON serileştirmesine gerek kalmadan Date, RegExp, Blob, File ve ArrayBuffer gibi karmaşık karmaşık veri türleri ve mantıksal veri yapıları doğrudan iletilebilir.
const channel = new BroadcastChannel('user_session');
channel.postMessage({ type: 'LOGOUT', timestamp: Date.now() });
channel.onmessage = (event) => {
if (event.data.type === 'LOGOUT') {
window.location.href = '/login';
}
};React Mimarisine Custom Hook İle Entegrasyon
Bileşen tabanlı modern kütüphanelerde, örneğin React mimarisinde BroadcastChannel API kullanımını sürdürülebilir kılmak için bu mantığı bir custom hook içerisine soyutlamak en temiz yaklaşımdır. Doğrudan bileşen lifecycle'ı içerisinde rastgele kanallar oluşturmak, zamanla bellek sızıntılarına (memory leak) ve birden fazla dinleyicinin aynı kanala bağlanmasına (duplicate event listeners) neden olabilir.
Tasarlanacak bir hook'un kanal adını ve gelen mesajları işleyecek bir geri çağırım (callback) fonksiyonunu parametre olarak alması gerekir. En kritik nokta ise React'in useEffect cleanup (temizlik) fonksiyonu içerisinde channel.close() metodunun çağrılarak tarayıcı hafızasında açık kalan kanal bağlantılarının güvenli bir şekilde sonlandırılmasıdır.
function useBroadcastChannel(channelName, onMessage) {
useEffect(() => {
const channel = new BroadcastChannel(channelName);
channel.onmessage = (e) => onMessage(e.data);
return () => channel.close();
}, [channelName, onMessage]);
}Bu custom hook yapısı, global durum yönetim kütüphaneleriyle (Zustand, Redux Toolkit veya React Context) son derece uyumlu çalışır. Örneğin bir e-ticaret uygulamasında kullanıcı sepetine ürün eklediğinde, durum güncellenirken aynı zamanda postMessage ile diğer sekmelere bilgi verilir. Diğer sekmelerde çalışan hook, gelen mesajı dinleyerek global store'u günceller. Böylece istemci tarafında sayfayı yenilemeye gerek kalmadan tüm sekmeler eşzamanlı olarak senkronize olur.
Hangi Durumda Hangi Yöntem Tercih Edilmeli?
Yazılım mimarisinde her senaryoya uyan tek bir gümüş kurşun olmadığını bilmek önemlidir. Sekmeler arası durum ve veri senkronizasyonu gereksinimlerinde localStorage, BroadcastChannel API ve SharedWorker gibi çözümler bulunmaktadır ve her birinin odaklandığı problem farklıdır.
Projelerinizde doğru aracı seçebilmeniz için dikkat edilmesi gereken temel farklar şunlardır:
- localStorage (Storage Events): Verinin tarayıcı kapatılıp açılsa bile kalıcı olarak saklanması gereken senaryolar (kullanıcının karanlık mod tercihi, dil seçimi, yetkilendirme token'ları) için kullanılmalıdır. Yalnızca sekmelere mesaj iletmek amacıyla bir olay tetikleme aracı olarak kullanılmamalıdır.
- BroadcastChannel API: Kalıcılık gerektirmeyen, aynı orijindeki sekmeler, pencere klasörleri veya worker'lar arasında anlık durum ve olay senkronizasyonu için en ideal seçenektir. Yüksek performanslı, asenkron ve temiz bir JavaScript API'sidir.
- SharedWorker: Sekmeler arası sadece mesaj iletmekle kalmayıp, ortak bir durumu (state) tek bir merkezde tutmak, arka planda veri işlemek veya tek bir WebSocket bağlantısını tüm sekmeler arasında ortaklaşa kullanmak gerektiğinde tercih edilmelidir.
Özetle, sadece sekmeleri birbiriyle haberleştirmek amacıyla localStorage üzerine kurulu hack'lere başvurmak günümüz web standartlarında teknik borç oluşturur. Sekmeler arası anlık olay bildirimlerinde tarayıcının sunduğu native BroadcastChannel API arayüzünü kullanmak, uygulamanızın hem kod kalitesini hem de çalışma zamanı performansını belirgin şekilde artıracaktır. Bir sonraki projenizde durum senkronizasyonunu kurgularken bu yerleşik arayüzü mimarinize dahil etmeyi değerlendirebilirsiniz.