Node.js İle Gerçek Zamanlı Sohbet Uygulaması Nasıl Yapılır?

Node.js İle Gerçek Zamanlı Sohbet Uygulaması Nasıl Yapılır?
Node.js İle Gerçek Zamanlı Sohbet Uygulaması Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce bilgisayarınızda Node.js'in en güncel LTS (Long Term Support) sürümünün yüklü olması gerekir. Terminalinize node -v yazarak sürüm kontrolü yapabilirsiniz. Ayrıca, paket yönetimi için npm veya yarn kullanacağız.

  • Node.js (v20 veya üzeri önerilir)
  • Temel JavaScript (ES6+ sözdizimi) bilgisi
  • Terminal kullanımı
  • Bir kod editörü (VS Code tavsiye edilir)

Proje klasörünüzü oluşturun ve gerekli bağımlılıkları yüklemek için aşağıdaki komutları terminalde çalıştırın:

mkdir chat-app
cd chat-app
npm init -y
npm install express socket.io

Burada express, web sunucumuzu ayağa kaldırmak için; socket.io ise istemci ve sunucu arasında çift yönlü, gerçek zamanlı iletişim kurmak için kullandığımız temel kütüphanelerdir.

Sunucu Tarafı Kurulumu ve Express Yapılandırması

Node.js sunucumuzu oluştururken Express'i HTTP sunucusu ile birleştirmemiz gerekir. Socket.io, doğrudan HTTP sunucusu üzerinde çalışarak WebSocket protokolü üzerinden veri alışverişi yapar.

server.js adında bir dosya oluşturun ve aşağıdaki kodları ekleyin:

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);

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

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

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

Bu kod bloğu, sunucuyu 3000 portunda başlatır ve herhangi bir istemci bağlandığında konsola bilgi verir. io.emit metodu, gelen mesajı tüm bağlı istemcilere yayınlamak (broadcast) için kullanılır.

İstemci Tarafı: HTML ve Socket.io Entegrasyonu

