Node.js İle Websocket Üzerinden Gerçek Zamanlı Veri Senkronizasyonu Nasıl Yapılır?

Node.js İle Websocket Üzerinden Gerçek Zamanlı Veri Senkronizasyonu Nasıl Yapılır?
Node.js İle Websocket Üzerinden Gerçek Zamanlı Veri Senkronizasyonu Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Gerçek zamanlı bir uygulama geliştirmeye başlamadan önce, sisteminizde Node.js'in güncel bir LTS (Long Term Support) sürümünün kurulu olduğundan emin olmalısınız. 2026 yılı standartları gereği, en az Node.js 22.x sürümünü kullanmanızı öneririm.

  • Node.js: v22.x veya üzeri.
  • npm veya pnpm: Paket yöneticisi.
  • Socket.io: Gerçek zamanlı iletişim için endüstri standardı kütüphane.
  • Express: HTTP sunucusu yönetimi için temel altyapı.

Projeyi başlatmak için bir klasör oluşturun ve gerekli bağımlılıkları yükleyin:

mkdir websocket-projesi
cd websocket-projesi
npm init -y
npm install express socket.io

Bu komutlar, projenizin temel yapılandırmasını oluşturacak ve ihtiyaç duyduğumuz kütüphaneleri node_modules klasörüne dahil edecektir.

Temel Sunucu Kurulumu ve Websocket Entegrasyonu

Websocket, standart HTTP protokolünün üzerine kurulan çift yönlü bir iletişim kanalıdır. Node.js üzerinde Express ile bir HTTP sunucusu oluşturup, Socket.io'yu bu sunucuya bağlamamız gerekir. Aşağıdaki kod bloğu, temel bir sunucu kurulumunu göstermektedir.

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = new Server(server);

io.on('connection', (socket) => {
  console.log('Bir kullanıcı bağlandı: ' + socket.id);

  socket.on('disconnect', () => {
    console.log('Kullanıcı ayrıldı');
  });
});

server.listen(3000, () => {
  console.log('Sunucu http://localhost:3000 adresinde çalışıyor');
});

Bu kodda, http.createServer kullanarak Express uygulamasını bir HTTP sunucusu haline getirdik ve Socket.io'yu bu sunucunun üzerine "bind" ettik. io.on('connection') bloğu, her yeni bağlantıda tetiklenir ve benzersiz bir socket.id oluşturur.

İstemci Tarafında Bağlantı Kurma

Sunucu tarafı hazır olduğuna göre, şimdi tarayıcıda çalışan istemcinin bu sunucuya nasıl bağlanacağını görelim. Socket.io, istemci tarafı için otomatik olarak bir istemci kütüphanesi sunar.



  const socket = io();

  socket.on('connect', () => {
    console.log('Sunucuya başarıyla bağlandınız, ID:', socket.id);
  });

İstemci tarafında io() fonksiyonunu çağırdığınızda, Socket.io otomatik olarak sunucunun bulunduğu adrese bir bağlantı isteği gönderir. connect olayı, bağlantı sağlandığında tetiklenir.

Gerçek Zamanlı Veri Gönderimi ve Dinleme

Veri senkronizasyonunun kalbi, emit ve on metodlarıdır. emit ile veri göndeririz, on ile gelen veriyi karşılarız. Aşağıdaki örnekte, istemciden sunucuya bir mesaj gönderip, sunucunun bunu tüm bağlı istemcilere yayınlamasını sağlıyoruz.

// Sunucu tarafı: Gelen veriyi tüm istemcilere yay (Broadcast)
socket.on('yeni-mesaj', (data) => {
  console.log('Gelen veri:', data);
  io.emit('mesaj-alindi', data);
});

// İstemci tarafı: Mesaj gönderme
socket.emit('yeni-mesaj', { metin: 'Merhaba Dünya!', zaman: Date.now() });

// İstemci tarafı: Yayınlanan mesajı dinleme
socket.on('mesaj-alindi', (data) => {
  console.log('Yeni mesaj:', data.metin);
});

