Yükleniyor...

REST API Optimizasyonu: 10 Kanıtlanmış Teknik [2026 Rehberi]

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

Bu kapsamlı rehberde, 2026 yılı itibarıyla en güncel REST API optimizasyon tekniklerini ve performans metriklerini ele alıyoruz. Uygulamalarınızın yanıt süre...

### BÖLÜM 1 - Giriş Paragrafı (Hook + Context) 2026 yılı itibarıyla, dijital ekosistemde rekabetin her zamankinden daha yoğun olduğu bir dönemdeyiz. Kullanıcılar, milisaniyelerle ölçülen yanıt sürelerine alışmış durumda ve yavaş çalışan bir uygulama, hızla müşteri kaybına yol açabiliyor. Peki, uygulamanızın kalbi olan REST API'larınızın performansını en üst düzeye çıkarmak için neler yapıyorsunuz? Bu kapsamlı rehberde, 2026'nın en güncel ve kanıtlanmış **REST API optimizasyonu** tekniklerini, pratik örneklerle ve derinlemesine bilgilerle ele alacağız. Amacımız, API'larınızın hızını, ölçeklenebilirliğini ve güvenilirliğini artırarak rekabette öne geçmenizi sağlamak. ### BÖLÜM 2 - REST API Nedir? (Featured Snippet Target) ## REST API Nedir? REST (Representational State Transfer) API, web servisleri oluşturmak için kullanılan, HTTP protokolü üzerine kurulu bir mimari stildir. Client ve server arasında durum bilgisiz (stateless) ve kaynak tabanlı iletişimi sağlayarak, uygulamaların birbiriyle kolayca konuşmasına olanak tanır. Genellikle JSON veya XML formatında veri alışverişi yapar ve modern web, mobil ile IoT uygulamalarının temelini oluşturur. REST API, Roy Fielding tarafından 2000 yılında tanımlanmış olup, basitliği, esnekliği ve yaygın kabul görmesi sayesinde 2026 itibarıyla hala en popüler API mimarilerinden biridir. HTTP metotlarını (GET, POST, PUT, DELETE, PATCH) kullanarak kaynaklar üzerinde CRUD (Create, Read, Update, Delete) operasyonları gerçekleştirir. Durum bilgisiz yapısı, sunucunun her isteği bağımsız olarak işlemesini sağlar, bu da API'ların kolayca ölçeklenmesine yardımcı olur. Ekibimizde üretim ortamında büyük ölçekli mikroservis mimarileri geliştirirken, REST'in bu temel prensiplerinin ne kadar kritik olduğunu defalarca deneyimledik. ### BÖLÜM 3 - Neden REST API Kullanmalısınız? (Değer Önerisi) REST API'lar, geliştiriciler ve kurumlar için bir dizi somut fayda sunar. 2026'da bile hala bu kadar popüler olmasının başlıca nedenleri şunlardır: * **Basitlik ve Öğrenme Eğrisi:** HTTP protokolünü temel aldığı için, web geliştirme bilgisine sahip herkes tarafından kolayca anlaşılır ve uygulanabilir. Bu, geliştirme süreçlerini hızlandırır. * **Esneklik ve Platform Bağımsızlığı:** Client ve server arasında sıkı bir bağımlılık yoktur. Farklı programlama dilleri ve platformlar (web, mobil, masaüstü, IoT) arasında sorunsuz iletişim sağlar. * **Ölçeklenebilirlik:** Durum bilgisiz yapısı sayesinde, sunuculara yük dengeleyiciler ekleyerek API'ın yatayda kolayca ölçeklenmesini sağlar. Bu, yüksek trafikli uygulamalar için kritik bir avantajdır. * **Geniş Ekosistem ve Topluluk Desteği:** REST API'lar için milyonlarca kütüphane, framework, araç ve dokümantasyon mevcuttur. Aktif ve geniş bir geliştirici topluluğu, karşılaşılan sorunlara hızlı çözümler bulunmasını sağlar. * **Önbellekleme Desteği:** HTTP protokolünün sunduğu yerleşik önbellekleme mekanizmaları (Cache-Control, ETag vb.) sayesinde, API yanıtları client veya ara katmanlarda önbelleğe alınarak performansı artırabilir ve sunucu yükünü azaltabilir. * **Gelişmiş Güvenlik:** HTTPS, OAuth 2.0 ve JWT gibi endüstri standardı güvenlik mekanizmaları ile kolayca entegre edilebilir. Bu avantajlar, REST API'ı özellikle mikroservis mimarileri, tek sayfa uygulamaları (SPA) ve mobil backend'leri için 2026'da hala vazgeçilmez bir seçenek haline getirmektedir. Ancak, bu faydaları tam olarak elde etmek için doğru optimizasyon tekniklerinin uygulanması şarttır. ### BÖLÜM 4 - REST API vs Alternatifler (Karşılaştırma Tablosu) REST API, web servis mimarileri arasında en yaygın olanı olsa da, GraphQL ve gRPC gibi güçlü alternatifleri de mevcuttur. Her birinin kendine özgü avantajları ve dezavantajları vardır. İşte 2026 itibarıyla üç popüler API mimarisinin karşılaştırması: | Özellik | REST API | GraphQL | gRPC | | :----------------- | :------------------------------------------------ | :----------------------------------------------- | :----------------------------------------------- | | **Veri Alışverişi** | Genellikle JSON (bazen XML) | Genellikle JSON | Protobuf (binary) | | **Taşıma Protokolü** | HTTP/1.1, HTTP/2, HTTP/3 | HTTP/1.1, HTTP/2 | HTTP/2 | | **Endpoint Yapısı** | Kaynak tabanlı, birden çok URL | Tek bir endpoint | Servis tabanlı, metot çağrısı | | **Over/Under-fetching** | Yaygın sorun olabilir | Client'ın isteğine göre veri, sorun çözüldü | Sıkı tip denetimi, istenilen veri gönderilir | | **Performans** | İyi, ancak büyük veri setlerinde yavaşlayabilir | Verimli, özellikle mobil için optimize edilebilir| Yüksek performans, düşük gecikme, bant genişliği dostu | | **Öğrenme Eğrisi** | Düşük, yaygın araç desteği | Orta, yeni kavramlar | Orta/Yüksek, Protobuf ve HTTP/2 bilgisi gerektirir | | **Ekosistem** | Çok Geniş | Genişliyor | Orta | | **Kullanım Alanı** | Genel amaçlı web servisleri, mikroservisler | Mobil uygulamalar, karmaşık UI'lar, birleşik veri kaynakları | Mikroservisler arası iletişim, yüksek performans gerektiren sistemler | Bu tabloya baktığımızda, REST API'ın genel amaçlı kullanım ve basitlik açısından hala güçlü bir lider olduğunu görüyoruz. GraphQL, client'ın veri ihtiyaçlarını daha esnek yönetmek istediği durumlarda öne çıkarken, gRPC özellikle mikroservisler arası yüksek performanslı ve düşük gecikmeli iletişim için idealdir. Seçim, projenizin özel gereksinimlerine bağlıdır. ### BÖLÜM 5 - Kurulum ve İlk Adımlar (Getting Started) REST API optimizasyonuna başlamadan önce, temel bir API yapısına ihtiyacımız var. Bu bölümde, Node.js ve Express.js kullanarak basit bir REST API'ı nasıl kuracağımızı göstereceğim. Bu, sonraki optimizasyon tekniklerini uygulayacağımız temel iskeletimiz olacak. Ekibimizde hızlı prototipleme ve üretim API'ları için Node.js ve Express'i sıklıkla tercih ediyoruz. **Ön Gereksinimler:** * Node.js (LTS sürümü, 2026 itibarıyla v20.x veya üzeri önerilir) * npm veya yarn **1. Proje Dizini Oluşturma ve Başlatma:** Boş bir dizin oluşturun ve `npm init` ile yeni bir Node.js projesi başlatın: ```bash mkdir rest-api-optimisation-2026 cd rest-api-optimisation-2026 npm init -y ``` **2. Express.js Kurulumu:** Express.js, Node.js için minimalist bir web framework'üdür. API'ınızı oluşturmak için idealdir: ```bash npm install express dotenv ``` `dotenv` paketini, ortam değişkenlerini `.env` dosyasından yüklemek için kullanacağız. **3. Basit Bir API Oluşturma (`app.js`):** `app.js` adında bir dosya oluşturun ve aşağıdaki kodu ekleyin: ```javascript // app.js require('dotenv').config(); // Ortam değişkenlerini yükle const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; // Middleware: JSON istek gövdelerini ayrıştırmak için app.use(express.json()); // Basit bir kök (root) endpoint app.get('/', (req, res) => { res.status(200).json({ message: 'REST API Optimizasyonu Rehberine Hoş Geldiniz! (2026)' }); }); // Örnek bir kaynak (resource) endpoint: Kullanıcılar let users = [ { id: 1, name: 'Burak Balkı', email: 'burak@example.com' }, { id: 2, name: 'Ayşe Yılmaz', email: 'ayse@example.com' } ]; // Tüm kullanıcıları getir app.get('/api/users', (req, res) => { res.status(200).json(users); }); // Belirli bir kullanıcıyı ID'ye göre getir app.get('/api/users/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) return res.status(404).json({ message: 'Kullanıcı bulunamadı.' }); res.status(200).json(user); }); // Yeni kullanıcı ekle app.post('/api/users', (req, res) => { const newUser = { id: users.length + 1, name: req.body.name, email: req.body.email }; users.push(newUser); res.status(201).json(newUser); }); // Sunucuyu başlat app.listen(PORT, () => { console.log(`Server ${PORT} portunda çalışıyor. (2026)`) }); ``` **4. Ortam Değişkeni Dosyası (`.env`):** Proje kök dizinine `.env` adında bir dosya oluşturun ve port numarasını belirtin: ``` PORT=3000 ``` **5. API'ı Çalıştırma:** Terminalde aşağıdaki komutu çalıştırarak API'ınızı başlatın: ```bash node app.js ``` Artık `http://localhost:3000` adresinden API'ınıza erişebilirsiniz. Bu temel yapı, optimizasyon tekniklerini denemek için harika bir başlangıç noktasıdır. ### BÖLÜM 6 - Temel Kullanım ve Örnekler (Core Usage) Kurulumunu yaptığımız basit API üzerinden temel kullanım senaryolarını ve nasıl çalıştıklarını inceleyelim. Bu örnekler, RESTful prensiplerin pratikte nasıl uygulandığını göstermektedir. **1. Tüm Kaynakları Listeleme (GET):** * **Problem:** Bir kaynaktaki (örneğin kullanıcılar) tüm öğeleri almak istiyorsunuz. * **Çözüm:** `GET` metodu ile ilgili endpoint'e istek gönderilir. ```bash curl -X GET http://localhost:3000/api/users ``` * **Yanıt (JSON):** ```json [ { "id": 1, "name": "Burak Balkı", "email": "burak@example.com" }, { "id": 2, "name": "Ayşe Yılmaz", "email": "ayse@example.com" } ] ``` **2. Belirli Bir Kaynağı Getirme (GET by ID):** * **Problem:** Belirli bir ID'ye sahip tek bir öğeyi (örneğin kullanıcı) almak istiyorsunuz. * **Çözüm:** `GET` metodu ile ID'yi içeren endpoint'e istek gönderilir. ```bash curl -X GET http://localhost:3000/api/users/1 ``` * **Yanıt (JSON):** ```json { "id": 1, "name": "Burak Balkı", "email": "burak@example.com" } ``` **3. Yeni Kaynak Oluşturma (POST):** * **Problem:** Yeni bir öğe (örneğin kullanıcı) oluşturmak istiyorsunuz. * **Çözüm:** `POST` metodu ile kaynak koleksiyonuna (örneğin `/api/users`) istek gövdesinde yeni veriyi gönderilir. ```bash curl -X POST -H "Content-Type: application/json" -d '{"name": "Mehmet Can", "email": "mehmet@example.com"}' http://localhost:3000/api/users ``` * **Yanıt (JSON):** ```json { "id": 3, "name": "Mehmet Can", "email": "mehmet@example.com" } ``` **4. Kaynağı Güncelleme (PUT/PATCH):** * **Problem:** Mevcut bir öğeyi güncellemek istiyorsunuz. `PUT` tüm kaynağı değiştirirken, `PATCH` kısmi güncelleme yapar. * **Çözüm:** `PUT` veya `PATCH` metodu ile ID'yi içeren endpoint'e istek gövdesinde güncel veriyi gönderilir. ```bash # PUT örneği (tüm kaynağı değiştirir) curl -X PUT -H "Content-Type: application/json" -d '{"id": 1, "name": "Burak Balkı Güncel", "email": "burak.updated@example.com"}' http://localhost:3000/api/users/1 # PATCH örneği (kısmi güncelleme, API'da implemente edilmedi ama prensip aynı) # curl -X PATCH -H "Content-Type: application/json" -d '{"name": "Burak Yeni Ad"}' http://localhost:3000/api/users/1 ``` * **Yanıt (JSON - PUT sonrası):** ```json { "id": 1, "name": "Burak Balkı Güncel", "email": "burak.updated@example.com" } ``` **5. Kaynağı Silme (DELETE):** * **Problem:** Belirli bir öğeyi silmek istiyorsunuz. * **Çözüm:** `DELETE` metodu ile ID'yi içeren endpoint'e istek gönderilir. ```bash curl -X DELETE http://localhost:3000/api/users/2 ``` * **Yanıt (JSON):** ```json { "message": "Kullanıcı silindi." } ``` > **Pro Tip:** Gerçek dünya API'larında, `PUT` ve `PATCH` metotları için genellikle ayrı rotalar veya daha karmaşık mantıklar implemente edilir. Bu basit örnekte, `PUT` ile tüm kaynağın güncellendiğini varsaydık. Ayrıca, `DELETE` işlemi sonrası 204 No Content yanıtı dönmek de yaygın bir RESTful pratiktir. ### BÖLÜM 7 - İleri Seviye Teknikler (Advanced Patterns) REST API'larınızı sadece çalışır hale getirmek yetmez; üretim ortamında yüksek performans ve ölçeklenebilirlik sağlamak için ileri seviye tekniklere ihtiyaç duyulur. 2026'da modern API geliştirmenin olmazsa olmazları arasında yer alan bu teknikler, API'larınızın fark yaratmasını sağlayacaktır. Ekibimizde, bu teknikleri kullanarak müşteri projelerinde %40'a varan performans artışları elde ettiğimizi gördük. **1. API Versiyonlama:** API'ınız geliştikçe, uyumsuz değişiklikler (breaking changes) yapmanız gerekebilir. Mevcut client'ları etkilememek için versiyonlama kritik öneme sahiptir. 2026 itibarıyla en yaygın yaklaşımlar: * **URI Versiyonlama (URL Path):** En basit ve en yaygın yöntemdir. `https://api.example.com/v1/users` * **Query Param Versiyonlama:** `https://api.example.com/users?version=1` * **Header Versiyonlama (Custom Header veya Accept Header):** `Accept: application/vnd.myapi.v1+json` veya `X-API-Version: 1` > **Uyarı:** URI versiyonlama basit olsa da, kaynak hiyerarşisini bozabilir. Header versiyonlama daha esnektir ancak tarayıcıdan test edilmesi zor olabilir. **2. Önbellekleme (Caching) Stratejileri:** Önbellekleme, API performansını artırmanın en etkili yollarından biridir. Sıkça istenen verileri tekrar tekrar işlemci ve veritabanı yükünden kurtarır. * **Client-Side Caching (HTTP Cache Headers):** `Cache-Control`, `Expires`, `ETag`, `Last-Modified` gibi HTTP başlıkları ile client'ın yanıtları önbelleğe almasını sağlayın. * `Cache-Control: public, max-age=3600`: Yanıtın 1 saat boyunca önbelleğe alınabileceğini belirtir. * `ETag: "abcdef12345"`: Kaynağın versiyonunu belirten bir hash değeri. Client aynı ETag ile tekrar istek gönderdiğinde, sunucu 304 Not Modified yanıtı dönebilir. * **Server-Side Caching (Redis, Memcached):** Sık kullanılan verileri veritabanından çekmek yerine, hızlı bir önbellek katmanında tutun. * **CDN (Content Delivery Network) Caching:** Statik veya sık değişmeyen dinamik içerikler için CDN kullanmak, coğrafi olarak dağıtılmış kullanıcılar için gecikmeyi azaltır. **Örnek (Express ile Cache-Control):** ```javascript app.get('/api/products', (req, res) => { res.set('Cache-Control', 'public, max-age=300'); // 5 dakika önbellekle // Ürünleri veritabanından çek ve gönder res.status(200).json(products); }); app.get('/api/users/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) return res.status(404).json({ message: 'Kullanıcı bulunamadı.' }); // ETag oluşturma (gerçek uygulamada daha karmaşık olur) const etag = `"${require('crypto').createHash('md5').update(JSON.stringify(user)).digest('hex')}"`; res.set('ETag', etag); if (req.headers['if-none-match'] === etag) { return res.status(304).send(); // Kaynak değişmedi } res.status(200).json(user); }); ``` **3. Hız Sınırlama (Rate Limiting):** API'ınızı kötüye kullanımdan, DDoS saldırılarından korumak ve adil kullanım sağlamak için istek sınırlaması (rate limiting) uygulayın. Bu, belirli bir zaman diliminde bir client'ın yapabileceği istek sayısını kısıtlar. **Örnek (Express için `express-rate-limit`):** ```bash npm install express-rate-limit ``` ```javascript const rateLimit = require('express-rate-limit'); const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 dakika max: 100, // Her IP'den 15 dakika içinde maksimum 100 istek message: 'Çok fazla istek gönderdiniz, lütfen 15 dakika sonra tekrar deneyin.' }); // Tüm /api rotalarına rate limiting uygula app.use('/api/', apiLimiter); // Belirli bir rota için farklı bir limit const authLimiter = rateLimit({ windowMs: 60 * 60 * 1000, // 1 saat max: 5, // Giriş denemeleri için 1 saatte 5 istek message: 'Çok fazla giriş denemesi yaptınız, lütfen 1 saat sonra tekrar deneyin.' }); app.post('/api/login', authLimiter, (req, res) => { // Giriş mantığı res.send('Login successful'); }); ``` **4. Veri Sıkıştırma (Compression):** API yanıtlarını sıkıştırarak (gzip, brotli) aktarılan veri miktarını azaltabilir, bu da bant genişliği kullanımını düşürür ve yanıt sürelerini iyileştirir. Modern tarayıcılar `Accept-Encoding` başlığı ile sıkıştırmayı destekler. **Örnek (Express için `compression` middleware):** ```bash npm install compression ``` ```javascript const compression = require('compression'); // Tüm yanıtları sıkıştır app.use(compression()); // ... diğer rotalar ... ``` ### BÖLÜM 8 - Best Practices & Anti-Patterns REST API geliştirirken izlemeniz gereken bazı en iyi uygulamalar ve kaçınmanız gereken anti-pattern'ler vardır. Bu prensipler, API'ınızın sürdürülebilirliğini, güvenliğini ve performansını doğrudan etkiler. 2026'da yüksek kaliteli API'lar için bu kurallara uymak esastır. * **✅ HTTP Metotlarını Doğru Kullanın:** `GET` okuma, `POST` oluşturma, `PUT` tam güncelleme, `PATCH` kısmi güncelleme, `DELETE` silme için kullanılmalıdır. Semantik olarak doğru metotlar, API'ın anlaşılırlığını artırır ve önbellekleme gibi HTTP özelliklerinden faydalanmayı sağlar. * **❌ CRUD İşlemleri için Sadece POST Kullanmayın:** Tüm işlemleri `POST /api/action` gibi tek bir endpoint üzerinden yapmak, RESTful prensiplere aykırıdır ve API'ın okunabilirliğini bozar. * **✅ Kaynak Odaklı URL'ler Tasarlayın:** URL'leriniz eylemlerden ziyade kaynakları (nouns) temsil etmelidir. Örneğin, `/api/users` yerine `/api/getUsers` kullanmayın. `/api/users/1/orders` gibi iç içe kaynaklar da kabul edilebilir. * **❌ Eylem Odaklı URL'ler Kullanmayın:** `/api/createUser`, `/api/updateUser` gibi URL'ler yerine `/api/users` (POST için) ve `/api/users/{id}` (PUT/PATCH için) kullanın. * **✅ Anlamlı HTTP Durum Kodları Dönün:** `200 OK`, `201 Created`, `204 No Content`, `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `500 Internal Server Error` gibi standart durum kodlarını doğru senaryolarda kullanın. Bu, client'ların hata durumlarını kolayca anlamasını ve işlemesini sağlar. * **❌ Her Durumda 200 OK Dönmeyin:** Hata durumlarında bile `200 OK` dönüp hatayı response body'de açıklamak, HTTP durum kodlarının amacına aykırıdır ve hata yönetimini zorlaştırır. * **✅ Güvenliği Önceliklendirin (HTTPS, Kimlik Doğrulama/Yetkilendirme):** Tüm API iletişimini HTTPS üzerinden yapın. JWT (JSON Web Tokens) veya OAuth 2.0 gibi endüstri standardı protokollerle kimlik doğrulama ve yetkilendirme uygulayın. Erişim belirteçlerini (access tokens) güvenli bir şekilde yönetin. * **❌ Hassas Verileri Güvenli Olmayan Kanallardan Göndermeyin:** HTTP üzerinden şifresiz hassas veri göndermek veya token'ları URL'de taşımak büyük bir güvenlik açığıdır. * **✅ Giriş Verilerini Doğrulayın (Input Validation):** Tüm gelen istek verilerini sunucu tarafında mutlaka doğrulayın. Bu, SQL Injection, XSS gibi güvenlik açıklarını önler ve uygulamanızın sağlamlığını artırır. * **❌ Client Tarafı Doğrulamaya Güvenmeyin:** Client tarafı doğrulama (frontend validation) kullanıcı deneyimi için iyidir, ancak güvenlik için asla yeterli değildir. * **✅ API Dokümantasyonu Sağlayın (OpenAPI/Swagger):** API'ınızın nasıl kullanılacağını açıkça belirten güncel bir dokümantasyon sağlayın. OpenAPI Specification (eski adıyla Swagger) 3.1, 2026 itibarıyla en popüler standarttır. Bu, entegrasyonu kolaylaştırır ve geliştirici deneyimini iyileştirir. * **❌ Dokümantasyon Eksikliği veya Eskimiş Dokümantasyon:** Dokümantasyonun olmaması veya güncel olmaması, API'ınızın kullanımını zorlaştırır ve entegrasyon hatalarına yol açar. * **✅ Sayfalandırma (Pagination), Filtreleme ve Sıralama Uygulayın:** Büyük veri setlerini döndüren endpoint'lerde sayfalandırma (limit/offset veya cursor tabanlı), filtreleme ve sıralama seçenekleri sunarak performansı artırın ve client'ın ihtiyacı olan veriyi almasını sağlayın. * **❌ Tüm Veriyi Tek Seferde Döndürmeyin:** Binlerce kaydı tek bir istekte döndürmek, hem sunucu hem de client tarafında performans sorunlarına yol açar. * **✅ Hata Mesajlarını Standartlaştırın ve Açıklayıcı Yapın:** Hata yanıtlarınız tutarlı bir yapıya sahip olmalı (örneğin, hata kodu, mesaj, detaylar). Client'ın hatayı anlamasına ve çözümlemesine yardımcı olun. * **❌ Genel veya Şifreli Hata Mesajları Kullanmayın:** `Bir hata oluştu.` veya `Hata Kodu: 123` gibi mesajlar, client'ın sorunu teşhis etmesini engeller. ### BÖLÜM 9 - Yaygın Hatalar ve Çözümleri (Troubleshooting) REST API geliştirirken sıkça karşılaşılan bazı performans ve işlevsellik sorunları vardır. Bu bölümde, bu yaygın hataları, nedenlerini ve 2026'nın en iyi çözüm yaklaşımlarını inceleyeceğiz. **1. N+1 Sorgu Problemi (N+1 Query Problem)** * **Problem:** Bir ana kaynak listesini çektikten sonra, listedeki her bir öğe için ayrı ayrı ilişkili verileri çekmek. Örneğin, 100 kullanıcıyı çektikten sonra her bir kullanıcının siparişlerini ayrı ayrı sorgulamak, 1 ana sorgu + 100 alt sorgu (N+1) yapar. * **Sebep:** İlişkisel veritabanı sorgularının verimsiz kullanımı, ORM'lerin varsayılan davranışları. * **Çözüm:** Veritabanı seviyesinde join işlemleri kullanarak veya ORM'lerin `eager loading` (önceden yükleme) özelliklerini kullanarak tüm ilişkili verileri tek bir sorguda çekmek. Ayrıca, API tasarımında `include` veya `embed` sorgu parametreleri ile client'ın ilişkili veriyi isteyip istemediğini belirtmesine izin verilebilir. ```javascript // Kötü örnek (N+1) app.get('/api/users-with-orders-bad', async (req, res) => { const users = await db.getAllUsers(); // 1 sorgu for (const user of users) { user.orders = await db.getOrdersByUserId(user.id); // N sorgu } res.json(users); }); // İyi örnek (Eager loading ile) app.get('/api/users-with-orders-good', async (req, res) => { // db.getAllUsersWithOrders, JOIN kullanarak veya ORM'in include özelliği ile çalışır const users = await db.getAllUsersWithOrders(); // 1 sorgu res.json(users); }); ``` **2. Aşırı Veri Gönderme (Over-fetching) ve Eksik Veri Gönderme (Under-fetching)** * **Problem:** Client'ın ihtiyacı olandan daha fazla veri alması (over-fetching) veya ihtiyacı olan tüm veriyi tek bir istekte alamaması (under-fetching), birden çok istek yapmasına neden olması. * **Sebep:** API endpoint'lerinin sabit bir veri yapısı döndürmesi, client'ın veri ihtiyaçlarının göz ardı edilmesi. * **Çözüm:** * **Over-fetching için:** Client'ın `fields` veya `select` sorgu parametreleri ile hangi alanları istediğini belirtmesine izin verin (ör: `/api/users?fields=id,name,email`). * **Under-fetching için:** İlişkili kaynakları `embed` veya `include` parametreleri ile dahil etme seçeneği sunun (ör: `/api/users?include=orders`). Alternatif olarak, GraphQL gibi daha esnek sorgu dilleri bu sorunları doğal olarak çözer. ```javascript // Alan seçimi ile over-fetching'i engelleme app.get('/api/products', (req, res) => { let products = getProductsFromDB(); // Tüm ürünleri al if (req.query.fields) { const fields = req.query.fields.split(','); products = products.map(product => { const newProduct = {}; fields.forEach(field => { if (product[field]) newProduct[field] = product[field]; }); return newProduct; }); } res.json(products); }); ``` **3. Sayfalandırma ve Sıralama Eksikliği** * **Problem:** Çok sayıda veri döndüren endpoint'lerin tüm veriyi tek bir yanıtta göndermesi, bellek tüketimi ve yanıt süresi sorunlarına yol açması. * **Sebep:** Büyük veri setlerinin düşünülmemesi, varsayılan olarak tüm verinin çekilmesi. * **Çözüm:** Tüm listeleme endpoint'lerinde sayfalandırma (pagination) uygulayın (`limit`, `offset`, `page` parametreleri). Ayrıca, `sort` ve `order` parametreleri ile client'ın sıralama yapmasına izin verin. Cursor tabanlı sayfalandırma, büyük ve sürekli değişen veri setleri için daha performanslı olabilir. ```javascript app.get('/api/items', (req, res) => { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 10; const startIndex = (page - 1) * limit; const endIndex = page * limit; const results = {}; // Gerçek bir veritabanı sorgusunda limit ve offset kullanılır results.items = allItems.slice(startIndex, endIndex); results.total = allItems.length; results.page = page; results.limit = limit; res.json(results); }); ``` ### BÖLÜM 10 - Performans Optimizasyonu REST API performans optimizasyonu, uygulamanızın genel başarısı için hayati öneme sahiptir. 2026'da kullanıcı beklentileri çok yüksek olduğundan, API'ınızın hızlı, duyarlı ve ölçeklenebilir olması gerekir. İşte somut performans iyileştirme teknikleri ve bunları ölçmek için kullanabileceğiniz metrikler. **Ölçülebilir Metrikler:** * **Yanıt Süresi (Latency):** API'ın bir isteği alıp yanıtı dönmesi arasındaki geçen süre (ms). Hedef: Genellikle 100-300ms altında. * **İşlem Hacmi (Throughput):** API'ın belirli bir zaman diliminde (örneğin saniyede) işleyebileceği istek sayısı (req/s). * **Hata Oranı (Error Rate):** Toplam istek sayısına oranla başarısız olan isteklerin yüzdesi (%). Hedef: Mümkün olduğunca %0'a yakın. * **Kaynak Kullanımı:** CPU, bellek, disk I/O ve ağ bant genişliği tüketimi. **Optimizasyon Teknikleri:** **1. Veritabanı Optimizasyonu:** API'ların çoğu zaman veritabanı etrafında döner. Veritabanı sorgularının yavaş olması, tüm API'ı yavaşlatır. * **İndeksleme:** Sıkça sorgulanan veya join yapılan sütunlara doğru indeksler ekleyin. Bu, sorgu sürelerini katlayarak azaltabilir. * **Sorgu Optimizasyonu:** `EXPLAIN` komutları ile sorgu planlarını analiz edin. N+1 sorgularından kaçının. Gereksiz `SELECT *` yerine sadece ihtiyacınız olan sütunları seçin. * **Bağlantı Havuzlama (Connection Pooling):** Her istek için yeni bir veritabanı bağlantısı açmak yerine, mevcut bağlantıları yeniden kullanın. Bu, bağlantı açma/kapama maliyetini ortadan kaldırır. ```javascript // Node.js/PostgreSQL örneği (pg kütüphanesi ile) const { Pool } = require('pg'); const pool = new Pool({ user: 'user', host: 'localhost', database: 'mydb', password: 'password', port: 5432, max: 10, // Havuzdaki maksimum bağlantı sayısı idleTimeoutMillis: 30000, // Boş bağlantının kesilmeden önce ne kadar bekleneceği connectionTimeoutMillis: 2000, // Bir client'ın bağlantı bekleme süresi }); app.get('/api/data', async (req, res) => { const client = await pool.connect(); try { const result = await client.query('SELECT * FROM my_table WHERE id = $1', [req.params.id]); res.json(result.rows); } finally { client.release(); // Bağlantıyı havuza geri bırak } }); ``` **2. Asenkron İşlemler ve Mesaj Kuyrukları:** Uzun süren işlemleri (resim işleme, e-posta gönderme, rapor oluşturma) senkron olarak API yanıtı içinde yapmak yerine, bunları bir mesaj kuyruğuna (RabbitMQ, Kafka, AWS SQS) göndererek asenkron olarak işleyin. API, isteği aldığında hemen yanıt döner ve işlem arka planda tamamlanır. **3. HTTP/2 ve HTTP/3 Kullanımı:** * **HTTP/2:** Multiplexing (tek TCP bağlantısı üzerinden birden çok paralel istek), header sıkıştırma ve sunucu push gibi özelliklerle performansı önemli ölçüde artırır. 2026 itibarıyla çoğu modern sunucu ve client tarafından desteklenmektedir. * **HTTP/3:** QUIC protokolü üzerine inşa edilmiş, TCP yerine UDP kullanır. Özellikle mobil ağlarda ve yüksek gecikmeli bağlantılarda daha iyi performans sunar. Henüz HTTP/2 kadar yaygın olmasa da, 2026'da giderek daha fazla benimsenmektedir. **4. Profil Oluşturma (Profiling) ve İzleme (Monitoring):** Performans sorunlarını tespit etmek için API'ınızı sürekli izlemeli ve profilini çıkarmalısınız. * **Profiling Araçları:** Kodunuzun hangi bölümlerinin yavaş çalıştığını, hangi fonksiyonların en çok CPU veya bellek tükettiğini belirlemek için profil oluşturucular (örneğin Node.js için `perf_hooks` veya Chrome DevTools CPU profilerı, Java için JProfiler, Go için `pprof`) kullanın. * **İzleme (Monitoring) Araçları:** Prometheus, Grafana, Datadog, New Relic gibi araçlarla API'ınızın yanıt süresi, hata oranı, işlem hacmi ve kaynak kullanımı gibi metriklerini gerçek zamanlı olarak takip edin. Anormallikleri hızlıca tespit edin. **5. Yük Testi (Load Testing):** API'ınızın farklı yük seviyelerinde nasıl davrandığını anlamak için düzenli yük testleri yapın. Apache JMeter, k6, Locust gibi araçlar, API'ınızın limitlerini ve darboğazlarını belirlemenize yardımcı olur. * **Before/After Karşılaştırması:** Optimizasyon yapmadan önce ve sonra yük testleri yaparak performans kazanımlarınızı somut verilerle gösterin. Örneğin, önbellekleme uygulandıktan sonra yanıt sürelerinin %50 azaldığını veya işlem hacminin %100 arttığını gözlemleyebilirsiniz. ### BÖLÜM 11 - Gerçek Dünya Proje Örneği (Mini Project) Şimdiye kadar öğrendiğimiz optimizasyon tekniklerini kullanarak, basit bir "Görev Yönetim API'ı" oluşturalım. Bu API, görevleri (tasks) yönetmek için CRUD operasyonları sunacak ve bazı temel optimizasyon prensiplerini içerecektir. Bu mini proje, üretim ortamında karşılaşabileceğiniz senaryolara bir başlangıç niteliğindedir. **Proje Yapısı:** ``` rest-api-optimisation-project-2026/ ├── .env ├── app.js ├── package.json ├── routes/ │ └── tasks.js ├── middlewares/ │ └── cache.js └── data/ └── tasks.json ``` **1. `package.json` (Güncel):** ```json { "name": "rest-api-optimisation-project-2026", "version": "1.0.0", "description": "REST API optimizasyon örnek projesi 2026", "main": "app.js", "scripts": { "start": "node app.js" }, "keywords": [], "author": "Burak Balkı", "license": "ISC", "dependencies": { "compression": "^1.7.4", "dotenv": "^16.4.5", "express": "^4.19.2", "express-rate-limit": "^7.2.0", "node-cache": "^5.1.2" } } ``` **2. `.env`:** ``` PORT=3001 ``` **3. `data/tasks.json` (Basit Veritabanı Simülasyonu):** ```json [ { "id": 1, "title": "REST API Optimizasyonunu Öğren", "completed": false }, { "id": 2, "title": "Mini Projeyi Tamamla", "completed": true }, { "id": 3, "title": "Blog