
Modern Frontend'in Derinlikleri: Main Thread vs Web Workers
Her JavaScript geliştiricisi, hayatında en az bir kez şu cümleyi duymuştur: "JavaScript single thread'dir."
Peki bu ne anlama gelir? Daha da önemlisi, bu durum uygulamalarımızı ve kullanıcı deneyimini nasıl etkiler?
Bu, tarayıcıda çalışan her şeyin (DOM güncellemeleri, kullanıcı etkileşimleri, API çağrıları, animasyonlar, hatta konsola yazdırdığın bir console.log() bile) aynı hat üzerinden ve sırayla işlenmesi anlamına gelir. Bu hatta Main Thread denir.
Yani tüm işlemler tek bir kuyrukta bekler. Eğer bu sırada zaman alan bir işlem gerçekleşiyorsa, diğer her işlem o işlemin bitmesini beklemek zorundadır. Bu da tıklamaları, kaydırmayı ve animasyonları kapsar. Ve kullanıcılar beklemek zorunda kaldığında... giderler. (Google'a göre, küçük bir gecikme bile %50'nin üzerinde kullanıcı kaybına yol açabilir.)
Bu yazıda, JavaScript'in single thread yapısının getirdiği sınırlamaları, bu sınırların gerçek projelerde nasıl hissedildiğini ve bu durumla başa çıkmak için elimizdeki en etkili araçlardan biri olan Web Workers'ı ele alacağız.
Bunu basit bir benzetmeyle açalım.
Bir Restoran Düşün...
Düşün ki bir restorandasın. Garson sipariş alıyor, mutfağa iletiyor, yemekleri masaya getiriyor, boş tabakları topluyor, masayı siliyor, hatta hesabı bile o alıyor… Yani restoranda her şeyi tek başına yapan bir garson var.
Eğer bir masa karmaşık bir sipariş verirse ya da uzun süreli bir işlem (mesela doğum günü pastası hazırlığı) isterse, garson oraya kitlenir. Diğer masalara ne sipariş alınabilir, ne servis yapılabilir. Bir süre sonra müşteriler sabırsızlanır, sinirlenir, hatta masadan kalkıp gidebilirler.
İşte o garson senin Main Thread'in.
Frontend'de de aynı şey olur. Eğer JavaScript, yani Main Thread, uzun süren bir işlemi üstlenirse (büyük bir veri seti, ağır bir hesaplama ya da zaman alan bir API cevabı) kullanıcı arayüzü donar. Butonlar tıklanamaz hâle gelir, animasyonlar takılır. Sayfa "çöktü mü?" hissi verir. Ve sonunda kullanıcıların %50'si, bir daha geri dönmemek üzere sayfayı terk edebilir.
Peki bu yoğunluğu nasıl yönetebiliriz? Garsona bir yardımcı (komi) getirmek gibi. İşte burada Web Workers devreye giriyor…
Web Worker Nedir?
Restoran örneğimize geri dönelim. Yardımcı (komi), garsonun zamanını alan işleri (mesela uzun süren siparişleri hazırlamak ya da pastayı süslemek gibi) arka planda hallediyor. Garson da bu sırada diğer masalara servis yapmaya, yeni siparişler almaya devam ediyor.
İşte Web Worker, JavaScript dünyasında tam olarak bu yardımcıdır. Web Worker, Main Thread dışında çalışan bağımsız bir iş parçacığıdır. Ona belli bir işi verirsin, o kendi başına halleder. Bu sırada Main Thread kullanıcı arayüzüyle ilgilenmeye devam eder: butonlara cevap verir, animasyonları çalıştırır, DOM güncellemelerini yapar.
Kısaca:
- Web Worker, tarayıcı içinde çalışan arka plan işçisidir.
- Main Thread'den bağımsızdır ama onunla mesajlaşarak iletişim kurar (
postMessage,onmessage). - DOM'a erişemez, bu yüzden yalnızca hesaplama ve veri işleme gibi görevlerde kullanılır.
- En büyük avantajı: UI'yi dondurmadan işlem yapabilmesidir.
Temel Örnek: Main Thread vs Web Worker
Web Worker'ın temel mantığı oldukça basittir: Main Thread ile Worker arasında bir iletişim kurulur. Bu iletişim postMessage() ile veri göndererek, onmessage ile cevap alarak sağlanır.
// main.js
const worker = new Worker('worker.js');
worker.postMessage(100000000); // Worker'a veri gönder
worker.onmessage = function (e) {
console.log('Sonuç:', e.data);
};
// worker.js
onmessage = function (e) {
let total = 0;
for (let i = 0; i < e.data; i++) {
total += i;
}
postMessage(total); // Hesaplanan sonucu Main Thread'e gönder
};
Bu örnekte, büyük bir döngü arka planda çalışıyor. Main Thread bu sırada serbest kalıyor ve kullanıcı arayüzü donmuyor.
Web Worker vs Main Thread: Gerçek Zamanlı Karşılaştırma
Gözle görülür ve doğrudan hissedilebilir bir farkı ortaya koymak için basit bir demo arayüz hazırladım. Bu arayüzde, büyük boyutlu bir JSON verisi hem Main Thread hem de Web Worker üzerinden işlenebiliyor. Böylece Web Worker'ın arka planda nasıl sorunsuz çalışmaya devam ettiğini, buna karşılık Main Thread'in ne kadar kolay tıkanabildiğini doğrudan gözlemleyebiliyorsunuz.
Gerçek hayatta karşımıza çıkabilecek PDF/görsel aktarımı, WebSocket bağlantıları, API polling ya da canvas çizimi gibi zaman alan işlemleri; ayrıca kullanıcının cihazının düşük işlem gücüne sahip olması veya yavaş internet bağlantısı gibi senaryoları simüle edebilmek için, hem Main Thread'e hem de Web Worker'a 2 saniyelik yapay bir gecikme ekledim.
Bu amaçla aşağıdaki gibi basit bir "gecikme simülasyonu" fonksiyonu kullandım:
function simulateProcessingDelay(duration = 2000) {
const startTime = Date.now();
while (Date.now() - startTime < duration) {
// Boş bir döngü ile 2000ms (2sn) bekleme
}
}

