GraphQL Tam Rehberi: Yüksek Performanslı Hosting’de Daha Hızlı, Daha Akıllı API’ler Oluşturun
GraphQL, Facebook’un mühendislik ekipleri içinde 2012’de doğmuş ve 2015’te açık kaynak topluluğuna yayınlanmış olan, modern web geliştirmede en yaygın olarak benimsenen API sorgu dillerinden biri haline gelmiştir. Gerçek zamanlı bir sohbet uygulaması, veri yoğun bir pano veya katı bant genişliği kısıtlamalarına sahip mobil-ilk bir ürün oluşturuyor olsanız da, GraphQL size tel üzerinden geçen verilerin tam olarak ne olduğu konusunda cerrahi kontrol sağlar.
Bu kapsamlı kılavuzda, GraphQL’nin ne olduğunu, neden birçok senaryoda geleneksel REST API’lerinden daha iyi performans gösterdiğini, ilk GraphQL sunucunuzu nasıl kuracağınızı ve bunu üretim iş yüklerinin taleplerini karşılayabilen altyapıya nasıl dağıtacağınızı öğreneceksiniz.
İçindekiler
- GraphQL Nedir?
- GraphQL vs. REST: Neden Önemlidir
- GraphQL’nin Temel Özellikleri
- GraphQL Sunucusu Kurulumu
- Şemanızı Tanımlama
- Çözücüleri Uygulama
- Verileri Sorgulama ve Değiştirme
- Aboneliklerle Gerçek Zamanlı Güncellemeler
- GraphQL İçgözlem ve Geliştirici Araçları
- GraphQL’yi Üretimde Dağıtma
- Güvenlik En İyi Uygulamaları
- Sonuç
1. GraphQL Nedir? {#what-is-graphql}
GraphQL, API’ler için açık kaynak bir sorgu dilidir ve bu sorguları verilerinize karşı yürütmek için bir çalışma zamanıdır. Her biri önceden belirlenmiş bir veri yapısını döndüren sabit bir uç nokta kümesini ortaya çıkaran REST’in aksine, GraphQL, istemcilerin ihtiyaç duydukları alanları ve ilişkileri tam olarak talep edebileceği tek bir uç nokta ortaya çıkarır — ne daha fazla, ne daha az.
Bu yaklaşım, REST API tasarımında en kalıcı iki sorunu ortadan kaldırır:
- Aşırı getirme — istemcinin gerçekten ihtiyaç duyduğundan çok daha fazla veri almak, bant genişliğini ve işleme süresini boşa harcamak.
- Yetersiz getirme — tek bir istekte çok az veri almak, istemciyi tam bir resim oluşturmak için birden fazla takip çağrısı yapmaya zorlayarak.
GraphQL ile, istemci yanıtın şeklini belirler. Sunucu şema tarafından tanımlanan sözleşmeyi yerine getirir ve istemci yalnızca kullanmayı amaçladığı şeyi ister.
2. GraphQL vs. REST: Neden Önemlidir {#graphql-vs-rest}
GraphQL’yi REST yerine ne zaman seçeceğinizi anlamak — ve bunun tersi — sağlam mimari kararlar almak için kritiktir.
| Boyut | REST | GraphQL |
|---|---|---|
| Uç noktalar | Çoklu (kaynak başına bir) | Tek birleşik uç nokta |
| Veri getirme | Sabit yanıt yapısı | İstemci tarafından belirtilen alanlar |
| Aşırı getirme | Yaygın | Tasarım gereği ortadan kaldırılmış |
| Yetersiz getirme | Yaygın (N+1 sorunu) | İç içe sorgularla çözülmüş |
| Sürüm oluşturma | URL veya başlık sürüm oluşturması gerekli | Sürüm oluşturmadan şema evrimi |
| Gerçek zamanlı destek | WebSockets veya yoklama gerektirir | Yerel abonelikler |
| Tür sistemi | İsteğe bağlı (OpenAPI/Swagger) | Yerleşik, zorunlu şema |
| Önbelleğe alma | HTTP düzeyinde önbelleğe alma basit | Sorgu farkında önbelleğe alma gerektirir |
GraphQL özellikle şu durumlarda güçlüdür:
- Karmaşık, birbirine bağlı veri modelleri burada tek bir görünüm birden fazla kaynaktan veri gerektirir.
- Mobil uygulamalar burada yük boyutunu en aza indirmek doğrudan kullanıcı deneyimini iyileştirir ve veri maliyetlerini azaltır.
- Hızlı ürün yinelemesi burada ön uç ekipleri arka uç API değişiklikleri için beklemeden veri gereksinimlerini geliştirmeleri gerekir.
- Mikro hizmetler toplaması burada bir GraphQL ağ geçidi birden fazla aşağı akış hizmetini birleşik bir API yüzeyine diker.
REST, basit CRUD API’leri, öngörülebilir HTTP semantiklerinden yararlanan üçüncü taraflar tarafından tüketilen genel API’ler ve HTTP düzeyinde önbelleğe almanın zor bir gereklilik olduğu senaryolar için sağlam bir seçim olmaya devam eder.
3. GraphQL’nin Temel Özellikleri {#key-features}
3.1 Kesin Veri Getirme
GraphQL’nin tanımlayıcı özelliği, istemcilerin veri gereksinimlerini sorgunun kendisinde bildirmeleridir. Tek bir uç noktaya yapılan tek bir istek, yalnızca istemcinin belirttiği alanlar doldurulmuş yanıtta ilgili nesnelerin derin bir şekilde iç içe geçmiş bir grafiğini alabilir.
Bu, birden fazla platform — web, iOS, Android, akıllı TV — arasında ürünler oluşturan ekipler için dönüştürücüdür; burada her yüzey farklı veri gereksinimlerine sahiptir. Ayrı REST uç noktaları korumak veya şişirilmiş yükleri kabul etmek yerine, her istemci uyarlanmış bir sorgu gönderir ve uyarlanmış bir yanıt alır.
3.2 Güçlü Şekilde Yazılan Şema
Her GraphQL API, GraphQL Şema Tanım Dili (SDL) ile yazılmış bir şema tarafından desteklenir. Şema, sunucu ile onu tüketen her istemci arasındaki yetkili sözleşmedir. Şu tanımlar:
- Türler — veri modelinizdeki her nesnenin şekli.
- Sorgular — istemcilerin gerçekleştirebileceği okuma işlemleri.
- Mutasyonlar — yazma işlemleri (oluştur, güncelle, sil).
- Abonelikler — gerçek zamanlı olay akışları.
- İlişkiler — türlerin birbirlerine nasıl başvurduğu.
Şema güçlü bir şekilde yazıldığından, tüm hata kategorileri üretimde değil geliştirme zamanında yakalanır. Araçlar, sorguları hiç yürütülmeden önce şemaya karşı doğrulayabilir ve IDE’ler doğru otomatik tamamlama ve satır içi belgeler sağlayabilir.
3.3 Aboneliklerle Gerçek Zamanlı Güncellemeler
GraphQL’nin abonelik mekanizması, kalıcı, olay odaklı bağlantılar istemci ve sunucu arasında etkinleştirir — tipik olarak WebSockets üzerinden uygulanır. Sunucuda abone olunan bir olay meydana geldiğinde (yeni bir ileti gönderilir, bir hisse senedi fiyatı değişir, bir sipariş durumu güncellenir), sunucu ilgili verileri tüm abone istemcilere hemen gönderir.
Bu, GraphQL’yi şu durumlarda doğal bir seçim yapar:
- Canlı sohbet ve mesajlaşma uygulamaları
- İşbirlikçi düzenleme araçları
- Canlı pazar verileriyle finansal panolar
- Gerçek zamanlı bildirimler ve etkinlik akışları
- Çok oyunculu oyun durumu senkronizasyonu
3.4 İçgözlem
GraphQL API’leri tasarım gereği kendi kendini belgeleyen. İçgözlem sistemi, istemcilerin şemayı kendisini sorgulamasına izin verir — çalışma zamanında kullanılabilir türleri, alanları, sorguları, mutasyonları ve açıklamalarını keşfeder. Bu yetenek, GraphiQL ve Apollo Studio gibi geliştirici araçlarını güçlendirir; bu araçlar, API yazarından herhangi bir ek çaba olmadan etkileşimli API kaşifleri, sorgu oluşturucuları ve otomatik belge oluşturma sağlar.
3.5 Sürüm Oluşturmadan Şema Evrimi
GraphQL’nin en pratik olarak değerli yönlerinden biri, değişimi ne kadar zarif bir şekilde işlediğidir. İstemciler yalnızca ihtiyaç duydukları alanları talep ettiğinden, şemaya yeni alanlar ve türler ekleyebilirsiniz mevcut istemcileri bozmadan. Eski alanları kullanımdan kaldırmak, URL sürüm oluşturması yerine şema ek açıklamaları aracılığıyla işlenir; API yüzeyinizi temiz ve istemcilerinizi kararlı tutar.
4. GraphQL Sunucusu Kurulumu {#setting-up}
GraphQL dilden bağımsızdır. Olgun sunucu kitaplıkları tüm teknoloji yığını arasında mevcuttur. İşte en yaygın olarak kullanılan seçenekler:
| Dil / Çalışma Zamanı | Kitaplık / Çerçeve |
|---|---|
| Node.js | Apollo Server, GraphQL Yoga, Express-GraphQL |
| Python | Strawberry, Graphene |
| Java | Spring for GraphQL, graphql-java |
| Go | gqlgen, graphql-go |
| Ruby | graphql-ruby |
| PHP | Lighthouse (Laravel), webonyx/graphql-php |
| Rust | async-graphql |
| .NET / C# | Hot Chocolate, GraphQL.NET |
Adım Adım: Node.js ile Apollo Server
Apollo Server, Node.js ekosisteminde en yaygın olarak dağıtılan GraphQL sunucusudur. Aşağıdaki izlenecek yol sizi sıfırdan çalışan bir sunucuya götürür.
Ön koşullar:
- Node.js 18 veya sonrası yüklü
- npm veya yarn paket yöneticisi
Adım 1: Projenizi başlatın
mkdir graphql-api && cd graphql-api
npm init -y
npm install @apollo/server graphqlAdım 2: Sunucu dosyanızı oluşturun
index.js adlı bir dosya oluşturun (veya ES modülleri için index.mjs):
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// Step 1: Define your type definitions (schema)
const typeDefs = `#graphql
type Book {
id: ID!
title: String!
author: String!
publishedYear: Int
genre: String
}
type Query {
books: [Book!]!
book(id: ID!): Book
}
`;
// Step 2: Define your data source (in-memory for this example)
const books = [
{
id: '1',
title: 'The Pragmatic Programmer',
author: 'David Thomas & Andrew Hunt',
publishedYear: 1999,
genre: 'Technology',
},
{
id: '2',
title: 'Clean Code',
author: 'Robert C. Martin',
publishedYear: 2008,
genre: 'Technology',
},
];
// Step 3: Define your resolvers
const resolvers = {
Query: {
books: () => books,
book: (_, { id }) => books.find((b) => b.id === id),
},
};
// Step 4: Create and start the server
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
});
console.log(`🚀 GraphQL server ready at: ${url}`);Adım 3: Sunucuyu başlatın
node index.js
# Output: 🚀 GraphQL server ready at: http://localhost:4000/Apollo Sandbox’ı açmak için tarayıcınızda http://localhost:4000/ adresine gidin — API’nizi hemen test edebileceğiniz etkileşimli bir sorgu kaşifi.
5. Şemanızı Tanımlama {#defining-schema}
Şema, her GraphQL API’sinin omurgasıdır. İyi tasarlanmış bir şemaya zaman yatırımı yapmak, uygulamanızın ömrü boyunca temettü verir.
Skaler Türler
GraphQL beş yerleşik skaler türü içerir:
Int — 32 bit işaretli tamsayı
Float — çift duyarlıklı kayan nokta
String — UTF-8 karakter dizisi
Boolean — true veya falseID — benzersiz tanımlayıcı, dize olarak seri hale getirilmişAyrıca Date, DateTime, Email, URL veya JSON gibi türler için özel skalerler tanımlayabilirsiniz.
Nesne Türleri
type Author {
id: ID!
name: String!
biography: String
books: [Book!]!
}
type Book {
id: ID!
title: String!
author: Author!
publishedYear: Int
genre: String
tags: [String!]
}! değiştiricisi boş olmayan bir alanı gösterir. [Book!]!, boş olmayan Book nesnelerinin boş olmayan bir listesi anlamına gelir.
Sorgular
type Query {
books: [Book!]!
book(id: ID!): Book
authors: [Author!]!
author(id: ID!): Author
booksByGenre(genre: String!): [Book!]!
}Mutasyonlar
type Mutation {
createBook(title: String!, authorId: ID!, genre: String): Book!
updateBook(id: ID!, title: String, genre: String): Book
deleteBook(id: ID!): Boolean!
}Giriş Türleri
Birden fazla argümana sahip mutasyonlar için, giriş türleri şemanızı temiz ve yeniden kullanılabilir tutar:
input CreateBookInput {
title: String!
authorId: ID!
publishedYear: Int
genre: String
tags: [String!]
}
type Mutation {
createBook(input: CreateBookInput!): Book!
}6. Çözücüleri Uygulama {#implementing-resolvers}
Çözücüler, şemanızdaki her alanı yerine getiren işlevlerdir. GraphQL şemasındaki her alanın bir çözücüsü olabilir. Bir alan için çözücü tanımlanmamışsa, GraphQL, üst nesnenin aynı adlı özelliğini döndüren varsayılan çözücüye geri döner.
Çözücü İmzası
fieldName: (parent, args, context, info) => valueparent— üst türün çözülmüş değeri (iç içe çözücüler için yararlı).args— sorguda alana geçirilen argümanlar.context— tüm çözücü zinciri aracılığıyla geçirilen paylaşılan nesne, tipik olarak kimliği doğrulanmış kullanıcı, veritabanı bağlantısı veya veri yükleyicileri içerir.info— sorgu yürütme hakkında meta veriler, alan adı ve şemayı içerir.
Örnek: Veritabanı ile Çözücüler
const resolvers = {
Query: {
books: async (_, __, { db }) => {
return db.collection('books').find().toArray();
},
book: async (_, { id }, { db }) => {
return db.collection('books').findOne({ _id: id });
},
},
Mutation: {
createBook: async (_, { input }, { db, user }) => {
if (!user) throw new Error('Authentication required');
const result = await db.collection('books').insertOne(input);
return { id: result.insertedId, ...input };
},
},
Book: {
// Nested resolver: fetch the author for each book
author: async (book, _, { db }) => {
return db.collection('authors').findOne({ _id: book.authorId });
},
},
};DataLoader ile N+1 Sorununu Önleme
İç içe çözücüler N+1 sorgu sorununu tetikleyebilir — 100 kitabın bir listesini getirmek ve ardından her kitabın yazarını çözmek için 100 ayrı veritabanı çağrısı yapmak. Çözüm, bir toplu işlem ve önbelleğe alma yardımcı programı olan DataLoader‘dır:
import DataLoader from 'dataloader';
// In your context factory:
const authorLoader = new DataLoader(async (authorIds) => {
const authors = await db.collection('authors')
.find({ _id: { $in: authorIds } })
.toArray();
return authorIds.map((id) => authors.find((a) => a._id === id));
});
// In your resolver:
Book: {
author: (book, _, { authorLoader }) => authorLoader.load(book.authorId),
}DataLoader, olay döngüsünün tek bir onayında tüm author aramaları tek bir veritabanı sorgusuna toplar; 100 sorguyu 1’e indirir.
7. Verileri Sorgulama ve Değiştirme {#querying-data}
Temel Sorgu
query GetAllBooks {
books {
id
title
author {
name
}
genre
}
}Argümanlarla Sorgu
query GetBook {
book(id: "1") {
title
author {
name
biography
}
publishedYear
tags
}
}Değişkenlerle Sorgu
Değişkenler sorgularınızı dinamik tutar ve enjeksiyon güvenlik açıklarını önler:
query GetBook($bookId: ID!) {
book(id: $bookId) {
title
author {
name
}
}
}{
"bookId": "1"
}Mutasyon Örneği
mutation AddBook($input: CreateBookInput!) {
createBook(input: $input) {
id
title
author {
name
}
}
}{
"input": {
"title": "Designing Data-Intensive Applications",
"authorId": "42",
"publishedYear": 2017,
"genre": "Technology"
}
}Parçalar
Parçalar, alan seçimlerini birden fazla sorgu arasında yeniden kullanmanıza izin verir:
fragment BookDetails on Book {
id
title
genre
publishedYear
}
query {
books {
...BookDetails
author {
name
}
}
}8. Aboneliklerle Gerçek Zamanlı Güncellemeler {#subscriptions}
GraphQL abonelikleri kalıcı bir bağlantı — tipik olarak WebSockets üzerinden — korur ve sunucuda belirli olaylar meydana geldiğinde istemcilere veri gönderir.
Şema Tanımı
type Subscription {
bookAdded: Book!
bookUpdated(id: ID!): Book!
}Sunucu Uygulaması (WebSockets ile Apollo Server)
npm install graphql-ws ws @graphql-tools/schemaimport { createServer } from 'http';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { PubSub } from 'graphql-subscriptions';
const pubsub = new PubSub();
const resolvers = {
Mutation: {
createBook: async (_, { input }, { db }) => {
const book = await db.collection('books').insertOne(input);
pubsub.publish('BOOK_ADDED', { bookAdded: book });
return book;
},
},
Subscription: {
bookAdded: {
subscribe: () => pubsub.asyncIterator(['BOOK_ADDED']),
},
},
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
const httpServer = createServer();
const wsServer = new WebSocketServer({ server: httpServer, path: '/graphql' });
useServer({ schema }, wsServer);İstemci Aboneliği
subscription OnBookAdded {
bookAdded {
id
title
author {
name
}
}
}9. GraphQL İçgözlem ve Geliştirici Araçları {#introspection}
GraphQL’nin içgözlem sistemi, en geliştirici dostu özelliklerinden biridir. __schema ve __type meta alanlarını sorgulayarak, istemciler ve araçlar çalışma zamanında API’nizin tam yapısını keşfedebilir.
İçgözlem Sorgusu Örneği
{
__schema {
types {
name
kind
description
}
}
}Temel Geliştirici Araçları
| Araç | Amaç |
|---|---|
| GraphiQL | Sorguları yazıp test etmek için tarayıcı içi IDE |
| Apollo Studio | Tam API yönetimi, performans izleme, şema kayıt defteri |
| Postman | Koleksiyon yönetimi ile GraphQL sorgu desteği |
| Insomnia | GraphQL desteği ile hafif API istemcisi |
| GraphQL Code Generator | Şemanızdan otomatik olarak TypeScript türleri oluşturur |
| Apollo Client DevTools | Apollo Client önbelleğinde hata ayıklama için tarayıcı uzantısı |
> Güvenlik Notu: Olası saldırganların API şemanızı ortaya çıkarmasını önlemek için üretim ortamlarında içgözlemi devre dışı bırakın. Apollo Server bunu basit hale getirir:
>
> “`javascript
> new ApolloServer({ typeDefs, resolvers, introspection: false });
> “`
10. GraphQL’yi Üretimde Dağıtma {#deploying}
GraphQL API’sini geliştirmeden üretim ortamına taşımak, altyapı, performans ve güvenilirliğe dikkatli bir şekilde dikkat etmeyi gerektirir.
Doğru Barındırma Altyapısını Seçme
GraphQL API’nizi çalıştırdığınız altyapı, performansını, güvenilirliğini ve ölçeklenebilirliğini doğrudan etkiler. Üretim iş yükleri için birkaç güçlü seçeneğiniz vardır:
VPS Barındırması çoğu GraphQL API’si için mükemmel bir başlangıç noktasıdır. Bir VPS Barındırması planı size ayrılmış kaynaklar, kök erişimi ve Node.js çalışma zamanınızı, ters proxy’nizi ve işlem yöneticinizi tam olarak ihtiyacınız gibi yapılandırma özgürlüğü verir. AlexHost VPS planları performansa duyarlı iş yükleri için oluşturulmuş ve SSD depolama ve yüksek bant genişliği bağlantısı içerir.
Adanmış Sunucular, GraphQL API’niz yüksek sorgu hacimlerini, karmaşık abonelik iş yüklerini işlediğinde veya birden fazla mikro hizmeti toplayarak bir ağ geçidi olarak hizmet ettiğinde doğru seçimdir. Bir Adanmış Sunucu ile, tüm CPU, RAM ve I/O kaynaklarına özel erişim elde edersiniz — gürültülü komşu yok, kaynak çekişmesi yok ve abonelikler için binlerce eşzamanlı WebSocket bağlantısını işlemek için ham güç.
GPU Barındırması, GraphQL API’niz makine öğrenmesi çıkarımı, gerçek zamanlı veri işleme boru hatları veya AI tarafından desteklenen özellikler için arayüz katmanı olarak hizmet ettiğinde dikkate almaya değerdir. AlexHost’tan
