Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce sisteminizde Node.js (v20 veya üzeri sürüm önerilir) yüklü olmalıdır. Ayrıca paket yönetimi için npm veya pnpm kullanacağız. Proje dizinini oluşturup gerekli kütüphaneleri yükleyerek işe başlayalım.
mkdir canli-not-defteri
cd canli-defter
npm init -y
npm install express socket.io
Bu komutlar, projenin temel yapısını oluşturur ve Express (web sunucusu çatısı) ile Socket.io (WebSocket kütüphanesi) paketlerini projenize dahil eder. 2026 yılı standartlarında, modüler bir yapı kurmak için package.json dosyanıza "type": "module" satırını eklemeyi unutmayın.
Sunucu Tarafı Yapılandırması
Sunucu tarafında, Express ile bir HTTP sunucusu oluşturacak ve bu sunucuyu Socket.io ile sarmalayacağız. Bu sayede hem statik dosyalarımızı (HTML/JS) sunabilecek hem de WebSocket bağlantılarını dinleyebileceğiz.
import express from 'express';
import { createServer } from 'http';
import { Server } from 'socket.io';
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer);
app.use(express.static('public'));
io.on('connection', (socket) => {
console.log('Bir kullanıcı bağlandı:', socket.id);
socket.on('not-degisti', (yeniIcerik) => {
// Gelen veriyi diğer tüm kullanıcılara yayınla
socket.broadcast.emit('not-guncelle', yeniIcerik);
});
});
httpServer.listen(3000, () => {
console.log('Sunucu http://localhost:3000 adresinde çalışıyor.');
});
Burada socket.broadcast.emit metodu kritik öneme sahiptir. Bu metod, mesajı gönderen kullanıcı hariç, bağlı olan tüm diğer istemcilere veriyi iletir. Böylece döngüsel bir veri trafiği oluşmasını engellemiş oluruz.
İstemci Tarafı ve Arayüz Tasarımı
Kullanıcının not yazacağı arayüzü basit bir textarea elementi ile oluşturacağız. İstemci tarafında Socket.io istemci kütüphanesini kullanarak sunucuya bağlanacağız.
İstemci tarafı, sunucudan gelen not-guncelle olayını dinlemeli ve yerel textarea içeriğini güncellemelidir. Kullanıcı yazdığında ise not-degisti olayını sunucuya tetiklemelidir.
Gerçek Zamanlı Senkronizasyon Mantığı
Not defterinin senkronize çalışması için input olayını dinlememiz gerekir. Ancak, kullanıcının her tuş vuruşunda sunucuya veri göndermek performans sorunlarına yol açabilir. Bu noktada "debounce" (gecikmeli işlem) tekniği kullanmak en profesyonel yaklaşımdır.
// public/app.js
const socket = io();
const notAlani = document.getElementById('notAlani');
notAlani.addEventListener('input', (e) => {
const icerik = e.target.value;
socket.emit('not-degisti', icerik);
});
socket.on('not-guncelle', (yeniIcerik) => {
notAlani.value = yeniIcerik;
});
Bu kod bloğu, kullanıcı yazdığı anda sunucuya veriyi gönderir. Sunucu ise bu veriyi diğer istemcilere dağıtır. İstemci, güncellemeyi aldığında textarea değerini değiştirerek senkronizasyonu tamamlar.
Veri Güvenliği ve Optimizasyon
Gerçek zamanlı uygulamalarda en büyük risklerden biri Cross-Site Scripting (XSS) saldırılarıdır. Kullanıcıdan gelen veriyi doğrudan DOM'a yazmak tehlikelidir. Veriyi sunucu tarafında veya istemcide mutlaka temizlemelisiniz.
Kritik Güvenlik Uyarısı: Kullanıcı girişlerini asla doğrudan
innerHTMLiçine yerleştirmeyin. Her zamantextContentveyavalueözelliklerini kullanarak veriyi metin olarak işleyin. Üretim ortamında (production) Socket.io bağlantılarını mutlaka CORS politikaları ile sınırlandırın.
Aşağıdaki tablo, farklı senkronizasyon yöntemlerinin karşılaştırmasını sunmaktadır:
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Socket.io | Düşük gecikme, kolay kullanım | Sunucu kaynak tüketimi |
| Polling (HTTP) | Basit, her yerde çalışır | Yüksek gecikme, gereksiz trafik |
| WebRTC | Sunucusuz (P2P), hızlı | Bağlantı kurma zorluğu |
Yaygın Hatalar ve Debug İpuçları
Geliştirme sırasında en sık karşılaşılan sorun bağlantı kopmalarıdır. Socket.io, otomatik yeniden bağlanma (auto-reconnect) özelliğine sahiptir ancak bazen sunucu tarafındaki oturumlar (sessions) çakışabilir.
- Bağlantı Hatası: Tarayıcı konsolunda 404 hatası alıyorsanız,
/socket.io/socket.io.jsdosyasının doğru yüklendiğinden emin olun. - Senkronizasyon Döngüsü: Eğer bir kullanıcı yazdığında kendi ekranındaki yazı da sürekli yer değiştiriyorsa,
inputolayını tetikleyen fonksiyon ile gelen veriyi işleyen fonksiyonun çakışmadığından emin olun. - Performans: Çok fazla kullanıcı olduğunda sunucu yükünü azaltmak için "Room" (Oda) yapısını kullanarak notları gruplandırın.
Sıkça Sorulan Sorular
Socket.io ile geleneksel HTTP arasındaki temel fark nedir?
HTTP, istemci istekte bulunmadan sunucunun veri gönderemediği tek yönlü bir protokoldür. Socket.io ise WebSocket protokolünü kullanarak sunucu ve istemci arasında sürekli açık, çift yönlü bir iletişim kanalı kurar.
Bu not defterini veritabanına nasıl bağlarım?
Sunucu tarafındaki socket.on('not-degisti') bloğu içinde veritabanı (MongoDB veya PostgreSQL gibi) işlemleri yaparak notu kalıcı hale getirebilirsiniz. Her bağlantıda veritabanından son notu çekip istemciye göndermelisiniz.
Aynı anda kaç kişi bağlanabilir?
Socket.io, tek bir sunucuda binlerce eşzamanlı bağlantıyı yönetebilir. Ancak ölçeklendirme için Redis gibi bir "adapter" kullanarak birden fazla sunucu arasında mesajlaşmayı senkronize etmeniz gerekir.
Üretim ortamında (Production) nelere dikkat etmeliyim?
HTTPS protokolünü mutlaka kullanmalı, Socket.io için "polling" yerine sadece "websocket" taşıma yöntemini zorlamalı ve sunucu kaynaklarını izlemelisiniz.
Not defterine kullanıcı isimlerini nasıl eklerim?
Socket.io'nun socket.handshake.query veya socket.data özelliklerini kullanarak kullanıcı bilgilerini bağlantı sırasında tutabilir ve mesajlara kimlik bilgisi ekleyebilirsiniz.
İleri Seviye Optimizasyon: Socket.io ile "Debounce" ve "Throttle" Kullanımı
Canlı not defteri uygulamanızda her tuş vuruşunda veriyi sunucuya göndermek, özellikle yüksek trafikli uygulamalarda ciddi bir ağ yükü ve sunucu darboğazı yaratır. Bu sorunu çözmek için Debounce (gecikmeli tetikleme) tekniğini kullanmak en iyi uygulamadır. Bu teknik, kullanıcı yazmayı bıraktıktan belirli bir süre sonra verinin gönderilmesini sağlar.
Aşağıdaki örnekte, lodash kütüphanesini kullanarak veya basit bir zamanlayıcı ile bu işlemi nasıl optimize edeceğinizi görebilirsiniz:
// İstemci tarafında debounce kullanımı
let timeout = null;
const textarea = document.getElementById('note-area');
textarea.addEventListener('input', (e) => {
clearTimeout(timeout);
timeout = setTimeout(() => {
socket.emit('edit-note', e.target.value);
}, 300); // Kullanıcı 300ms boyunca yazmayı durdurduğunda gönder
});
Uygulamayı Ölçeklendirme: Redis ile Çoklu Sunucu Desteği
Uygulamanız büyüdüğünde, tek bir Node.js sunucusu yeterli olmayabilir. Birden fazla sunucu (horizontal scaling) kullandığınızda, bir sunucuya bağlanan kullanıcının notu, diğer sunucuya bağlı olan kullanıcıya iletilmeyebilir. Bu sorunu aşmak için Socket.io Redis Adapter kullanmanız gerekir.
Bu yapı, tüm sunucuların bir Redis veritabanı üzerinden haberleşmesini sağlayarak mesajların senkronize kalmasına olanak tanır. Kurulum için şu adımları izleyebilirsiniz:
@socket.io/redis-adapterveredispaketlerini yükleyin.- Sunucu tarafında adaptörü yapılandırarak Socket.io örneğine bağlayın.
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));
});
Canlı Not Defteri İçin Otomatik Test Stratejileri
Gerçek zamanlı uygulamalarda test süreci, geleneksel HTTP isteklerinden daha karmaşıktır. Jest ve socket.io-client kullanarak, birden fazla istemcinin aynı anda not defterine bağlanıp veri gönderdiğini simüle eden entegrasyon testleri yazmalısınız.
İpucu: Testlerinizdesocket.io-clientkullanarak sanal istemciler oluşturun vedone()fonksiyonu ile mesajın sunucuya ulaştığını ve diğer istemcilere yayınlandığını doğrulayın.
Örnek bir test senaryosu yapısı şu şekildedir:
const io = require("socket.io-client");
test("not içeriği diğer kullanıcılara başarıyla iletilmeli", (done) => {
const client1 = io("http://localhost:3000");
const client2 = io("http://localhost:3000");
client2.on("update-note", (data) => {
expect(data).toBe("Merhaba Dünya");
client1.disconnect();
client2.disconnect();
done();
});
client1.emit("edit-note", "Merhaba Dünya");
});
Sonuç
Node.js ve Socket.io kullanarak paylaşımlı bir canlı not defteri oluşturmak, modern web geliştirme süreçlerinin temel taşlarını öğrenmenizi sağlar. Bu projeyi geliştirmek için bir sonraki adımda notları veritabanına kaydetmeyi, kullanıcılar için oda (room) sistemi kurmayı veya metin editörüne zengin metin (bold, italic) desteği eklemeyi deneyebilirsiniz.
Yasal Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Yazılımlarınızın güvenliği, veri gizliliği ve sunucu yönetimi tamamen geliştiricinin sorumluluğundadır. Üretim ortamına geçmeden önce güvenlik denetimlerini (security audit) mutlaka yapınız.


Yorumlar (0)
Yorum Yaz