REST, GraphQL ve gRPC: API Tasarım Rehberi

## API Tasarımında Üç Temel Yaklaşım REST, GraphQL ve gRPC aynı problemi çözmez. Üçü de "istemci ile sunucu arasında veri taşıma" işini yapar, ancak...

REST, GraphQL ve gRPC: API Tasarım Rehberi

API Tasarımında Üç Temel Yaklaşım

REST, GraphQL ve gRPC aynı problemi çözmez. Üçü de "istemci ile sunucu arasında veri taşıma" işini yapar, ancak bunu farklı varsayımlarla yapar. Doğru seçim, hangisinin "daha iyi" olduğuna değil, hangi kısıtların sizin için baskın olduğuna bağlıdır: istemci çeşitliliği, veri şekli, gecikme bütçesi, ekip alışkanlıkları ve tarayıcı desteği.

Bu rehber, üç yaklaşımı aynı kavramlar üzerinden karşılaştırır ve seçim yaparken hangi soruları sormanız gerektiğini somutlaştırır. Sürüme bağlı ayrıntılardan kaçınıldı; HTTP/2, protobuf ve GraphQL şeması gibi olgun standartlar üzerinden konuşuluyor.

Ortak Zemin: Hepsi HTTP Üzerinden Konuşur (Çoğunlukla)

Üçü de tipik olarak HTTP kullanır, ancak kullandıkları katman farklıdır:

  • REST, HTTP'nin semantiğini (metotlar, durum kodları, başlıklar) birinci sınıf vatandaş olarak kullanır.
  • GraphQL, çoğunlukla tek bir POST uç noktası üzerinden çalışır; HTTP'yi taşıma katmanı olarak görür.
  • gRPC, HTTP/2'yi taşıma olarak kullanır ve protobuf ile tanımlanmış RPC çağrıları yapar. Tarayıcıdan doğrudan kullanım için gRPC-Web gibi bir köprü gerekir.

Bu fark, karşılaştırmanın çoğunu açıklar.

REST: Kaynak Odaklı Tasarım

REST'te model, kaynaklardır. Her kaynağın bir URL'si vardır ve işlemler HTTP metotlarıyla ifade edilir.

Tipik bir kaynak tasarımı:

GET    /users/42
GET    /users/42/orders?status=shipped
POST   /users
PATCH  /users/42
DELETE /users/42

Beklenen davranış nettir: GET güvenli ve yan etkisiz olmalı, PUT/PATCH gövdeyle kaynağı güncellemeli, DELETE idempotent olmalıdır. Durum kodları anlam taşır: 200, 201, 204, 400, 401, 403, 404, 409, 422, 429, 500.

Güçlü yanları:

  • HTTP önbellekleme (ETag, Cache-Control) doğal olarak çalışır.
  • Tarayıcı, CDN, proxy ve API gateway'ler varsayılan olarak uyumludur.
  • Öğrenme eğrisi düşüktür; ekip değişimi kolaydır.

Zayıf yanları:

  • İstemci ihtiyacı değiştiğinde ya çok veri gelir (over-fetching) ya da birden fazla istek gerekir (under-fetching).
  • İlişkili veriler için istemci tarafında birleştirme yapmak gerekir.
  • Şema sözleşmesi çoğu zaman dışarıda tutulur (OpenAPI gibi bir araçla belgelenmedikçe).

Yaygın hatalar:

  • Fiilleri URL'ye gömmek (/getUserById), kaynak modelini bozar.
  • GET isteğinde yan etki üretmek (önbellek ve retry davranışını bozar).
  • Toplu işlemler için POST /users/bulk-delete gibi kaynak dışı uç noktalar açmak; bunun yerine bir "iş" (job) kaynağı modellemek daha temizdir.

GraphQL: Şema Odaklı Sorgu Dili

GraphQL'de istemci ne istediğini tek bir sorguda tanımlar. Sunucu, şemada tanımlı alanları çözer.

query {
  user(id: "42") {
    name
    orders(status: SHIPPED) {
      id
      total
    }
  }
}

Sunucu tarafındaki şema, sözleşmedir:

type User {
  id: ID!
  name: String!
  orders(status: OrderStatus): [Order!]!
}

type Order {
  id: ID!
  total: Float!
  status: OrderStatus!
}

enum OrderStatus { PENDING SHIPPED DELIVERED }

Güçlü yanları:

  • İstemci tam ihtiyacı kadar veri alır; over/under-fetching sorunu ortadan kalkar.
  • Tek uç nokta, çok farklı istemci profilleri (mobil, web, TV) için uygundur.
  • Şema, dokümantasyon ve tip güvenliği üretir (codegen araçları).

Zayıf yanları:

  • HTTP önbellekleme doğrudan çalışmaz; çoğu zaman uygulama katmanında çözüm gerekir.
  • Karmaşık sorgular sunucuda pahalı olabilir; derinlik ve maliyet sınırlaması şarttır.
  • N+1 problemi çözümleyici (resolver) tasarımında kolayca ortaya çıkar; DataLoader benzeri bir toplu yükleme mekanizması gerekir.

Güvenlik notları:

  • Derinlik (depth) ve karmaşıklık (complexity) limitleri olmadan bir istemci sunucuyu kolayca zorlayabilir.
  • Tek uç nokta, yetkilendirmeyi alan bazında yapmayı gerektirir; alan seviyesinde yetki kontrolü unutulursa veri sızabilir.
  • Sorgu içeriğini loglamak yararlıdır, ancak hassas alanların loglanmamasına dikkat edin.

gRPC: Sözleşme Odaklı RPC

