Node.js İle Graphql Tabanlı Veri Sorgulama Arayüzü Nasıl Yapılır?

Node.js İle Graphql Tabanlı Veri Sorgulama Arayüzü Nasıl Yapılır?
Node.js İle Graphql Tabanlı Veri Sorgulama Arayüzü Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce sisteminizde Node.js'in en güncel LTS (Long Term Support) sürümünün kurulu olması gerekmektedir. Proje bağımlılıklarını yönetmek için npm veya pnpm kullanabilirsiniz. Ayrıca, GraphQL sorgularını test etmek için tarayıcı tabanlı bir arayüz olan Apollo Sandbox veya GraphQL Playground oldukça işlevseldir.

Kurulum için terminalinizi açın ve aşağıdaki komutları sırasıyla çalıştırarak proje klasörünüzü oluşturun:

mkdir graphql-node-api
cd graphql-node-api
npm init -y
npm install @apollo/server graphql

Bu adımlar, projenin temelini atar ve Apollo Server ile GraphQL kütüphanesini projenize dahil eder. Apollo Server, Node.js üzerinde çalışan en popüler ve güvenilir GraphQL sunucusu uygulamasıdır.

GraphQL Şeması (Schema) Tanımlama

GraphQL'in kalbi, verinin nasıl göründüğünü tanımlayan şemadır. Şema, API'nizin sözleşmesidir; hangi veri tiplerinin sorgulanabileceğini ve hangi işlemlerin yapılabileceğini belirtir. Aşağıdaki kod bloğunda, basit bir kullanıcı yönetimi için gerekli olan User tipini ve sorgu yapısını tanımlıyoruz.

const typeDefs = `#graphql
  type User {
    id: ID!
    username: String!
    email: String!
  }

  type Query {
    users: [User]
    user(id: ID!): User
  }
`;

Burada ID! ifadesi, alanın zorunlu (non-nullable) olduğunu belirtir. Query tipi, istemcinin veri okumak için kullanacağı giriş noktalarını temsil eder.

Çözümleyicileri (Resolvers) Yazma

Çözümleyiciler, şemada tanımlanan alanların verisini nereden ve nasıl alacağımızı belirlediğimiz fonksiyonlardır. Veritabanı veya harici bir API ile iletişim tam olarak bu noktada gerçekleşir. Aşağıdaki örnekte, statik bir veri dizisi üzerinden basit bir çözümleyici mantığı kurguluyoruz.

const users = [
  { id: '1', username: 'ahmet_yilmaz', email: 'ahmet@example.com' },
  { id: '2', username: 'ayse_demir', email: 'ayse@example.com' },
];

const resolvers = {
  Query: {
    users: () => users,
    user: (_, { id }) => users.find(user => user.id === id),
  },
};

Burada _ (alt çizgi), kullanılmayan ana nesneyi (parent) temsil eder. İkinci parametre olan { id } ise GraphQL sorgusundan gelen argümanları yakalar.

Apollo Server Kurulumu ve Başlatma

Şema ve çözümleyiciler hazır olduğuna göre, artık sunucuyu ayağa kaldırabiliriz. Apollo Server, bu iki bileşeni birleştirerek HTTP üzerinden gelen istekleri işler. Aşağıdaki kod, sunucunun yapılandırılmasını ve çalıştırılmasını gösterir.

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';

const server = new ApolloServer({ typeDefs, resolvers });

const { url } = await startStandaloneServer(server, {
  listen: { port: 4000 },
});

console.log(`Sunucu hazır: ${url}`);

Bu kod bloğu, 4000 numaralı portta bir HTTP sunucusu başlatır. Tarayıcınızda http://localhost:4000 adresine giderek GraphQL arayüzünü görebilirsiniz.

REST ve GraphQL Karşılaştırması

GraphQL'in neden tercih edildiğini anlamak için aşağıdaki tabloyu inceleyebilirsiniz:

Özellik REST API GraphQL
Veri Alma Birden fazla endpoint Tek bir endpoint
Veri Miktarı Sabit (Over-fetching riski) İstenilen kadar (Tam kontrol)
Versiyonlama v1/v2 gibi yollar Şema evrimi

Güvenlik ve Performans Optimizasyonu

Kritik Güvenlik Uyarısı: GraphQL sunucunuzu üretim ortamına (production) alırken mutlaka "Introspection" özelliğini kapatın ve derinlik sınırlaması (query depth limiting) uygulayın. Aksi takdirde, kötü niyetli kullanıcılar karmaşık sorgularla sunucunuzu yorabilir (Denial of Service - DoS).

Veritabanı işlemlerinde "N+1 problemi" ile karşılaşmamak için DataLoader kütüphanesini kullanmanız önerilir. Ayrıca, kullanıcı girişlerini doğrulamak için JWT (JSON Web Token) kullanarak çözümleyiciler içinde yetkilendirme katmanı eklemelisiniz.

Sıkça Sorulan Sorular

GraphQL sorgularında hata ayıklama nasıl yapılır?

Apollo Server, varsayılan olarak hataları detaylı bir şekilde döndürür. Geliştirme aşamasında formatError özelliğini kullanarak hataları loglayabilir ve istemciye daha anlamlı mesajlar dönebilirsiniz.

GraphQL ile dosya yükleme mümkün mü?

Evet, ancak standart GraphQL üzerinden değil, genellikle Multipart Request protokolü veya Base64 formatı ile yapılır. Büyük dosyalar için doğrudan S3 gibi bir depolama servisine yükleme yapıp URL'i GraphQL üzerinden dönmek daha performanslıdır.