Burada io.emit kullanmak, sunucuya bağlı olan tüm istemcilere veriyi iletir. Eğer sadece mesajı gönderen kişiye yanıt vermek isteseydik socket.emit kullanmamız yeterli olacaktı.

Websocket İletişim Yöntemleri Karşılaştırması

Yöntem Kullanım Amacı Avantajı
socket.emit Birebir iletişim Hızlı ve spesifik
io.emit Genel yayın (Broadcast) Tüm kullanıcılara anlık güncelleme
socket.to(room).emit Oda bazlı iletişim Segmentasyon ve performans

Güvenlik ve Ölçeklendirme Uyarıları

Kritik Güvenlik Uyarısı: Websocket bağlantılarında "Cross-Origin Resource Sharing" (CORS) ayarlarını mutlaka kısıtlayın. Üretim ortamında (production), io nesnesini tanımlarken sadece güvenilir domainlere izin verin. Ayrıca, gelen verileri asla doğrudan veritabanına veya HTML'e yazdırmayın; XSS ve SQL Injection saldırılarına karşı veriyi mutlaka doğrulayın (sanitizasyon yapın).

Ölçeklendirme için, uygulamanız birden fazla sunucuya (instance) yayıldığında "Redis Adapter" kullanmanız gerekecektir. Bu, farklı sunuculardaki kullanıcıların birbirleriyle senkronize olmasını sağlar.

Sıkça Sorulan Sorular

Websocket bağlantısı sürekli kopuyor, ne yapmalıyım?

Bu durum genellikle yük dengeleyicilerin (load balancer) bağlantıyı zaman aşımına uğratmasından kaynaklanır. Socket.io'nun "heartbeat" (kalp atışı) mekanizması bağlantıyı canlı tutar, ancak proxy ayarlarınızın "upgrade" başlıklarına izin verdiğinden emin olun.

Websocket yerine neden HTTP Polling kullanmıyoruz?

HTTP Polling, sunucuya sürekli istek atarak kaynak tüketir ve yüksek gecikmeye sebep olur. Websocket ise tek bir TCP bağlantısı üzerinden çift yönlü ve düşük gecikmeli iletişim sağlar.

Socket.io yerine neden "native" Websocket kullanmıyoruz?

Native Websocket; otomatik yeniden bağlanma, oda yönetimi, binary veri desteği ve eski tarayıcı uyumluluğu gibi özellikleri sunmaz. Socket.io, bu karmaşık süreçleri yönetmek için geliştirilmiş bir kütüphanedir.

Veri güvenliğini nasıl sağlarım?

Bağlantı kurulurken "middleware" kullanarak JWT (JSON Web Token) ile kimlik doğrulama yapın. Yetkisiz bağlantıları next(new Error('Yetkisiz')) ile reddedin.

Oda (Room) yapısı nedir?

Oda yapısı, kullanıcıları gruplandırmanıza yarar. Örneğin, bir chat uygulamasında kullanıcıları "genel" veya "destek" gibi odalara ayırarak sadece ilgili kişilere veri gönderebilirsiniz.

WebSocket Uygulamalarında Hata Ayıklama ve Performans İzleme

Gerçek zamanlı uygulamalar, geleneksel HTTP tabanlı sistemlere göre daha karmaşık bir hata ayıklama sürecine sahiptir. Bağlantı kopmaları, paket kayıpları veya yüksek gecikme süreleri (latency), kullanıcı deneyimini doğrudan etkiler. Uygulamanızın performansını optimize etmek için aşağıdaki stratejileri izleyebilirsiniz.

Geliştirme Aşamasında Hata Ayıklama

Socket.io ile çalışırken, sunucu tarafında yaşanan olayları izlemek için DEBUG ortam değişkenini kullanabilirsiniz. Bu, bağlantı süreçlerini ve paket akışını konsolda detaylı bir şekilde görmenizi sağlar.

# Linux/macOS için
DEBUG=socket.io:* node server.js

# Windows (PowerShell) için
$env:DEBUG="socket.io:*"; node server.js