gRPC, servisler arası iletişim için tasarlanmıştır. Şema .proto dosyasıdır; mesajlar protobuf ile serileştirilir; taşıma HTTP/2'dir.

syntax = "proto3";

service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc ListOrders (ListOrdersRequest) returns (stream Order);
}

message GetUserRequest {
  string id = 1;
}

message User {
  string id = 1;
  string name = 2;
}

message ListOrdersRequest {
  string user_id = 1;
}

message Order {
  string id = 1;
  double total = 2;
}

Güçlü yanları:

  • İkili (binary) protobuf, JSON'a göre daha küçük ve hızlıdır.
  • HTTP/2 üzerinden çoklama (multiplexing), akış (streaming) ve başlık sıkıştırma sağlar.
  • Kod üretimi (codegen) ile istemci ve sunucu tipleri otomatik üretilir; sözleşme kayması azalır.
  • Servisler arası iç iletişimde gecikme ve bant genişliği avantajı belirgindir.

Zayıf yanları:

  • Tarayıcıdan doğrudan kullanılamaz; gRPC-Web veya bir proxy gerekir.
  • İnsan tarafından okunabilirliği düşüktür; hata ayıklama için özel araçlar gerekir.
  • Şema değişikliklerinde geriye dönük uyumluluk kurallarına (alan numaralarını yeniden kullanmama, silinen alanları reserved işaretleme) dikkat edilmelidir.

Yaygın hatalar:

  • Var olan bir alanın numarasını yeni bir alan için yeniden kullanmak; bu, eski istemcilerde sessiz veri bozulmasına yol açar.
  • optional/required semantiğini proto3'te yanlış varsaymak.
  • Büyük mesajları tek çağrıda göndermeye çalışmak; akış (streaming) yerine tek seferlik çağrı kullanmak.

Karşılaştırma Tablosu

Kriter REST GraphQL gRPC
Sözleşme OpenAPI (opsiyonel) Şema (zorunlu) .proto (zorunlu)
Taşıma HTTP/1.1 veya 2 HTTP (genelde POST) HTTP/2
Serileştirme JSON (yaygın) JSON Protobuf
Tarayıcı desteği Doğal Doğal gRPC-Web/proxy
Önbellekleme HTTP düzeyinde Uygulama düzeyinde Uygulama düzeyinde
Akış Sınırlı (SSE, chunked) Abonelikler Birinci sınıf
Kod üretimi Araçlara bağlı Şemadan Şemadan
Tipik kullanım Genel API, CRUD Çok istemcili BFF Servisler arası

Seçim İçin Sorulacak Sorular

  1. İstemci kim? Tarayıcı ve üçüncü taraflar mı, yoksa kendi servisleriniz mi? Kendi servisleriniz arasında gRPC genelde net kazanç sağlar.
  2. Veri şekli sabit mi? İstemciye göre değişiyorsa GraphQL, sabit ve kaynak odaklıysa REST uygundur.
  3. Önbellek kritik mi? Genel içerik, CDN ve HTTP önbelleği önemliyse REST doğal seçimdir.
  4. Akış gerekli mi? Gerçek zamanlı, iki yönlü akış gerekiyorsa gRPC akışları güçlü bir seçenektir.
  5. Ekip hangi araçlara hâkim? Öğrenme maliyeti gerçek bir maliyettir; sırf moda olduğu için GraphQL veya gRPC'ye geçmek projeyi yavaşlatır.

Birlikte Kullanım

Bu üç yaklaşım birbirinin yerine geçmek zorunda değil. Yaygın bir düzen:

  • Dış API: REST (geniş uyumluluk, önbellek, üçüncü taraf entegrasyonu).
  • İstemci katmanı (BFF): GraphQL (mobil ve web'in farklı veri ihtiyaçları).
  • Servisler arası: gRPC (düşük gecikme, güçlü sözleşme).

Bu düzende her katman, kendi kısıtlarına uygun teknolojiyi kullanır; tek bir yaklaşımı her yere zorlamak genelde daha pahalıdır.

Ortak Güvenlik ve Operasyon Notları

  • Kimlik doğrulama: Üç yaklaşımda da token veya oturum tabanlı kimlik doğrulama kullanılabilir; ancak GraphQL'de alan bazlı yetkilendirme, gRPC'de metadata üzerinden yetki taşıma ayrıca ele alınmalıdır.
  • Hız sınırlama: REST'te uç nokta bazında, GraphQL'de sorgu karmaşıklığı bazında, gRPC'de metot bazında düşünün.
  • Gözlemlenebilirlik: REST ve gRPC için HTTP durum kodları ve süreler doğal metriklerdir; GraphQL'de hata HTTP 200 içinde dönebildiği için ayrı hata metrikleri gerekir.
  • Sürümleme: REST'te URL veya başlıkla, GraphQL'de şema evrimiyle (alan ekleme, @deprecated), gRPC'de proto alan numaralarının korunmasıyla yapılır.
  • Hata modeli: Her üç yaklaşımda da tutarlı bir hata gövdesi tanımlamak, istemci tarafını basitleştirir.

Sonuç

REST, GraphQL ve gRPC farklı problemleri çözer. REST kaynak ve HTTP semantiği etrafında, GraphQL istemci ihtiyaçları etrafında, gRPC sözleşme ve performans etrafında şekillenir. Seçim yaparken "hangisi daha modern" değil, "hangi kısıtlar benim için baskın" sorusunu sorun. Çoğu sistemde en sağlam çözüm, katmanlara göre bu üçünü birlikte kullanmaktır.

İLGİLİ İÇERİKLER

Bunları da Okumak İsteyebilirsiniz