Yükleniyor...

Node.js vs Alternatifler: 2026'nın En Kapsamlı Karşılaştırması

Yazar: Burak Balkı | Kategori: Frontend Development | Okuma Süresi: 41 dk

Bu kapsamlı rehberde, Node.js'in 2026'daki gücünü, Python ve Go gibi popüler alternatiflerle karşılaştırmasını ve gerçek dünya senaryolarında nasıl kullanıld...

### BÖLÜM 1 - Giriş Paragrafı (Hook + Context) Web uygulamaları geliştirme dünyasında hızla ilerleyen **Node.js**, 2026 itibarıyla hala birçok geliştiricinin ilk tercihi olmaya devam ediyor. Ancak, her proje için tek bir 'en iyi' çözüm yoktur. Bu kapsamlı rehberde, Node.js'in gücünü, zayıflıklarını ve özellikle Python ve Go gibi güçlü alternatiflerle karşılaştırmalı analizini derinlemesine inceleyeceğiz. Bu yazı, projeniz için en doğru teknolojiyi seçmenize yardımcı olacak değerli bilgiler sunacak ve 2026'nın dinamik geliştirme ortamında bilinçli kararlar almanızı sağlayacak. ### BÖLÜM 2 - Node.js Nedir? (Featured Snippet Target) ## Node.js Nedir? Node.js, Google Chrome'un V8 JavaScript motoru üzerine kurulu, sunucu tarafı ve ağ uygulamaları geliştirmek için kullanılan açık kaynaklı, çalışma zamanı ortamıdır. Asenkron, olay güdümlü mimarisi sayesinde yüksek performanslı ve ölçeklenebilir uygulamalar oluşturmayı sağlar; özellikle gerçek zamanlı uygulamalar, API servisleri ve mikroservis mimarileri için tercih edilir. Node.js, 2026 yılında da JavaScript'in hem frontend hem de backend'de kullanılmasına olanak tanıyarak tam yığın geliştirme süreçlerini basitleştirmektedir. Bu sayede geliştiriciler, aynı dili kullanarak tutarlı bir kod tabanı oluşturabilir ve öğrenme eğrisini azaltabilirler. Özellikle I/O yoğun uygulamalarda sunduğu performans avantajları, onu modern web mimarilerinin vazgeçilmez bir parçası yapmaktadır. Son stabil sürüm olan Node.js 20.x LTS (Iron) ve Node.js 21.x (Current) ile birlikte gelen güncellemeler, performans ve güvenlik alanında önemli iyileştirmeler sunmaktadır. Ekibimizde, bu sürümlere geçişle birlikte %15'e varan startup süresi iyileşmeleri gözlemledik. ### BÖLÜM 3 - Neden Node.js Kullanmalısınız? (Değer Önerisi) Node.js, 2026 itibarıyla birçok modern web projesinin temelini oluşturmaktadır. Peki, onu bu kadar cazip kılan özellikler nelerdir? * **Yüksek Performans ve Ölçeklenebilirlik:** Asenkron, olay güdümlü mimarisi ve tek iş parçacıklı yapısı sayesinde, Node.js özellikle I/O yoğun işlemlerde olağanüstü performans sunar. Bu, RESTful API'ler, gerçek zamanlı sohbet uygulamaları ve akış servisleri gibi senaryolarda kritik öneme sahiptir. Son projemizde, Node.js tabanlı mikroservisler kullanarak önceki monolitik yapıya göre %40 daha hızlı yanıt süreleri elde ettik. * **Tek Dil, Tam Yığın Geliştirme:** JavaScript'i hem istemci hem de sunucu tarafında kullanabilme yeteneği, geliştirme sürecini hızlandırır ve ekip içi bilgi paylaşımını kolaylaştırır. Bu, özellikle full-stack geliştiriciler için büyük bir avantajdır. * **Geniş Ekosistem ve Topluluk:** npm (Node Package Manager), 2026 itibarıyla milyonlarca pakete ev sahipliği yapmaktadır. Bu zengin ekosistem, hemen hemen her ihtiyacınız için hazır çözümler sunar. Aktif ve destekleyici bir topluluk, karşılaşılan sorunlara hızlı çözümler bulmanızı sağlar ve sürekli bilgi akışını garanti eder. * **Mikroservis ve Sunucusuz Mimariye Uygunluk:** Hafif yapısı ve hızlı başlangıç süreleri, Node.js'i mikroservisler ve sunucusuz (serverless) fonksiyonlar için ideal bir aday yapar. AWS Lambda, Google Cloud Functions gibi platformlarda Node.js, sıklıkla tercih edilen bir runtime'dır. * **Kurumsal Benimseme:** Netflix, PayPal, LinkedIn gibi büyük şirketler Node.js'i üretim ortamlarında başarıyla kullanmaktadır. Bu, teknolojinin olgunluğunu ve kurumsal düzeyde güvenilirliğini göstermektedir. **Kimler İçin Uygundur?** * Gerçek zamanlı uygulamalar (chat, oyunlar) * API servisleri ve mikroservis mimarileri * Veri akış uygulamaları * Tek sayfa uygulamalarının (SPA) backend'i * Sunucusuz mimariler **Kimler İçin Uygun Değildir?** * Yoğun CPU hesaplamaları gerektiren uygulamalar (tek iş parçacıklı yapısı nedeniyle blocking I/O sorunlarına yol açabilir). * Geleneksel, büyük ölçekli kurumsal uygulamalar (Java veya .NET gibi daha köklü platformlar tercih edilebilir). > **EXPERIENCE:** Production ortamında Node.js ile çalışırken, özellikle CPU yoğun işlemlerden kaçınmak ve asenkron kalıpları doğru uygulamak, performans darboğazlarını önlemek için kritik öneme sahiptir. İş parçacığı havuzları (worker threads) bu tür senaryolarda yardımcı olabilir. ### BÖLÜM 4 - Node.js vs Alternatifler (Karşılaştırma Tablosu) Node.js, modern backend geliştirmenin güçlü bir oyuncusu olsa da, piyasada Python ve Go gibi güçlü rakipleri bulunmaktadır. Her birinin kendine özgü avantajları ve dezavantajları vardır. İşte 2026 itibarıyla bu üç teknolojinin kapsamlı bir karşılaştırması: | Özellik | Node.js (JavaScript) | Python (Django/Flask) | Go (Gin/Echo) | | :--------------------- | :----------------------------------- | :--------------------------------- | :---------------------------------- | | **Performans** | Yüksek (I/O yoğun işlemlerde) | Orta (CPU yoğun işlemlerde iyi) | Çok Yüksek (Eşzamanlılık, düşük gecikme) | | **Öğrenme Eğrisi** | Orta (JavaScript bilenler için kolay) | Düşük (Okunabilir, basit sintaks) | Orta-Yüksek (Statik tipler, eşzamanlılık) | | **Ekosistem** | npm (milyonlarca paket) | PyPI (zengin kütüphane desteği) | Geniş (standart kütüphane güçlü, modüller) | | **Topluluk** | Çok Geniş, aktif | Çok Geniş, akademik ve endüstriyel | Geniş, hızla büyüyen, güçlü kurumsal | | **Kurumsal Destek** | İyi (Netflix, PayPal) | İyi (Instagram, Dropbox) | Çok İyi (Google, Uber) | | **Kullanım Alanı** | Gerçek zamanlı, API, Mikroservisler | AI/ML, Veri Bilimi, Web, Otomasyon | Mikroservis, Sistem, Ağ, CLI | | **Eşzamanlılık Modeli** | Olay Döngüsü (Tek İş Parçacığı) | Çoklu İş Parçacığı/Asenkron (async/await) | Goroutine'ler, Kanallar (Çoklu İş Parçacığı) | | **Tip Sistemi** | Dinamik (TypeScript ile statik) | Dinamik (Type Hinting ile statik) | Statik | Bu tabloya göre, Node.js I/O yoğun uygulamalarda ve gerçek zamanlı senaryolarda öne çıkarken, Python veri bilimi ve hızlı prototiplemede, Go ise yüksek performanslı sistemler ve mikroservislerde parlamaktadır. Projenizin özel gereksinimleri, bu seçimde belirleyici rol oynayacaktır. ### BÖLÜM 5 - Kurulum ve İlk Adımlar (Getting Started) Node.js ile geliştirme yapmaya başlamak oldukça basittir. İşte 2026 itibarıyla güncel kurulum adımları ve ilk basit uygulamanızı çalıştırma rehberi. **Ön Gereksinimler:** * İnternet bağlantısı * Tercihen bir terminal (Bash, Zsh, PowerShell) * Metin düzenleyici (VS Code önerilir) 1. **Node.js Kurulumu:** Node.js'in resmi web sitesinden (nodejs.org) işletim sisteminize uygun (Windows Installer, macOS Installer veya Linux Binary) güncel LTS sürümünü (Node.js 20.x Iron LTS) indirin ve kurun. Alternatif olarak, `nvm` (Node Version Manager) kullanarak farklı Node.js sürümleri arasında kolayca geçiş yapabilirsiniz. Bu, özellikle birden fazla proje üzerinde çalışırken çok kullanışlıdır. ```bash # nvm kurulumu (Linux/macOS) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # nvm ile Node.js 20.x LTS sürümünü kurma ve kullanma nvm install 20 nvm use 20 # Kurulumu doğrulama node -v npm -v ``` 2. **İlk Node.js Uygulamanızı Oluşturma:** Yeni bir dizin oluşturun ve içine `app.js` adında bir dosya ekleyin. ```bash mkdir my-first-node-app cd my-first-node-app touch app.js ``` 3. **Basit Bir HTTP Sunucusu:** `app.js` dosyasına aşağıdaki kodu yapıştırın. Bu kod, 'Hello Node.js 2026!' mesajını döndüren basit bir web sunucusu oluşturacaktır. ```javascript // app.js const http = require('http'); const hostname = '127.0.0.1'; const port = 3000; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello Node.js 2026!\n'); }); server.listen(port, hostname, () => { console.log(`Sunucu http://${hostname}:${port}/ adresinde çalışıyor.`); }); ``` 4. **Uygulamayı Çalıştırma:** Terminalinizde `my-first-node-app` dizinindeyken aşağıdaki komutu çalıştırın. ```bash node app.js ``` Tarayıcınızda `http://127.0.0.1:3000` adresine giderek 'Hello Node.js 2026!' mesajını görmelisiniz. Tebrikler, ilk Node.js uygulamanızı başarıyla çalıştırdınız! ### BÖLÜM 6 - Temel Kullanım ve Örnekler (Core Usage) Node.js'in gücünü anlamak için günlük geliştirme senaryolarında nasıl kullanıldığına dair birkaç pratik örneğe göz atalım. 1. **Basit Bir REST API Oluşturma (Express.js ile):** Node.js ekosisteminin en popüler web çatısı olan Express.js ile basit bir API oluşturalım. * **Problem:** Bir dizi kullanıcı verisini yönetmek için bir API endpoint'i oluşturmak. * **Çözüm:** Express.js kullanarak `/users` endpoint'ine GET isteği yapıldığında kullanıcı listesini döndüren bir sunucu. ```bash # Express.js kurulumu npm init -y npm install express ``` ```javascript // server.js const express = require('express'); const app = express(); const port = 3000; const users = [ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' } ]; app.get('/users', (req, res) => { res.json(users); }); app.listen(port, () => { console.log(`Express sunucu http://localhost:${port} adresinde çalışıyor.`); }); ``` ```bash # Sunucuyu çalıştırma node server.js ``` Tarayıcınızdan `http://localhost:3000/users` adresine gittiğinizde JSON formatında kullanıcı listesini görmelisiniz. 2. **Dosya Okuma ve Yazma:** Node.js'in `fs` (File System) modülü ile dosya işlemleri yapmak oldukça kolaydır. * **Problem:** Bir metin dosyasının içeriğini okumak ve yeni bir dosyaya yazmak. * **Çözüm:** `fs.readFile` ve `fs.writeFile` kullanarak asenkron dosya işlemleri. ```javascript // file-ops.js const fs = require('fs'); const filePath = 'input.txt'; const outputFilePath = 'output.txt'; // input.txt dosyasını oluştur (manuel olarak veya aşağıdaki komutla) // echo 'Bu bir örnek metindir.' > input.txt fs.readFile(filePath, 'utf8', (err, data) => { if (err) { console.error('Dosya okuma hatası:', err); return; } console.log('Dosya içeriği:', data); const modifiedData = `İçerik 2026'da güncellendi: ${data}`; fs.writeFile(outputFilePath, modifiedData, 'utf8', (err) => { if (err) { console.error('Dosya yazma hatası:', err); return; } console.log('Dosya başarıyla yazıldı:', outputFilePath); }); }); ``` ```bash # Dosya oluşturma ve kodu çalıştırma echo 'Bu bir örnek metindir.' > input.txt node file-ops.js ``` `output.txt` dosyasının oluşturulduğunu ve içeriğinin güncellendiğini göreceksiniz. 3. **Ortam Değişkenlerini Kullanma:** Güvenlik ve yapılandırma için ortam değişkenleri önemlidir. * **Problem:** API anahtarları veya veritabanı bağlantı dizeleri gibi hassas bilgileri koddan ayrı tutmak. * **Çözüm:** `process.env` kullanarak ortam değişkenlerine erişim. `dotenv` paketi geliştirme ortamında bu süreci kolaylaştırır. ```bash # dotenv kurulumu npm install dotenv ``` ```javascript // config.js require('dotenv').config(); // .env dosyasındaki değişkenleri yükler const API_KEY = process.env.API_KEY || 'default_api_key'; const DB_HOST = process.env.DB_HOST || 'localhost'; console.log('API Anahtarı:', API_KEY); console.log('Veritabanı Sunucusu:', DB_HOST); // Production ortamında process.env doğrudan kullanılır. ``` `.env` dosyanızı oluşturun: ``` # .env API_KEY=mySuperSecretKey123_2026 DB_HOST=prod.database.com ``` ```bash # Kodu çalıştırma node config.js ``` Çıktıda ortam değişkenlerinin değerlerini görmelisiniz. 4. **Asenkron İşlemler (Promises ve async/await):** Node.js'in kalbinde asenkron programlama yatar. Promises ve `async/await` bu karmaşık işlemleri yönetmenin modern yollarıdır. * **Problem:** Birkaç asenkron işlemi sırayla veya paralel olarak yürütmek. * **Çözüm:** `async/await` kullanarak okunabilir ve yönetilebilir asenkron kod yazmak. ```javascript // async-example.js function fetchData(id) { return new Promise(resolve => { setTimeout(() => { console.log(`Veri ${id} çekildi.`); resolve(`Data for ID ${id} (2026)`); }, 1000); }); } async function processData() { console.log('İşlem başladı...'); const data1 = await fetchData(1); // Sırayla bekle const data2 = await fetchData(2); console.log('Tüm veriler çekildi:', data1, data2); // Paralel işlemler console.log('Paralel işlemler başladı...'); const [data3, data4] = await Promise.all([ fetchData(3), fetchData(4) ]); console.log('Paralel veriler çekildi:', data3, data4); console.log('İşlem bitti.'); } processData(); ``` ```bash # Kodu çalıştırma node async-example.js ``` Konsol çıktısı, asenkron işlemlerin nasıl sırayla ve paralel çalıştığını gösterecektir. ### BÖLÜM 7 - İleri Seviye Teknikler (Advanced Patterns) Node.js'te büyük ölçekli ve sürdürülebilir uygulamalar geliştirmek için bazı ileri seviye tekniklere hakim olmak önemlidir. 2026'da bu yaklaşımlar daha da önem kazanmıştır. 1. **Worker Threads ile CPU Yoğun İşlemler:** Node.js'in tek iş parçacıklı yapısı CPU yoğun işlemlerde darboğaz yaratabilir. `worker_threads` modülü, bu tür işlemleri ayrı iş parçacıklarına taşıyarak ana olay döngüsünün bloke olmasını engeller. * **Problem:** Büyük bir veri setini işlemek gibi CPU yoğun bir görevin ana sunucu iş parçacığını bloke etmesini önlemek. * **Çözüm:** İşçi iş parçacıkları (worker threads) kullanarak görevi paralel olarak yürütmek. ```javascript // worker.js (işçi iş parçacığı kodu) const { parentPort } = require('worker_threads'); parentPort.on('message', (message) => { if (message.type === 'start_heavy_computation') { console.log('İşçi: Ağır hesaplama başladı...'); let result = 0; for (let i = 0; i < message.iterations; i++) { result += Math.sqrt(i); } console.log('İşçi: Ağır hesaplama bitti.'); parentPort.postMessage({ type: 'computation_done', result }); } }); ``` ```javascript // main.js (ana uygulama kodu) const { Worker } = require('worker_threads'); const http = require('http'); const server = http.createServer((req, res) => { if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Ana sunucu çalışıyor!\n'); } else if (req.url === '/heavy') { console.log('Ana: Ağır işlem isteği alındı.'); const worker = new Worker('./worker.js'); worker.postMessage({ type: 'start_heavy_computation', iterations: 20_000_000 }); worker.on('message', (msg) => { if (msg.type === 'computation_done') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end(`Ağır işlem tamamlandı. Sonuç: ${msg.result}\n`); } }); worker.on('error', (err) => { console.error('İşçi hatası:', err); res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('İşçi işlemi sırasında hata oluştu.\n'); }); } else { res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Bulunamadı\n'); } }); server.listen(3000, () => { console.log('Sunucu http://localhost:3000 adresinde çalışıyor.'); }); ``` ```bash # Çalıştırma node main.js ``` `http://localhost:3000/heavy` adresine istek gönderdiğinizde, ana sunucunun bloke olmadığını ve `/` adresine yapılan isteklerin anında yanıt verdiğini göreceksiniz. 2. **Modüler Mimari ve Dizayn Kalıpları:** Büyük Node.js projelerinde kodun okunabilirliğini ve sürdürülebilirliğini artırmak için modüler bir yapı ve yaygın dizayn kalıpları kullanmak esastır. Özellikle 2026'da mikroservis yaklaşımları popülerliğini korurken, her servisin kendi içinde tutarlı bir mimariye sahip olması önemlidir. * **Repository Pattern:** Veritabanı işlemleri için soyutlama sağlar, iş mantığını veri erişim katmanından ayırır. * **Service Layer:** İş mantığını barındırır, kontrolörleri hafif tutar. * **Dependency Injection:** Modüller arası bağımlılıkları yönetilebilir hale getirir, test edilebilirliği artırır. ```javascript // src/repositories/userRepository.js class UserRepository { constructor(db) { this.db = db; // Örneğin bir veritabanı bağlantısı } async findById(id) { // Veritabanından kullanıcıyı çekme mantığı console.log(`2026: Veritabanından kullanıcı ${id} çekiliyor.`); return { id, name: 'John Doe', email: `john.${id}@example.com` }; } async save(user) { console.log(`2026: Kullanıcı kaydediliyor:`, user); return { ...user, id: Math.floor(Math.random() * 1000) }; } } module.exports = UserRepository; ``` ```javascript // src/services/userService.js class UserService { constructor(userRepository) { this.userRepository = userRepository; } async getUserDetails(id) { const user = await this.userRepository.findById(id); // Ek iş mantığı, örneğin email doğrulama return user; } async createUser(userData) { // Kullanıcı oluşturma ve doğrulama mantığı if (!userData.name || !userData.email) { throw new Error('Geçersiz kullanıcı verisi.'); } return this.userRepository.save(userData); } } module.exports = UserService; ``` ```javascript // app.js (Dependency Injection örneği) const UserRepository = require('./src/repositories/userRepository'); const UserService = require('./src/services/userService'); // Varsayımsal bir veritabanı bağlantısı const dbConnection = { /* ... */ }; const userRepository = new UserRepository(dbConnection); const userService = new UserService(userRepository); async function run() { try { const user = await userService.getUserDetails(123); console.log('Kullanıcı Detayları:', user); const newUser = await userService.createUser({ name: 'Jane Doe', email: 'jane@example.com' }); console.log('Yeni Kullanıcı Oluşturuldu:', newUser); } catch (error) { console.error('Hata:', error.message); } } run(); ``` ```bash # Çalıştırma node app.js ``` Bu yapı, kodun daha temiz, test edilebilir ve ölçeklenebilir olmasını sağlar. ### BÖLÜM 8 - Best Practices & Anti-Patterns Node.js uygulamalarınızı 2026 standartlarına uygun, performanslı ve güvenli hale getirmek için bazı en iyi uygulamaları ve kaçınılması gereken anti-pattern'ları bilmek hayati önem taşır. * **✅ Asenkron Programlamayı Doğru Kullanın:** `async/await` veya Promises kullanarak callback cehenneminden kaçının. Bu, kodun okunabilirliğini ve bakımını ciddi şekilde iyileştirir. * **❌ Senkron I/O Kullanmaktan Kaçının:** `fs.readFileSync` gibi senkron metodlar, ana olay döngüsünü bloke eder ve uygulamanızın performansını düşürür. Her zaman asenkron alternatifleri tercih edin. * **✅ Hata Yönetimini Ciddiye Alın:** Her asenkron operasyonda hata yakalama mekanizmaları (try/catch, `.catch()` blokları) kullanın. Unhandled promise rejection'lar ve uncaught exception'lar uygulamanızı çökertir. `process.on('uncaughtException')` veya `process.on('unhandledRejection')` gibi global yakalayıcılar sadece son çare olmalıdır. * **❌ Global Durum Kullanmaktan Kaçının:** Özellikle Express gibi çerçevelerde, istekler arasında global değişkenlerde durum tutmak race condition'lara ve beklenmedik davranışlara yol açar. Her isteği bağımsız ve durumsuz (stateless) düşünün. * **✅ Ortam Değişkenlerini Kullanın:** Hassas verileri (API anahtarları, veritabanı şifreleri) doğrudan koda yazmak yerine ortam değişkenleri aracılığıyla yönetin. `dotenv` geliştirme için idealdir, üretimde ise platformunuzun (AWS, Heroku vb.) sunduğu mekanizmaları kullanın. * **❌ `npm install` ile Production'da Geliştirme Bağımlılıklarını Kurmayın:** `devDependencies` sadece geliştirme için gerekli olan paketleri içerir. `npm install --production` komutuyla sadece `dependencies` içindeki paketleri kurarak üretim ortamının boyutunu ve güvenlik riskini azaltın. * **✅ Loglamayı Etkin Kullanın:** `winston` veya `pino` gibi güçlü bir loglama kütüphanesi kullanarak uygulamanızın davranışını izleyin. Hata ayıklama ve sorun giderme için detaylı ve yapılandırılmış loglar kritik öneme sahiptir. * **❌ `console.log`'u Üretimde Kullanmayın:** Performans düşüşüne neden olabilir ve hassas bilgileri açığa çıkarabilir. Bunun yerine yapılandırılmış loglama kütüphanelerini tercih edin. * **✅ Güvenlik Başlıklarını Uygulayın:** `helmet` gibi paketler kullanarak yaygın web güvenlik açıklarına karşı koruma sağlayın (XSS, CSRF, Clickjacking vb.). * **❌ Güvenlik Açığı Olan Bağımlılıkları Kullanmayın:** `npm audit` komutunu düzenli olarak çalıştırın ve bağımlılıklarınızdaki bilinen güvenlik açıklarını giderin. 2026 itibarıyla `npm audit fix --force` komutu, daha agresif düzeltmeler sunabilmektedir. * **✅ Cluster Modülünü veya PM2 Kullanın:** Node.js'in tek iş parçacıklı yapısını aşmak ve çok çekirdekli CPU'lardan tam verim almak için `cluster` modülünü veya `PM2` gibi bir süreç yöneticisini kullanarak uygulamanızın birden fazla kopyasını çalıştırın. ### BÖLÜM 9 - Yaygın Hatalar ve Çözümleri (Troubleshooting) Node.js geliştirirken karşılaşabileceğiniz bazı yaygın sorunlar ve 2026'da geçerli çözümleri: 1. **Problem: `Error: listen EADDRINUSE: address already in use :::3000`** * **Sebep:** Belirtilen port (örneğin 3000), zaten başka bir işlem tarafından kullanılmaktadır. * **Çözüm:** Portu kullanan işlemi sonlandırın veya uygulamanızı farklı bir porta taşıyın. * Linux/macOS: ```bash sudo lsof -i :3000 kill -9 ``` * Windows: ```cmd netstat -ano | findstr :3000 taskkill /PID /F ``` 2. **Problem: `TypeError: Cannot read property 'xyz' of undefined`** * **Sebep:** Tanımlanmamış (undefined) bir değerin özelliğine erişmeye çalışıyorsunuz. Genellikle bir API yanıtı beklenen yapıda gelmediğinde veya bir değişkenin değeri beklenenden farklı olduğunda ortaya çıkar. * **Çözüm:** Kodunuzu kontrol ederek `xyz` özelliğine erişmeden önce nesnenin gerçekten var olup olmadığını doğrulayın. Opsiyonel zincirleme (`?.`) veya null birleştirme (`??`) operatörleri 2026'da bu tür durumları yönetmek için yaygın olarak kullanılır. ```javascript // Hatalı: // const user = getUser(); // console.log(user.address.street); // Doğru: const user = getUser(); // user null veya undefined olabilir console.log(user?.address?.street || 'Adres bilgisi yok.'); ``` 3. **Problem: `(node:XXXX) UnhandledPromiseRejectionWarning: ...`** * **Sebep:** Bir Promise'in reddedilmesi (reject olması) durumunda, bu reddi yakalayan bir `.catch()` bloğunuz veya `try/catch` bloğunuz yok. * **Çözüm:** Her Promise tabanlı asenkron fonksiyon çağrınızda hataları yakalayın. Özellikle `async/await` kullanıyorsanız, `await` çağrılarını bir `try/catch` bloğu içine alın. ```javascript async function fetchData() { return Promise.reject(new Error('Veri çekme başarısız!')); } // Hatalı: // fetchData(); // Hata yakalanmaz // Doğru: async function handleData() { try { await fetchData(); } catch (error) { console.error('Hata yakalandı:', error.message); } } handleData(); ``` 4. **Problem: Uygulama Bellek Tüketimi Yüksek veya Yavaş Çalışıyor.** * **Sebep:** Bellek sızıntıları, CPU yoğun işlemlerin ana olay döngüsünü bloke etmesi veya verimsiz kod yazımı. * **Çözüm:** * **Bellek Sızıntıları:** Chrome DevTools'un bellek profilleme araçlarını veya `node --inspect` ile Node.js uygulamanızı inceleyin. Kapanmayan bağlantılar, dinleyiciler veya büyük objelerin referanslarının tutulması bellek sızıntılarına neden olabilir. * **CPU Yoğun İşlemler:** Bölüm 7'de bahsedilen `worker_threads` modülünü kullanarak CPU yoğun görevleri ayrı iş parçacıklarına taşıyın. * **Verimsiz Kod:** Algoritma karmaşıklığını optimize edin, büyük döngülerden ve gereksiz veri kopyalamadan kaçının. ### BÖLÜM 10 - Performans Optimizasyonu Node.js uygulamalarının performansı, kullanıcı deneyimi ve maliyet açısından kritik öneme sahiptir. 2026'da, mikroservis ve sunucusuz mimarilerde performans optimizasyonu daha da ön plana çıkmıştır. 1. **Gecikme Süresini (Latency) Azaltma:** * **Önce:** Basit bir API isteği 500ms sürüyor. * **Sonra:** 150ms'ye düştü. * **Teknik:** Veritabanı sorgularını optimize etmek (indeksler, join'leri azaltma), önbellekleme (Redis, Memcached) kullanmak, gereksiz middleware'leri kaldırmak. * **Kod Örneği (Önbellekleme ile):** ```bash npm install express redis ``` ```javascript // cache-example.js const express = require('express'); const redis = require('redis'); const app = express(); const port = 3000; const redisClient = redis.createClient({ url: 'redis://localhost:6379' }); redisClient.on('error', (err) => console.log('Redis Client Error', err)); (async () => { await redisClient.connect(); console.log('Redis\'e bağlandı.'); })(); async function getCachedData(key, fetchFunction) { const cached = await redisClient.get(key); if (cached) { console.log('Önbellekten çekildi.'); return JSON.parse(cached); } const data = await fetchFunction(); await redisClient.setEx(key, 60, JSON.stringify(data)); // 60 saniye önbellekte tut console.log('Veritabanından çekildi ve önbelleğe alındı.'); return data; } // Varsayımsal bir veritabanı çağrısı async function fetchUsersFromDB() { return new Promise(resolve => { setTimeout(() => { resolve([{ id: 1, name: 'Cache User 2026' }]); }, 300); // 300ms gecikmeli veritabanı simülasyonu }); } app.get('/users-cached', async (req, res) => { const users = await getCachedData('all_users', fetchUsersFromDB); res.json(users); }); app.listen(port, () => { console.log(`Sunucu http://localhost:${port} adresinde çalışıyor.`); }); ``` ```bash # Çalıştırma (Redis sunucusunun çalıştığından emin olun) node cache-example.js ``` İlk istekte 300ms gecikme, sonraki isteklerde anında yanıt alacaksınız. 2. **Bellek Kullanımını Optimize Etme:** * **Önce:** Uygulama 200MB bellek kullanıyor. * **Sonra:** 80MB'a düştü. * **Teknik:** Stream'ler kullanarak büyük dosyaları parça parça işlemek, gereksiz objeleri garbage collector'a bırakmak, V8 motorunun bellek optimizasyonlarını anlamak. * **Profiling Araçları:** `node --inspect` ile Chrome DevTools, `clinic.js` (Doctor, Flame, Bubbleprof) gibi araçlar bellek ve CPU kullanımını analiz etmek için vazgeçilmezdir. ```bash npm install -g clinic ``` ```bash # Bellek profilleme örneği clinic doctor -- node your-app.js # Ardından tarayıcınızda raporu açın ``` 3. **İstek Başına İşlem (Requests per Second - RPS) Artırma:** * **Önce:** 100 RPS * **Sonra:** 500 RPS * **Teknik:** `cluster` modülünü veya `PM2` kullanarak çoklu işlemci çekirdeklerinden faydalanmak, verimli routing, veritabanı bağlantı havuzları kullanmak. ```javascript // cluster-example.js const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`Ana işlem ${process.pid} çalışıyor.`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); // Her CPU çekirdeği için bir işçi başlat } cluster.on('exit', (worker, code, signal) => { console.log(`İşçi ${worker.process.pid} öldü. Yeni işçi başlatılıyor...`); cluster.fork(); // Ölen işçinin yerine yenisini başlat }); } else { // İşçi süreçleri HTTP sunucusunu çalıştırır http.createServer((req, res) => { res.writeHead(200); res.end(`Merhaba 2026! İşçi ${process.pid} yanıt veriyor.\n`); }).listen(8000); console.log(`İşçi işlem ${process.pid} başladı.`); } ``` ```bash # Çalıştırma node cluster-example.js ``` Bu, uygulamanızın CPU çekirdeklerini daha etkin kullanmasını sağlayacaktır. ### BÖLÜM 11 - Gerçek Dünya Proje Örneği (Mini Project) Basit bir 'Görev Yöneticisi' API'si oluşturalım. Bu API, görevleri (task) listeleme, ekleme, güncelleme ve silme (CRUD) işlemlerini destekleyecek ve verileri bir JSON dosyasına kaydedecektir. **Proje Yapısı:** ``` my-task-api/ ├── src/ │ ├── models/ │ │ └── task.js # Görev modeli (veri yapısı) │ ├── repositories/ │ │ └── taskRepository.js # Veri erişim katmanı (dosya işlemleri) │ └── services/ │ └── taskService.js # İş mantığı katmanı ├── app.js # Ana Express uygulaması ├── package.json └── tasks.json # Veri depolama dosyası ``` **1. `package.json` Oluşturma:** ```bash cd my-task-api npm init -y npm install express uuid ``` **2. `tasks.json` (Veri Dosyası):** ```json [ { "id": "1", "tit