Şimdi kullanıcıların mesaj yazabileceği ve gelen mesajları görebileceği bir arayüz oluşturalım. index.html dosyasını oluşturun ve temel yapılandırmayı yapın.




    
    Gönder const socket = io(); const form = document.getElementById('form'); const input = document.getElementById('input'); form.addEventListener('submit', (e) => { e.preventDefault(); if (input.value) { socket.emit('chat message', input.value); input.value = ''; } }); socket.on('chat message', (msg) => { const item = document.createElement('li'); item.textContent = msg; document.getElementById('messages').appendChild(item); });

    İstemci tarafında socket.emit ile sunucuya veri gönderiyoruz, socket.on ile de sunucudan gelen mesajları dinleyerek DOM üzerinde güncelliyoruz.

    Gerçek Zamanlı İletişim Yöntemlerinin Karşılaştırılması

    Sohbet uygulamalarında kullanılan farklı yöntemlerin performans ve kullanım kolaylığı açısından karşılaştırması aşağıdadır:

    Yöntem Avantaj Dezavantaj
    WebSocket Çift yönlü, çok düşük gecikme Karmaşık bağlantı yönetimi
    Socket.io Otomatik tekrar bağlanma, kolay API Ekstra kütüphane bağımlılığı
    Long Polling Tüm tarayıcılarla uyumlu Yüksek sunucu yükü, yavaş

    Güvenlik Önlemleri ve Mesaj Filtreleme

    Gerçek zamanlı uygulamalarda en büyük risk XSS (Cross-Site Scripting) saldırılarıdır. Kullanıcıdan gelen veriyi doğrudan HTML içine basmak tehlikelidir. Mesajları ekrana yazdırırken textContent kullanmak, tarayıcının veriyi kod olarak değil, metin olarak işlemesini sağlar.

    Kritik Güvenlik Uyarısı: Üretim ortamında (production) kullanıcıdan gelen verileri mutlaka sunucu tarafında doğrulayın (sanitization). Asla ham HTML verisini istemciye geri göndermeyin.

    Ayrıca, kullanıcıların birbirine özel mesaj göndermesini sağlamak için socket.join metodunu kullanarak "odalar" (rooms) oluşturabilirsiniz. Bu, verinin sadece ilgili kullanıcılara gitmesini sağlar.

    Uygulamayı Test Etme ve Yayına Alma

    Uygulamanızı çalıştırmak için terminalde node server.js komutunu kullanın. Ardından tarayıcınızda http://localhost:3000 adresine gidin. İki farklı sekme açarak birinden mesaj gönderdiğinizde diğerinde anında belirdiğini göreceksiniz.

    Üretim ortamına geçerken, Node.js uygulamanızı PM2 gibi bir süreç yöneticisi ile çalıştırmanız ve sunucunuzun güvenliği için Helmet.js gibi kütüphanelerle HTTP başlıklarını (headers) koruma altına almanız önerilir.

    Yazılım geliştirme süreçlerinde kod güvenliği tamamen geliştiricinin sorumluluğundadır. Bu rehberdeki örnekler temel eğitim amaçlıdır; canlı bir projede mutlaka profesyonel güvenlik denetimlerinden geçirilmelidir.

    Sıkça Sorulan Sorular

    Socket.io kullanmadan WebSocket ile yapabilir miyim?

    Evet, Node.js içerisinde yer alan ws kütüphanesini kullanarak saf WebSocket protokolünü kullanabilirsiniz. Ancak Socket.io, bağlantı kesilmelerinde otomatik yeniden bağlanma ve odaya göre mesajlaşma gibi özellikleri hazır sunduğu için daha pratiktir.

    Mesajları veritabanına nasıl kaydederim?

    Sunucu tarafındaki socket.on('chat message', ...) bloğu içerisinde, mesajı broadcast etmeden önce MongoDB veya PostgreSQL gibi bir veritabanına INSERT sorgusu ile kaydedebilirsiniz.

    Aynı anda kaç kullanıcı destekler?

    Node.js'in olay döngüsü (event loop) yapısı sayesinde binlerce eşzamanlı bağlantıyı yönetebilirsiniz. Ancak bellek kullanımı ve işlemci gücü sunucunuzun kapasitesine bağlıdır.

    HTTPS kullanmam zorunlu mu?

    Gerçek zamanlı uygulamalarda veri güvenliği için HTTPS kullanımı artık bir standarttır. Üretim ortamında mutlaka geçerli bir SSL sertifikası kullanmalısınız.

    Mesajların gönderildiğini nasıl anlarım?

    Socket.io'nun "acknowledgement" (onay mekanizması) özelliğini kullanarak, mesaj sunucuya ulaştığında istemciye bir "gönderildi" bilgisi dönmesini sağlayabilirsiniz.

    Uygulamanın Ölçeklenebilirliğini Artırmak: Redis ve Pub/Sub

    Uygulamanız tek bir sunucuda mükemmel çalışsa da, kullanıcı sayısı arttığında yatay ölçeklendirme (horizontal scaling) yapmanız gerekecektir. Birden fazla Node.js sunucusu çalıştırdığınızda, bir sunucuya bağlı olan kullanıcı diğer sunucudaki kullanıcıya mesaj gönderemez. Bu durumu aşmak için Redis Adapter kullanmanız gerekir.

    Redis, sunucular arasında bir "mesaj aracısı" (message broker) görevi görerek olayların tüm sunuculara yayınlanmasını sağlar.

    // Sunucu tarafında Redis entegrasyonu
    const { createClient } = require('redis');
    const { createAdapter } = require('@socket.io/redis-adapter');
    
    const pubClient = createClient({ url: 'redis://localhost:6379' });
    const subClient = pubClient.duplicate();
    
    Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
      io.adapter(createAdapter(pubClient, subClient));
    });

    İleri Seviye Hata Ayıklama ve İzleme Teknikleri

    Gerçek zamanlı uygulamalarda bağlantı kopmaları ve senkronizasyon hataları kaçınılmazdır. Uygulamanızın sağlığını izlemek için aşağıdaki stratejileri uygulayabilirsiniz:

    • Socket.io Debug Modu: Geliştirme aşamasında tüm olay trafiğini görmek için ortam değişkenini kullanın: DEBUG=socket.io* node app.js.
    • Bağlantı Durumu İzleme: İstemci tarafında connect_error ve reconnect_attempt olaylarını dinleyerek kullanıcıya bağlantı durumu hakkında bilgi verin.
    // İstemci tarafı hata yönetimi
    socket.on("connect_error", (err) => {
      console.log(`Bağlantı hatası: ${err.message}`);
      // Kullanıcıya "Yeniden bağlanılıyor..." uyarısı göster
    });
    
    socket.on("reconnect", (attemptNumber) => {
      console.log(`Başarıyla yeniden bağlandı. Deneme sayısı: ${attemptNumber}`);
    });

    Performans Optimizasyonu İçin İpuçları

    Sohbet uygulamanızın kaynak tüketimini optimize etmek için şu yöntemleri göz önünde bulundurun:

    1. Payload Boyutunu Sınırlayın: Çok büyük mesajların veya dosyaların gönderilmesini engelleyin.
    2. Binary Veri Transferi: Resim veya dosya gönderimlerinde base64 yerine Buffer veya Blob kullanarak ağ trafiğini azaltın.
    3. Namespace Kullanımı: Farklı sohbet odalarını veya özelliklerini (örneğin: genel sohbet vs. özel mesajlaşma) io.of('/admin') gibi farklı namespace'lere ayırarak olay trafiğini izole edin.
    Profesyonel Not: Yüksek trafikli uygulamalarda, istemci tarafında mesajları "debounce" ederek (kullanıcı her tuşa bastığında değil, belirli aralıklarla) sunucuya göndermek, CPU yükünü ciddi oranda düşürecektir.

    Sonuç

    Node.js ile gerçek zamanlı sohbet uygulaması yapmak, hem olay tabanlı programlamayı anlamak hem de WebSocket teknolojisine hakim olmak için mükemmel bir başlangıçtır. Bu projeyi geliştirmek için bir sonraki adımınız, mesajları bir veritabanına kaydetmek ve kullanıcı kimlik doğrulaması (JWT - JSON Web Token) eklemek olmalıdır.

    Başarılı bir sohbet uygulaması için kullanıcı deneyimini iyileştirecek "yazıyor..." bilgisi veya "çevrimiçi/çevrimdışı" durum göstergeleri gibi özellikleri de projenize dahil edebilirsiniz. Kodunuzu her zaman modüler tutmayı ve hata yönetimi (error handling) mekanizmalarını ihmal etmemeyi unutmayın.

    Bu yazıya tepkinizi paylaşın:
    Mert Çelik

    Kendin yap (DIY) projeleri ve teknik tamirat rehberleri konusunda uzmanım. Denenmiş ve test edilmiş yöntemlerle okuyuculara güvenilir bilgiler sunuyorum.

    Yorumlar (0)

    Yorum Yaz