Node.js ve Socket.io ile Gerçek Zamanlı Uygulama Geliştirme Rehberi
Modern web uygulamalarında kullanıcı deneyimini en üst seviyeye çıkarmak için gerçek zamanlı (real-time) veri iletişimi kritik bir rol oynar. Bu makalede, Node.js ve Socket.io kütüphanesini kullanarak düşük gecikmeli, çift yönlü iletişim sistemlerinin nasıl kurulacağını, SQL veritabanı entegrasyonunu ve üretim ortamı için en iyi uygulama (best practices) yöntemlerini derinlemesine inceleyeceğiz.
Socket.io ve Geleneksel HTTP Arasındaki Farklar
Geleneksel HTTP protokolü "request-response" (istek-yanıt) modeline dayanır. İstemci bir istek gönderir ve sunucu yanıt verir. Ancak canlı sohbet, borsa takibi veya çok oyunculu oyunlar gibi uygulamalarda sunucunun istemciye veri itmesi (push) gerekir.
| Özellik | HTTP Protokolü | Socket.io (WebSocket) |
|---|---|---|
| İletişim Tipi | Tek Yönlü (Unidirectional) | Çift Yönlü (Bidirectional) |
| Gecikme (Latency) | Yüksek (Her istekte header gönderilir) | Düşük (Sürekli açık bağlantı) |
| Veri Transferi | İstemci tetikler | Sunucu veya İstemci tetikleyebilir |
Node.js ve Socket.io Kurulumu
Projenize başlamak için Node.js ortamınızın kurulu olduğundan emin olun. İlk adım olarak gerekli bağımlılıkları yükleyelim:
npm install express socket.io
npm install mysql2 // SQL entegrasyonu için
Temel Sunucu Yapılandırması
Aşağıdaki örnek, temel bir Express sunucusu üzerinde Socket.io'nun nasıl ayağa kaldırılacağını 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, {
cors: {
origin: "*", // Güvenlik için üretimde spesifik domain yazılmalıdır
}
});
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 3000 portunda çalışıyor.');
});
SQL Veritabanı ile Gerçek Zamanlı Veri Senkronizasyonu
Gerçek dünya senaryolarında, genellikle bir SQL veritabanına veri yazıldığında tüm bağlı istemcilerin güncellenmesi istenir. Örneğin, bir sipariş takip sisteminde sipariş durumu değiştiğinde kullanıcıya anlık bildirim gitmelidir.
Örnek: SQL'den Veri Çekme ve Yayınlama (Emit)
Veritabanında bir değişiklik olduğunda bunu dinleyen ve bağlı tüm istemcilere yayınlayan bir yapı kuralım:
const mysql = require('mysql2');
const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'app_db'
});
// Yeni mesaj geldiğinde veritabanına kaydet ve herkese yayınla
socket.on('new_message', (data) => {
const query = 'INSERT INTO messages (user_id, content) VALUES (?, ?)';
db.query(query, [data.userId, data.content], (err, result) => {
if (!err) {
// Tüm istemcilere (gönderen dahil) veriyi gönder
io.emit('receive_message', {
id: result.insertId,
content: data.content,
userId: data.userId
});
}
});
});
Socket.io Olay Yönetimi (Broadcasting ve Rooms)
Socket.io'da veriyi kimin alacağını kontrol etmek için farklı yöntemler bulunur:
- io.emit(): Bağlı olan herkese gönderir.
- socket.broadcast.emit(): Gönderen kişi hariç herkese gönderir.
- socket.to(room).emit(): Sadece belirli bir "odadaki" kullanıcılara gönderir.
Odalar (Rooms) Kullanımı
Özellikle özel mesajlaşma veya belirli bir gruba bildirim gönderme senaryolarında kullanılır:
// Kullanıcıyı belirli bir odaya dahil etme
socket.on('join_room', (roomName) => {
socket.join(roomName);
console.log(`${socket.id} adlı kullanıcı ${roomName} odasına katıldı.`);
});
// Sadece o odadakilere mesaj gönderme
socket.to('private_room').emit('private_notice', 'Bu sadece bu odaya özeldir.');
Güvenlik ve Performans İçin En İyi Uygulamalar (Best Practices)
1. Kimlik Doğrulama (Authentication)
Bağlantı kurulmadan önce JWT (JSON Web Token) kullanarak kimlik doğrulaması yapmak güvenliğin ilk adımıdır:
io.use((socket, next) => {
const token = socket.handshake.auth.token;
if (isValid(token)) {
next();
} else {
next(new Error("Yetkisiz erişim!"));
}
});
2. Ölçeklenebilirlik (Scalability)
Uygulamanız birden fazla sunucuda (Node.js cluster) çalışıyorsa, sunucular arası haberleşme için Redis Adapter kullanmalısınız. Aksi takdirde, Sunucu A'ya bağlı bir kullanıcı, Sunucu B'ye bağlı bir kullanıcıya mesaj gönderemez.
3. Hata Yönetimi
İstemci tarafında `connect_error` ve `reconnect_attempt` olaylarını dinleyerek kullanıcıya bağlantı durumu hakkında bilgi vermek, kullanıcı deneyimini iyileştirir.
Sonuç
Node.js ve Socket.io ikilisi, SQL veritabanlarıyla entegre edildiğinde son derece güçlü ve ölçeklenebilir gerçek zamanlı sistemler oluşturmanıza olanak tanır. Olay tabanlı mimariyi doğru kurgulamak, odaları (rooms) verimli kullanmak ve güvenlik katmanlarını (middleware) ihmal etmemek, profesyonel bir uygulamanın temel taşlarıdır. Daha fazla bilgi için resmi Socket.io dökümantasyonunu inceleyebilirsiniz.