JavaScript Web Storage: localStorage ve sessionStorage

JavaScript Web Storage: localStorage ve sessionStorage
Web Storage API, tarayıcıda anahtar-değer çiftlerini saklamak için basit ve senkron bir mekanizma sunar. localStorage kalıcı, sessionStorage ise oturum bazlı depolama sağlar. Cookie'lere göre daha büyük kapasite ve daha kolay kullanım sunan Web Storage, kullanıcı tercihleri, form verileri ve uygulama durumu saklamak için yaygın olarak kullanılır.
1. localStorage ve sessionStorage Temelleri
Her iki depolama alanı da aynı API'yi paylaşır, ancak yaşam süreleri farklıdır.
// localStorage — kalıcı (tarayıcı kapatılsa bile kalır)
localStorage.setItem("tema", "koyu");
localStorage.setItem("dil", "tr");
const tema = localStorage.getItem("tema"); // "koyu"
const bilinmeyen = localStorage.getItem("yok"); // null
localStorage.removeItem("dil");
localStorage.clear(); // Tümünü sil
// sessionStorage — oturum bazlı (sekme kapatılınca silinir)
sessionStorage.setItem("sepet", JSON.stringify(["Laptop", "Mouse"]));
const sepet = JSON.parse(sessionStorage.getItem("sepet"));
// Tüm anahtarları listeleme
for (let i = 0; i < localStorage.length; i++) {
const anahtar = localStorage.key(i);
const deger = localStorage.getItem(anahtar);
console.log(`${anahtar}: ${deger}`);
}
// Object.keys alternatifi
const tumAnahtarlar = Object.keys(localStorage);
console.log(tumAnahtarlar);
2. JSON Veri Yönetimi
Web Storage yalnızca string saklar. Karmaşık veri tipleri için JSON serileştirme kullanılır.
// Güvenli Storage wrapper
class StorageManager {
#storage;
#onEk;
constructor(storage = localStorage,) {
this.#storage = storage;
this.#onEk = onEk;
}
#anahtarOlustur(anahtar) {
return `${this.#onEk}${anahtar}`;
}
kaydet(anahtar, deger, sureSaniye = null) {
const veri = {
deger,
olusturma: Date.now(),
sonlanma: sureSaniye ? Date.now() + sureSaniye * 1000 : null
};
try {
this.#storage.setItem(
this.#anahtarOlustur(anahtar),
JSON.stringify(veri)
);
return true;
} catch (hata) {
if (hata.name === "QuotaExceededError") {
console.warn("Depolama alanı dolu!");
this.eskiVerileriTemizle();
return false;
}
throw hata;
}
}
getir(anahtar, varsayilan = null) {
const ham = this.#storage.getItem(this.#anahtarOlustur(anahtar));
if (!ham) return varsayilan;
try {
const veri = JSON.parse(ham);
// Süre kontrolü
if (veri.sonlanma && Date.now() > veri.sonlanma) {
this.sil(anahtar);
return varsayilan;
}
return veri.deger;
} catch {
return varsayilan;
}
}
sil(anahtar) {
this.#storage.removeItem(this.#anahtarOlustur(anahtar));
}
eskiVerileriTemizle() {
const anahtarlar = Object.keys(this.#storage)
.filter(k => k.startsWith(this.#onEk));
for (const anahtar of anahtarlar) {
try {
const veri = JSON.parse(this.#storage.getItem(anahtar));
if (veri.sonlanma && Date.now() > veri.sonlanma) {
this.#storage.removeItem(anahtar);
}
} catch {
this.#storage.removeItem(anahtar);
}
}
}
}
// Kullanım
const storage = new StorageManager(localStorage, "blog_");
storage.kaydet("kullanici", { ad: "Tarık", rol: "admin" });
storage.kaydet("geciciToken", "abc123", 3600); // 1 saat geçerli
const kullanici = storage.getir("kullanici");
console.log(kullanici); // { ad: "Tarık", rol: "admin" }
3. Storage Event ile Sekmeler Arası İletişim
storage olayı, aynı origin'deki farklı sekmeler arasında iletişim kurmak için kullanılabilir.
// Diğer sekmelerdeki değişiklikleri dinleme
window.addEventListener("storage", (event) => {
console.log("Depolama değişti:", {
anahtar: event.key,
eskiDeger: event.oldValue,
yeniDeger: event.newValue,
url: event.url,
storage: event.storageArea
});
// Oturum durumu değişikliği
if (event.key === "oturum_durumu") {
if (event.newValue === "cikis") {
// Diğer sekmede çıkış yapıldı, bu sekmeyi de güncelle
window.location.href = "/giris";
}
}
// Tema değişikliği
if (event.key === "tema") {
document.documentElement.dataset.tema = event.newValue;
}
});
// Sekmeler arası mesajlaşma (BroadcastChannel alternatifi)
function mesajGonder(kanal, veri) {
const mesaj = JSON.stringify({ kanal, veri, zaman: Date.now() });
localStorage.setItem("_mesaj", mesaj);
localStorage.removeItem("_mesaj"); // Tetikle ve temizle
}
window.addEventListener("storage", (e) => {
if (e.key === "_mesaj" && e.newValue) {
const { kanal, veri } = JSON.parse(e.newValue);
console.log(`[${kanal}] Mesaj alındı:`, veri);
}
});
4. Güvenlik ve En İyi Pratikler
// ❌ YANLIŞ: Hassas veri saklama
localStorage.setItem("token", "gizli-jwt-token"); // XSS ile çalınabilir
localStorage.setItem("sifre", "12345"); // Asla!
// ✅ DOĞRU: Hassas veri için httpOnly cookie kullanın
// Veri şifreleme (basit obfuscation, gerçek güvenlik değil)
function basitSifrele(metin, anahtar) {
return btoa(
metin.split("").map((c, i) =>
String.fromCharCode(c.charCodeAt(0) ^ anahtar.charCodeAt(i % anahtar.length))
).join("")
);
}
// Depolama boyutu hesaplama
function storageBoyutu(storage = localStorage) {
let toplam = 0;
for (const anahtar of Object.keys(storage)) {
toplam += anahtar.length + storage.getItem(anahtar).length;
}
return {
byte: toplam * 2, // UTF-16
kb: ((toplam * 2) / 1024).toFixed(2),
mb: ((toplam * 2) / (1024 * 1024)).toFixed(4)
};
}
console.log(storageBoyutu());
// { byte: 2048, kb: "2.00", mb: "0.0020" }
// Feature detection
function storageKullanilabilir(tip = "localStorage") {
try {
const storage = window[tip];
const test = "__storage_test__";
storage.setItem(test, test);
storage.removeItem(test);
return true;
} catch {
return false;
}
}
if (!storageKullanilabilir()) {
console.warn("localStorage kullanılamıyor, fallback mekanizması aktif");
}
Sonuç
Web Storage API, istemci tarafında basit veri depolama için etkili bir araçtır. localStorage ile kalıcı tercihler, sessionStorage ile oturum bazlı veriler, storage event ile sekmeler arası iletişim ve güvenli wrapper'lar ile veri yönetimi modern web uygulamalarının temel ihtiyaçlarını karşılar. Hassas veriler için alternatif mekanizmalar kullanmayı ve kapasite sınırlarını göz önünde bulundurmayı unutmayın.