Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce bilgisayarınızda Node.js çalışma ortamının kurulu olması gerekmektedir. 2026 yılı standartlarında en az v20.x sürümünü kullanmanızı öneririm. Proje dizinini oluşturmak ve gerekli paketleri yüklemek için terminalinizi açın ve aşağıdaki adımları izleyin.
Öncelikle proje klasörünü oluşturup bağımlılıkları tanımlayalım:
mkdir beyaz-tahta-app
cd beyaz-tahta-app
npm init -y
npm install express socket.io
Bu komutlar, projemizin temelini oluşturan Express (web sunucusu çatısı) ve Socket.io (WebSocket yönetimi) kütüphanelerini projenize dahil edecektir. Geliştirme sürecinde kodunuzu daha hızlı test etmek için nodemon paketini de npm install --save-dev nodemon komutuyla kurabilirsiniz.
Sunucu Tarafı Kurulumu ve Socket.io Yapılandırması
Sunucu tarafında, HTTP sunucumuzu ayağa kaldırmalı ve Socket.io'yu bu sunucuya bağlamalıyız. Socket.io, HTTP sunucusu üzerinden gelen bağlantıları dinleyerek WebSocket protokolüne yükseltme (upgrade) işlemini otomatik gerçekleştirir.
server.js dosyasını oluşturun ve şu 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.use(express.static('public'));
io.on('connection', (socket) => {
console.log('Yeni bir kullanıcı bağlandı: ' + socket.id);
socket.on('cizim', (data) => {
socket.broadcast.emit('cizim', data);
});
});
server.listen(3000, () => {
console.log('Sunucu http://localhost:3000 adresinde çalışıyor.');
});
Burada socket.broadcast.emit metodu kritiktir; çünkü bu metod, çizim yapan kişi hariç ağdaki tüm bağlı diğer istemcilere veriyi iletir. Böylece çizimi yapan kişinin ekranında verinin tekrar işlenip gecikme yaratmasını engellemiş oluruz.
İstemci Tarafı: HTML5 Canvas ile Çizim Mantığı
İstemci tarafında, kullanıcının fare hareketlerini yakalamak ve bu verileri koordinat düzleminde çizime dönüştürmek için HTML5 canvas elementini kullanacağız. public/index.html dosyasını oluşturun.
Bu yapı, tarayıcıda 800x600 boyutlarında bir çalışma alanı oluşturur. /socket.io/socket.io.js yolu, Socket.io sunucusu tarafından otomatik olarak istemciye servis edilen istemci kütüphanesidir.
Çizim Verilerinin İletimi ve Senkronizasyon
Şimdi public/main.js dosyasında fare hareketlerini yakalayacak ve veriyi sunucuya gönderecek mantığı kuralım. Fare sürüklendiğinde koordinatları alıp Socket.io ile yayınlayacağız.
const socket = io();
const canvas = document.getElementById('tahta');
const ctx = canvas.getContext('2d');
let ciziyor = false;
canvas.addEventListener('mousedown', () => ciziyor = true);
canvas.addEventListener('mouseup', () => ciziyor = false);
canvas.addEventListener('mousemove', (e) => {
if (!ciziyor) return;
const veri = { x: e.clientX, y: e.clientY };
ctx.fillRect(veri.x, veri.y, 2, 2);
socket.emit('cizim', veri);
});
socket.on('cizim', (data) => {
ctx.fillRect(data.x, data.y, 2, 2);
});
Bu kod bloğu, yerel çizim ile ağ üzerinden gelen çizimi birleştirir. Kullanıcı fareyi hareket ettirdiğinde socket.emit ile sunucuya veri gönderilir, sunucu da bunu diğerlerine dağıtır.
Performans ve Güvenlik Karşılaştırması
Gerçek zamanlı uygulamalarda veri iletim yöntemlerini anlamak için aşağıdaki tabloyu inceleyebilirsiniz:
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| WebSocket (Socket.io) | Düşük gecikme, tam çift yönlü | Sunucu kaynak tüketimi yüksektir |
| Polling (Düzenli İstek) | Basit uygulama | Yüksek gecikme, gereksiz trafik |
| Server-Sent Events | Tek yönlü hızlı veri akışı | İstemciden sunucuya veri gönderemez |
Kritik Uyarı: Üretim ortamında (production) Socket.io kullanırken, her zaman "CORS" (Cross-Origin Resource Sharing) ayarlarını yapılandırın. Aksi takdirde, uygulamanız kötü niyetli domainlerden gelen WebSocket bağlantılarına açık hale gelebilir. Ayrıca, kullanıcıdan gelen verileri asla doğrudan DOM'a enjekte etmeyin; XSS saldırılarına karşı her zaman temizleyin.
Sıkça Sorulan Sorular
Socket.io yerine neden doğrudan WebSocket kullanmıyoruz?
Socket.io, WebSocket protokolünün üzerine eklenmiş bir katmandır. Bağlantı koptuğunda otomatik yeniden bağlanma, fallback mekanizmaları (WebSocket desteklenmiyorsa HTTP polling'e dönme) ve oda (room) yönetimi gibi özellikleri kutudan çıktığı gibi sunar.
Çizim verileri çok büyük olursa ne yapmalıyım?
Çizim verilerini her piksel için göndermek yerine, "başlangıç" ve "bitiş" noktalarını içeren vektörel veriler göndererek veri paket boyutunu ciddi oranda düşürebilirsiniz.
Uygulamayı birden fazla sunucuda nasıl ölçeklerim?
Socket.io, Redis Adapter kullanarak farklı sunucular arasında mesajlaşmayı senkronize edebilir. Bu, uygulamanızın binlerce kullanıcıya ölçeklenmesini sağlar.
Gecikme (Latency) sorunlarını nasıl çözerim?
İstemci tarafında "throttling" veya "debouncing" tekniklerini kullanarak, saniyede gönderilen paket sayısını sınırlandırabilirsiniz.
Veritabanı bağlantısı eklemeli miyim?
Çizimlerin kalıcı olmasını istiyorsanız, çizim verilerini (koordinat dizilerini) MongoDB gibi bir doküman tabanlı veritabanında saklayıp, yeni bağlanan kullanıcılara ilk yüklemede gönderebilirsiniz.
Güvenlik Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Uygulamanızı canlıya almadan önce giriş doğrulama, hız sınırlama (rate limiting) ve veri sanitasyonu gibi güvenlik katmanlarını mutlaka ekleyin. Yazılım güvenliği, sürekli güncellenen bir süreçtir.
Uygulama İçin İleri Seviye Optimizasyon Teknikleri
Paylaşımlı beyaz tahta uygulamanız kullanıcı sayınız arttıkça bant genişliği ve işlemci yükü açısından zorlanmaya başlayacaktır. Bu noktada, ham veri akışını optimize etmek uygulamanızın akıcılığını korumak için kritik öneme sahiptir.
Veri Sıkıştırma ve Paketleme (Throttling)
Her fare hareketinde bir socket mesajı göndermek, sunucuyu gereksiz yere meşgul eder. Bunun yerine, çizim verilerini belirli bir aralıkla (örneğin 16ms - 60 FPS) "throttle" ederek göndermek performansı ciddi oranda artırır. Ayrıca, JSON verilerini küçültmek için gereksiz alanları kaldırabilirsiniz.
// İstemci tarafında çizim verisini optimize etme
let isDrawing = false;
let lastEmit = 0;
canvas.addEventListener('mousemove', (e) => {
if (!isDrawing) return;
const now = Date.now();
// 16ms'de bir gönderim yap (yaklaşık 60 FPS)
if (now - lastEmit > 16) {
socket.emit('drawing', {
x0: lastX, y0: lastY,
x1: e.clientX, y1: e.clientY,
color: currentColor
});
lastEmit = now;
}
});
Binary Veri Aktarımı ile Yükü Hafifletme
JSON formatı metin tabanlı olduğu için büyük miktarda koordinat verisinde şişkinlik yaratır. Verileri ArrayBuffer veya TypedArray kullanarak binary formatta göndermek, ağ üzerinden geçen veri boyutunu %70'e kadar azaltabilir.
Uygulamanın Canlı Ortama (Deployment) Hazırlanması
Geliştirme ortamındaki basit node server.js komutu, canlı ortamdaki trafik yükünü karşılamaya yetmeyecektir. Uygulamanızı yayına alırken dikkat etmeniz gereken temel noktalar şunlardır:
- Process Manager Kullanımı: Uygulamanızın çökmesi durumunda otomatik yeniden başlatılması için
PM2kullanın. - Reverse Proxy: Socket.io bağlantılarını doğru yönetmek ve SSL/TLS (HTTPS) desteği sağlamak için Nginx'i bir reverse proxy olarak yapılandırın.
- Sticky Sessions: Birden fazla sunucu (load balancer) kullanıyorsanız, Socket.io'nun el sıkışma (handshake) aşamasında aynı sunucuya yönlendirme yapması için "sticky sessions" özelliğini aktif edin.
# PM2 ile uygulamayı başlatma
pm2 start server.js --name "whiteboard-app"
# Uygulama durumunu izleme
pm2 monit
Nginx Yapılandırması İpucu
WebSocket bağlantılarının kesilmemesi için Nginx konfigürasyonunuzda Upgrade ve Connection başlıklarını mutlaka tanımlayın:
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;
}
Not: Canlı ortamda Socket.io kullanırken, istemcilerin bağlantı koptuğunda otomatik olarak yeniden bağlanma (reconnection) stratejilerini test etmeyi unutmayın. Sunucu tarafındapingTimeoutvepingIntervaldeğerlerini ağ koşullarınıza göre optimize etmek, "hayalet" bağlantıların önüne geçecektir.
Sonuç
Node.js ve Socket.io kullanarak paylaşımlı bir beyaz tahta uygulaması geliştirmek, gerçek zamanlı sistemlerin temellerini öğrenmek için mükemmel bir projedir. Bu uygulamayı daha ileriye taşımak için bir sonraki adımda, kullanıcılara renk seçimi, fırça boyutu ayarı veya çizimleri temizleme gibi özellikler ekleyebilir, hatta MongoDB kullanarak çizimlerin kaydedilip daha sonra tekrar yüklenebilmesini sağlayabilirsiniz. Başarılar dilerim.


Yorumlar (0)
Yorum Yaz