15%

Tüm Hosting Hizmetlerinde %15 indirim

Becerilerini test et ve herhangi bir hosting planında İndirim kazan

Kodu kullanın:

Skills
Başlayın
01.11.2024
1 +1

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

  1. GraphQL Nedir?
  2. GraphQL vs. REST: Neden Önemlidir
  3. GraphQL’nin Temel Özellikleri
  4. GraphQL Sunucusu Kurulumu
  5. Şemanızı Tanımlama
  6. Çözücüleri Uygulama
  7. Verileri Sorgulama ve Değiştirme
  8. Aboneliklerle Gerçek Zamanlı Güncellemeler
  9. GraphQL İçgözlem ve Geliştirici Araçları
  10. GraphQL’yi Üretimde Dağıtma
  11. Güvenlik En İyi Uygulamaları
  12. 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.

BoyutRESTGraphQL
Uç noktalarÇoklu (kaynak başına bir)Tek birleşik uç nokta
Veri getirmeSabit yanıt yapısıİstemci tarafından belirtilen alanlar
Aşırı getirmeYaygınTasarım gereği ortadan kaldırılmış
Yetersiz getirmeYaygın (N+1 sorunu)İç içe sorgularla çözülmüş
Sürüm oluşturmaURL veya başlık sürüm oluşturması gerekliSürüm oluşturmadan şema evrimi
Gerçek zamanlı destekWebSockets veya yoklama gerektirirYerel abonelikler
Tür sistemiİsteğe bağlı (OpenAPI/Swagger)Yerleşik, zorunlu şema
Önbelleğe almaHTTP düzeyinde önbelleğe alma basitSorgu 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.jsApollo Server, GraphQL Yoga, Express-GraphQL
PythonStrawberry, Graphene
JavaSpring for GraphQL, graphql-java
Gogqlgen, graphql-go
Rubygraphql-ruby
PHPLighthouse (Laravel), webonyx/graphql-php
Rustasync-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 graphql

Adı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 false
  • ID — 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) => value
    • parent — ü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/schema
    import { 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ç
    GraphiQLSorguları yazıp test etmek için tarayıcı içi IDE
    Apollo StudioTam API yönetimi, performans izleme, şema kayıt defteri
    PostmanKoleksiyon yönetimi ile GraphQL sorgu desteği
    InsomniaGraphQL desteği ile hafif API istemcisi
    GraphQL Code GeneratorŞemanızdan otomatik olarak TypeScript türleri oluşturur
    Apollo Client DevToolsApollo 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

    15%

    Tüm Hosting Hizmetlerinde %15 indirim

    Becerilerini test et ve herhangi bir hosting planında İndirim kazan

    Kodu kullanın:

    Skills
    Başlayın