Demo ve Kaynak Kodlar
Aşağıdaki görsel, aynı veri işleme işleminin hem Web Worker hem de Main Thread üzerinde nasıl sonuçlandığını yan yana gösteriyor. Her iki tarafta da 2 saniyelik yapay bir gecikme uygulanarak eşit koşullar oluşturuldu.
Canlı Demo: https://canbulgay.github.io/web-workers-vs-main-thread/?lang=tr
Kaynak Kod: https://github.com/canbulgay/web-workers-vs-main-thread
Ne Zaman Web Worker Kullanılmalı?
Web Worker, her senaryoda kullanılacak bir araç değildir. Ancak bazı işlemler vardır ki, Main Thread'e yüklendiğinde kullanıcı arayüzünü ciddi şekilde etkileyebilir. İşte Web Worker'ların gerçekten fark yarattığı senaryolar:
Ağır Hesaplamalar
Büyük veri kümeleri üzerinde döngü çalıştırmak, matematiksel analizler, filtreleme ve sıralama işlemleri.
Single Page Application (SPA)
SPA mimarileri, tek bir HTML dosyası üzerinden çalışan ve içerik değişimini JavaScript ile yöneten uygulamalardır. Bu yapı; yönlendirme, veri yönetimi ve bileşen güncellemeleri gibi tüm kullanıcı deneyimini JavaScript'e yükler. Bu nedenle SPA'lerde Main Thread zaten yoğun çalışır. Eğer buna ağır işlemler de eklenirse, sayfa kolayca donar veya yavaşlar.
Veri Şifreleme / Çözme
Kriptografik algoritmalar ve kullanıcı verilerinin tarayıcı tarafında şifrelenmesi.
Canvas Çizimleri & Görsel İşleme
Yüksek çözünürlüklü görsellerin işlenmesi, dinamik grafik çizimleri ve piksel düzeyinde hesaplamalar (örneğin oyun motorları). Bu işlemler ciddi CPU kullanır, ana thread'i meşgul etmemelidir.
Büyük Dosya İşleme
PDF oluşturma/parçalama, görsellerin optimize edilmesi ve yeniden boyutlandırılması gibi zaman alan işlemler Main Thread dışında çalışmaktan fayda görür.
Ağ Tabanlı İşlemler
WebSocket veya API polling ile sürekli veri akışı; gelen güncellemelerin UI güncellenmeden önce işlenmesi gereken durumlar.
Ne Zaman Kullanılmamalı?
Web Worker'lar faydalı olsa da her zaman doğru seçim değildir. İşte onları kullanmaman gereken durumlar:
DOM ile Etkileşim Gereken İşlemler
Web Worker'lar DOM'a erişemez. Yani document, window, localStorage, alert, console.log gibi tarayıcıya özgü API'ler Worker içinde kullanılamaz.
Basit ve Hızlı İşlemler
Çok küçük veya hızlı tamamlanacak işlemler için Worker kullanmak fazladan karmaşıklık getirir. Worker oluşturmak, mesaj gönderip sonucu beklemek gibi işlemler ek maliyet yaratır.
Çok Sayıda Worker Kullanmak
Her Worker, tarayıcı içinde ayrı bir thread oluşturur ve sistem kaynaklarını tüketir. Birden fazla Worker gereksiz yere oluşturulursa bellek kullanımı artar, performans düşebilir. Gerekirse tek bir Worker içinde işlem kuyruğu oluştur, işlem paylaşımı yap; thread havuzu (thread pool) benzeri çözümler düşün.
Veriyi Sık Sık Ana Thread'e Taşımak
Worker ile Main Thread arasında veri aktarımı postMessage() ile yapılır. Eğer sık sık büyük veriler aktarılıyorsa, bu iletişim süreci performansı düşürebilir. Veri aktarımını minimize et; mümkünse Transferable Objects (örneğin ArrayBuffer) gibi hafif veri yapıları kullan.
Toparlayalım
Özellikle işlem süresi 100ms'yi aşan CPU yoğun görevlerde, arka arkaya gelen WebSocket güncellemeleri gibi gerçek zamanlı veri akışlarında, düşük performanslı cihazlarda (örneğin mobil veya eski donanımlarda) ya da kullanıcı arayüzünün kesintisiz çalışmasının kritik olduğu durumlarda (Figma, Canva, medya oynatıcıları veya canlı doküman düzenleme araçlarında olduğu gibi) Web Worker kullanımı neredeyse kaçınılmaz hâle gelir.
Kısacası, Web Worker doğru yerde kullanıldığında uygulamanın sadece hızını değil, kalitesini ve güvenilirliğini de artırır.