N+1 problemi nedir?

Bir kullanıcı listesi çekerken, her kullanıcı için ayrı bir veritabanı sorgusu atılması durumudur. DataLoader kullanarak bu sorguları toplu (batch) hale getirip tek bir veritabanı isteğine indirebilirsiniz.

GraphQL her proje için uygun mudur?

Eğer uygulamanız çok basit bir veri yapısına sahipse ve sadece CRUD işlemleri yapıyorsanız, REST API daha hızlı geliştirilebilir. Ancak karmaşık ilişkili verilerle çalışıyorsanız GraphQL en doğru tercihtir.

Production ortamında nasıl güvenli tutarım?

HTTPS protokolünü zorunlu kılın, rate-limiting (istek sınırlama) uygulayın ve şema üzerinde hassas alanları (örneğin kullanıcı şifre hash'leri) asla dışarıya açmayın.

GraphQL Projelerinde Test Stratejileri ve Birim Testleri

GraphQL API'lerinizin kararlılığını sağlamak için sadece manuel sorgular yeterli değildir. Sunucu tarafında çözümleyicilerin (resolvers) beklenen veriyi döndürdüğünden emin olmak için otomatikleştirilmiş testler yazmalısınız. Node.js ekosisteminde Jest ve Supertest ikilisi, GraphQL endpoint'lerinizi test etmek için endüstri standardıdır.

Aşağıdaki örnek, bir sorgunun başarılı bir şekilde veri döndürüp döndürmediğini kontrol eden temel bir test senaryosunu göstermektedir:

const { ApolloServer } = require('apollo-server');
const { typeDefs, resolvers } = require('./schema');

const testServer = new ApolloServer({ typeDefs, resolvers });

test('kullanıcı sorgusu doğru veri döndürmeli', async () => {
  const GET_USER = `
    query {
      user(id: "1") {
        name
      }
    }
  `;

  const res = await testServer.executeOperation({ query: GET_USER });
  
  expect(res.errors).toBeUndefined();
  expect(res.data.user.name).toBe('Ahmet Yılmaz');
});

Bu test yapısı, şemanızda bir değişiklik yaptığınızda veya çözümleyicilerde bir hata oluştuğunda hızlıca geri bildirim almanızı sağlar. Özellikle CI/CD süreçlerinde bu tür birim testleri, üretim ortamındaki hataları minimize eder.

GraphQL Sunucularını Ölçeklendirme ve Deployment

GraphQL sunucunuzu canlı ortama taşırken, REST API'lerden farklı olarak "tek bir endpoint" üzerinden tüm trafiğin aktığını unutmamalısınız. Bu durum, yük dengeleyiciler (load balancers) ve önbellekleme stratejileri için özel yaklaşımlar gerektirir.

Performans İçin Önbellekleme Katmanları

GraphQL'de HTTP tabanlı önbellekleme (cache) yapmak zordur çünkü tüm istekler POST metoduyla yapılır. Bu sorunu aşmak için şu yöntemleri izleyebilirsiniz:

  • Persisted Queries: İstemci tarafında sorguları önceden hash'leyerek sunucuya gönderin. Bu, hem bant genişliğini azaltır hem de sunucunun sorguyu doğrulamak için harcadığı süreyi kısaltır.
  • DataLoader Kullanımı: Veritabanı sorgularını toplu (batching) hale getirerek N+1 problemini tamamen ortadan kaldırın.
  • Redis Entegrasyonu: Sıkça sorgulanan verileri Redis üzerinde tutarak veritabanı üzerindeki yükü hafifletin.

Deployment İpuçları

Node.js tabanlı GraphQL sunucunuzu dağıtırken mutlaka bir process manager (örneğin PM2) kullanın. Ayrıca, GraphQL Playground veya Apollo Sandbox gibi geliştirme araçlarını üretim ortamında NODE_ENV=production kontrolü ile devre dışı bırakmayı unutmayın:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: process.env.NODE_ENV !== 'production',
  playground: process.env.NODE_ENV !== 'production',
});

Bu yapılandırma, dışarıdan gelen kişilerin şemanızı keşfetmesini (introspection) engelleyerek uygulamanızın iç yapısını gizli tutmanıza yardımcı olur.

Sonuç

Node.js ile GraphQL tabanlı bir veri sorgulama arayüzü oluşturmak, uygulamanızın veri katmanını modernleştirmek için atılacak en büyük adımdır. Bu rehberde temel şema tanımlama, çözümleyiciler ve sunucu kurulumunu öğrendiniz. Bir sonraki adım olarak, veritabanı entegrasyonu için Prisma veya Mongoose gibi bir ORM (Object-Relational Mapping) aracı kullanarak gerçek verilerle çalışmayı deneyebilirsiniz.

Yasal Uyarı: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Uygulamanızın canlı ortam güvenliği, veri gizliliği ve yasal uyumluluğu (KVKK vb.) tamamen geliştiricinin sorumluluğundadır. Üretim ortamına geçmeden önce mutlaka profesyonel güvenlik testleri yapınız.

Bu yazıya tepkinizi paylaşın:
Mert Çelik

Kendin yap (DIY) projeleri ve teknik tamirat rehberleri konusunda uzmanım. Denenmiş ve test edilmiş yöntemlerle okuyuculara güvenilir bilgiler sunuyorum.

Yorumlar (0)

Yorum Yaz