API tasarımında GraphQL mi yoksa REST mi kullanmalısınız? Bu kapsamlı rehberde her iki yaklaşımın güçlü ve zayıf yönlerini, performans farklarını ve hangi senaryolarda hangisinin tercih edilmesi gerektiğini inceliyoruz.
REST API Nedir?
REST (Representational State Transfer), 2000 yılında Roy Fielding tarafından tanımlanan bir mimari stildir. HTTP protokolü üzerine kurulu, kaynak odaklı bir API tasarım yaklaşımıdır.
REST Prensipleri
- Stateless: Her istek bağımsız, sunucu state tutmaz
- Client-Server: İstemci ve sunucu ayrımı
- Cacheable: Yanıtlar cache'lenebilir
- Uniform Interface: Standart HTTP metodları
- Layered System: Katmanlı mimari desteği
REST API Örneği
# Kullanıcı listesi
GET /api/users
# Tek kullanıcı
GET /api/users/123
# Kullanıcı oluşturma
POST /api/users
Content-Type: application/json
{
"name": "Ali Yılmaz",
"email": "ali@example.com"
}
# Kullanıcı güncelleme
PUT /api/users/123
Content-Type: application/json
{
"name": "Ali Yılmaz",
"email": "ali.yilmaz@example.com"
}
# Kullanıcı silme
DELETE /api/users/123
GraphQL Nedir?
GraphQL, Facebook tarafından 2015'te açık kaynak olarak yayınlanan bir sorgu dili ve runtime'dır. İstemcinin tam olarak ihtiyaç duyduğu veriyi talep etmesine olanak tanır.
GraphQL Temel Kavramları
- Schema: API'nin tip tanımları
- Query: Veri okuma operasyonları
- Mutation: Veri yazma/güncelleme operasyonları
- Subscription: Real-time güncellemeler
- Resolver: Veri çözümleme fonksiyonları
GraphQL Schema Örneği
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
createdAt: DateTime!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
comments: [Comment!]!
}
type Query {
user(id: ID!): User
users(limit: Int, offset: Int): [User!]!
post(id: ID!): Post
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
deleteUser(id: ID!): Boolean!
}
GraphQL Query Örneği
# Sadece ihtiyaç duyulan alanları çekme
query {
user(id: "123") {
name
email
posts {
title
comments {
content
}
}
}
}
# Mutation örneği
mutation {
createUser(input: {
name: "Ali Yılmaz"
email: "ali@example.com"
}) {
id
name
}
}
Detaylı Karşılaştırma
| Kriter | REST | GraphQL |
|---|---|---|
| Veri Çekme | Sabit endpoint'ler, over/under fetching | İstemci istediği alanları seçer |
| Endpoint Sayısı | Her kaynak için ayrı endpoint | Tek endpoint (/graphql) |
| Versiyonlama | /api/v1/, /api/v2/ | Schema evrim, deprecation |
| Caching | HTTP caching (kolay) | Karmaşık (Apollo Client vb.) |
| Öğrenme Eğrisi | Düşük | Orta-Yüksek |
| Tooling | Postman, Swagger | GraphiQL, Apollo Studio |
| Real-time | WebSocket ayrı implementasyon | Subscriptions built-in |
| File Upload | Kolay (multipart/form-data) | Ek konfigürasyon gerekli |
Over-fetching ve Under-fetching Problemi
REST'te Problem
# Kullanıcı adı ve email için istek
GET /api/users/123
# Response (gereksiz veriler de geliyor)
{
"id": 123,
"name": "Ali",
"email": "ali@example.com",
"address": "...",
"phone": "...",
"birthDate": "...",
"createdAt": "...",
"updatedAt": "...",
// ... 20 alan daha
}
# Kullanıcı ve postları için 2 ayrı istek gerekli
GET /api/users/123
GET /api/users/123/posts
GraphQL'de Çözüm
# Tek istekte sadece ihtiyaç duyulan veriler
query {
user(id: "123") {
name
email
posts {
title
}
}
}
# Response (sadece istenen alanlar)
{
"data": {
"user": {
"name": "Ali",
"email": "ali@example.com",
"posts": [
{ "title": "İlk Yazım" },
{ "title": "İkinci Yazım" }
]
}
}
}
Performans Karşılaştırması
REST Avantajları
- HTTP Caching: CDN ve browser cache kolay
- Basit Sorgular: Daha az işlem yükü
- Tahmin Edilebilir: Response boyutu sabit
GraphQL Avantajları
- Tek İstek: N+1 sorgu problemi çözümü
- Daha Az Veri: Bandwidth tasarrufu
- Mobil Uygulamalar: Düşük bant genişliği için ideal
Güvenlik Konuları
REST Güvenliği
- Rate limiting kolay
- Endpoint bazlı authorization
- Input validation standart
GraphQL Güvenliği
- Query Depth Limiting: Derin sorguları engelle
- Query Complexity: Karmaşık sorguları sınırla
- Field-level Authorization: Alan bazlı yetkilendirme
- Introspection: Production'da kapat
// GraphQL Depth Limiting örneği
const depthLimit = require('graphql-depth-limit');
const server = new ApolloServer({
typeDefs,
resolvers,
validationRules: [depthLimit(5)]
});
Hangi Durumda Hangisi?
REST Tercih Edilmeli:
- Basit CRUD operasyonları
- Public API'ler (3rd party entegrasyon)
- Ağır caching gereksinimleri
- Dosya upload/download yoğun sistemler
- Microservices arası iletişim
- Küçük ekip, hızlı geliştirme
GraphQL Tercih Edilmeli:
- Karmaşık veri ilişkileri
- Mobil uygulamalar (bandwidth kritik)
- Farklı client'lar (web, mobile, TV)
- Hızlı değişen frontend gereksinimleri
- Real-time özellikler gerektiğinde
- BFF (Backend for Frontend) pattern
Popüler Framework ve Araçlar
REST
- Express.js: Node.js için minimalist framework
- FastAPI: Python async API framework
- Spring Boot: Java enterprise framework
- Laravel: PHP framework
- Swagger/OpenAPI: Dokümantasyon
GraphQL
- Apollo Server: Node.js GraphQL server
- Apollo Client: Frontend state management
- Hasura: Instant GraphQL API
- Prisma: Type-safe database client
- GraphQL Code Generator: Type generation
Hybrid Yaklaşım
Birçok modern uygulama her iki yaklaşımı birlikte kullanır:
- Public API için REST
- Frontend (SPA/Mobile) için GraphQL
- Microservices arası REST/gRPC
- BFF katmanında GraphQL aggregation
Turkuaz Ajans Yaklaşımı: Projenin gereksinimlerine göre en uygun API mimarisini seçiyoruz. Genellikle mobil uygulamalar için GraphQL, basit web projeleri için REST tercih ediyoruz. Karmaşık projelerde hybrid yaklaşım uyguluyoruz.
Sonuç
"En iyi" API yoktur, projenize en uygun API vardır. Karar verirken şunları değerlendirin:
- Ekibinizin deneyimi
- Client çeşitliliği (web, mobile, 3rd party)
- Veri yapısının karmaşıklığı
- Caching gereksinimleri
- Real-time ihtiyaçları
- Uzun vadeli bakım planları
API Tasarımı ve Backend Geliştirme
Projenize en uygun API mimarisini birlikte belirleyelim.
Backend Teklifi Al