İstemci tarafında ise tarayıcınızın "Network" sekmesinde yer alan "WS" (WebSocket) filtresini kullanarak gönderilen ve alınan çerçeveleri (frames) inceleyebilirsiniz. Eğer veri gönderilmiyor ancak hata da alınmıyorsa, genellikle bir "Event Listener" çakışması veya yanlış "Namespace" kullanımı söz konusudur.

Performans Optimizasyonu İçin İpuçları

WebSocket üzerinden çok fazla veri gönderimi, istemci tarafında "Main Thread"in kilitlenmesine neden olabilir. Performansı artırmak için şu yöntemleri uygulayın:

  • Veri Sıkıştırma: Büyük JSON objeleri göndermek yerine, veriyi sıkıştırın veya sadece değişen alanları (delta) gönderin.
  • Throttling (Kısıtlama): Özellikle mouse hareketi veya scroll gibi sürekli tetiklenen olaylarda, veriyi her milisaniyede değil, belirli aralıklarla (örneğin 50ms'de bir) gönderin.
  • Binary Veri Kullanımı: Metin tabanlı JSON yerine, daha küçük boyutlu olan ArrayBuffer veya Blob formatlarını tercih edin.
// İstemci tarafında veri gönderimini kısıtlama örneği
let lastEmit = 0;
const throttleLimit = 100; // ms

function sendData(data) {
    const now = Date.now();
    if (now - lastEmit > throttleLimit) {
        socket.emit('update', data);
        lastEmit = now;
    }
}

WebSocket Uygulamalarını Yayına Alma (Deployment)

Uygulamanızı yerel ortamdan canlı sunucuya taşırken dikkat etmeniz gereken en kritik nokta, WebSocket bağlantısının "Upgrade" aşamasıdır. Nginx gibi bir ters vekil sunucu (reverse proxy) kullanıyorsanız, WebSocket trafiğine izin verecek şekilde yapılandırmanız gerekir.

Nginx Konfigürasyonu

Nginx üzerinden WebSocket trafiğini yönlendirmek için Upgrade ve Connection başlıklarını doğru yapılandırmalısınız:

location /socket.io/ {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
}

Ölçeklenebilirlik İçin Redis Adaptörü

Uygulamanız büyüdüğünde, tek bir sunucu yetersiz kalacaktır. Birden fazla sunucuya geçtiğinizde, bir sunucuya bağlı olan istemci diğer sunucudaki istemciye mesaj gönderemez. Bu sorunu çözmek için socket.io-redis paketini kullanarak tüm sunucuları bir "Message Broker" (Redis) üzerinden birbirine bağlayabilirsiniz.

const redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));

Bu yapı sayesinde, bir odadaki mesajlar Redis üzerinden tüm sunuculara dağıtılır ve gerçek zamanlı senkronizasyon kesintisiz devam eder.

Sonuç

Node.js ve Socket.io kullanarak gerçek zamanlı veri senkronizasyonu kurmak, uygulamanızın interaktiflik seviyesini bir üst seviyeye taşır. Bu rehberde öğrendiğiniz temel bağlantı, veri yayını ve güvenlik prensipleri, daha karmaşık sistemlerin temelini oluşturur. Bir sonraki adım olarak, bu yapıyı bir veritabanı (örneğin MongoDB veya PostgreSQL) ile entegre ederek verilerin kalıcı hale getirilmesini ve "Redis" kullanarak çoklu sunucu mimarisine geçişi araştırmanızı öneririm.

Not: Bu içerik, yazılım geliştirme süreçlerinde en iyi pratikleri yansıtmak amacıyla hazırlanmıştır. Uygulamanızın canlıya alınması aşamasında güvenlik duvarı ve HTTPS konfigürasyonlarını mutlaka tamamlayın.

Bu yazıya tepkinizi paylaşın:
Kerem Demir

Mutfak pratikleri ve ev ekonomisi konularında uzmanlaşmış bir editörüm. Okuyucularıma bütçe dostu ve uygulanabilir yaşam tavsiyeleri sunuyorum.

Yorumlar (0)

Yorum Yaz