GraphQL Nedir ve Nasıl Çalışır?

GraphQL, veri sorgulama ve manipülasyonunu kolaylaştırmak için kullanılan bir sorgulama dilidir. GraphQL’in temel amacı, istemci tarafından ihtiyaç duyulan verilerin spesifik olarak talep edilmesini sağlamaktır. Bu sayede gereksiz veri aktarımları önlenir ve istemciye sadece ihtiyaç duyduğu veriler sunulur.

GraphQL Temel Bileşenleri

GraphQL, şu temel bileşenlere sahiptir:

1. Sorgular (Queries)

Sorgular, sunucudan veri almak için kullanılır. İstemci, belirli bir şekilde şekillendirilmiş bir sorgu yaparak, sadece ihtiyaç duyduğu verileri alabilir. Sorgu, belirli bir veri tipine ait bir alanın ve alt alanların taleplerini içerir.

Örnek bir GraphQL sorgusu:

1
2
3
4
5
6
7
8
9
10
query {
user(id: 123) {
name
email
posts {
title
content
}
}
}

Bu sorgu, sunucudan kullanıcı adı, e-posta ve kullanıcının yazılarının başlık ve içeriklerini getirecektir.

2. Mutasyonlar (Mutations)

Mutasyonlar, sunucuda veri değişiklikleri yapmak için kullanılır. Veri ekleme, güncelleme veya silme gibi işlemleri gerçekleştirmek için kullanılır. Bir mutasyon, bir işlem adını ve ilgili verileri içerir.

Örnek bir GraphQL mutasyonu:

1
2
3
4
5
6
7
mutation {
createUser(name: "John", email: "john@example.com", password: "123456") {
id
name
email
}
}

Bu mutasyon, sunucuda yeni bir kullanıcı oluşturacak ve oluşturulan kullanıcının kimlik bilgilerini geri döndürecektir.

3. Şematik Tanımlama (Schema Definition Language - SDL)

GraphQL, bir şema tanımlama dili olan SDL’yi kullanır. Şema, mevcut veri tiplerini, ilişkileri ve izin verilen sorgu ve mutasyonları belirtir. Şema, hem sunucu tarafında hem de istemci tarafında veri taleplerini

yaparken kullanılır.

Örnek bir GraphQL şeması:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}

type Post {
id: ID!
title: String!
content: String!
author: User!
}

type Query {
user(id: ID!): User
post(id: ID!): Post
}

type Mutation {
createUser(name: String!, email: String!, password: String!): User
createPost(title: String!, content: String!, authorId: ID!): Post
}

Bu örnekte, User ve Post adında iki veri tipi tanımlanmıştır. Query ve Mutation ise sırasıyla sorgu ve mutasyon işlemlerini tanımlar.

GraphQL vs. REST

API (Application Programming Interface), yazılım sistemlerinin iletişim kurmalarını sağlayan bir arayüzdür. RESTful API’lar ve GraphQL, günümüzde en popüler API türleri arasında yer alır. Her ikisi de veri alışverişi için kullanılırken, farklı yaklaşımlar ve özellikler sunarlar. Bu bölümde, GraphQL ve REST arasındaki farklara daha detaylı bir şekilde değineceğiz.

RESTful API

REST (Representational State Transfer), dağıtılmış sistemler arasında kaynaklara erişim için kullanılan bir mimari stildir. RESTful API’lar, HTTP protokolü üzerinden kaynakları temsil eden URL’ler aracılığıyla iletişim kurar. REST, şu ana ilkeler üzerine kuruludur:

  1. Kaynak Merkezlilik: Her kaynak, benzersiz bir URL ile temsil edilir ve HTTP metotları (GET, POST, PUT, DELETE) kullanılarak işlemler gerçekleştirilir.

  2. Durumsuzluk: Sunucu, istemciden gelen her isteği bağımsız olarak işler ve istemcinin durumu tutmaz. Her istek, gerekli tüm bilgileri içermelidir.

  3. Önbellekleme: RESTful API’lar, sunucu ve istemci arasında önbellekleme yapılmasına olanak tanır. İstemci, bir kaynağı alırken veya değiştirirken, ilgili önbelleğin güncellenmesi gerekip gerekmediğini belirtir.

  4. Birlikte Sözleşme (Contract First): API, birlikte kullanılan bir sözleşme olan HTTP metotlarını ve durum kodlarını kullanır. Bu sayede, sunucu ve istemci arasında anlaşma sağlanır.

RESTful API’lar genellikle JSON veya XML formatında veri döndürür. İstemci, belirli bir kaynağa HTTP metotlarını kullanarak istek gönderir ve sunucu, ilgili durum kodunu ve yanıt verisini döndürür.

GraphQL

GraphQL, Facebook tarafından geliştirilen bir sorgulama dilidir ve RESTful API’ların bazı sınırlamalarını aşmak için tasarlanmıştır. GraphQL’in temel özellikleri şunlardır:

  1. Esnek Veri Talepleri: GraphQL, istemcilerin ihtiyaç duydukları verileri spesifik olarak talep etmelerine olanak tanır. İstemci, sadece istediği alanları ve ilişkili verileri belirterek sunucudan almak istediği veri miktarını kontrol edebilir. Bu sayede, gereksiz veri aktarımı ve ağ trafiği azalır.

  2. Tek Bir Endpoint: GraphQL, tek bir endpoint üzerinden veri taleplerini yönetir. İstemci, tüm veri ihtiyaçlarını tek bir istekte birleştirebilir. Böylece, birden fazla RESTful API endpointine ihtiyaç duymadan verilere erişebilir.

  3. Şematik Tanımlama: GraphQL, bir şema tanımlama dili olan SDL’yi kullanır. Şema, mevcut veri tiplerini, ilişkileri ve izin verilen sorgu ve mutasyonları belirtir. Şematik tanımlama, istemciye hangi verileri talep edebileceğini ve nasıl kullanabileceğini net bir şekilde gösterir.

  4. Strong Typing: GraphQL, verilerin tipini güçlü bir şekilde belirtir. Şemada tanımlanan veri tipleri, istemcinin hangi verilere erişebileceğini ve nasıl kullanabileceğini belirler. Bu, hataların erken tespit edilmesine ve veri bütünlüğünün sağlanmasına yardımcı olur.

GraphQL, RESTful API’larla karşılaştırıldığında daha esnek bir veri alışverişi sağlar. İstemciler, sadece ihtiyaç duydukları verileri talep ederken sunucu, sadece bu talepleri yerine getirir. Bu sayede, gereksiz veri alışverişi ve ağ trafiği azalırken, istemci tarafında performans artırılır.

NodeJS İle GraphQL Uygulaması

Proje Kurulumu

Öncelikle, Node.js ve npm’i bilgisayarınıza kurmanız gerekmektedir. Bu adımları tamamladıktan sonra yeni bir Node.js projesi oluşturarak gerekli bağımlılıkları yükleyin. Bu adımları takip etmek için aşağıdaki komutları kullanabilirsiniz:

1
2
3
4
$ mkdir nodejs-graphql-api
$ cd nodejs-graphql-api
$ npm init -y
$ npm install express graphql express-graphql

İlk olarak, bir proje klasörü oluşturuyoruz ve bu klasöre geçiyoruz. Ardından, npm init -y komutunu kullanarak bir package.json dosyası oluşturuyoruz. Bu dosya, proje bağımlılıklarını ve diğer ayarları içerir. Son olarak, npm install komutuyla gerekli bağımlılıkları yükleyin. Bu projede, Express, GraphQL ve express-graphql paketlerini kullanacağız.

GraphQL Schema Oluşturma

Şimdi, GraphQL şemamızı oluşturmak için schema.graphql adında bir dosya oluşturalım. Bu dosya, API’nin kullanacağı veri modellerini ve şema tanımlarını içerecektir. Örneğimizde, Movie adında bir veri modelimiz olacak. Her film, id, title, director ve year alanlarına sahip olacak. Ayrıca, sorgu ve mutasyon tipleri için de şema tanımları yapacağız.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type Movie {
id: ID!
title: String!
director: String!
year: Int!
}

type Query {
movie(id: ID!): Movie
movies: [Movie]
}

type Mutation {
addMovie(title: String!, director: String!, year: Int!): Movie
updateMovie(id: ID!, title: String, director: String, year: Int): Movie
}

Bu şemada, Movie adında bir tip tanımladık. Bu tip, her bir film için gerekli olan alanları içerir. Ardından, Query tipiyle sorgu işlemlerini tanımladık. movie alanı, belirli bir filmi ID’ye göre sorgulamak için kullanılırken, movies alanı tüm filmleri döndürmek için kullanılır. Son olarak, Mutation tipiyle mutasyon işlemlerini tanımladık. addMovie alanı yeni bir film eklemek için kullanılırken, updateMovie alanı mevcut bir filmin bilgilerini güncellemek için kullanılır.

Express ve GraphQL Kullanarak API’nin Oluşturulması

API’yi oluşturmak için index.js adında bir dosya oluşturalım. Bu dosya, Express ve GraphQL kullanarak API’yi oluşturacak olan kodları içerecektir. İlk olarak, gerekli paketleri import edelim ve şemayı oluşturalım.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

// GraphQL Schema
const schema = buildSchema(`
type Movie {
id: ID!
title: String!
director: String!
year: Int!
}

type Query {
movie(id: ID!): Movie
movies: [Movie]
}

type Mutation {
addMovie(title: String!, director: String!, year: Int!): Movie
updateMovie(id: ID!, title: String, director: String, year: Int): Movie
}
`);

Bu kısımda, Express ve express-graphql paketlerini import ediyoruz. Ardından, buildSchema fonksiyonunu kullanarak şemayı oluşturuyoruz. Şemada, Movie tipi için alanları ve Query ile Mutation tipleri için işlemleri tanımlıyoruz.

Şema oluşturulduktan sonra, film verilerini tanımlayalım. Bu örnekte, basitçe birkaç film verisi oluşturacağız. Bu veriler, API üzerinden sorgulanabilecek film örneklerini temsil edecek.

1
2
3
4
5
// Movie Datas
const movies = [
{ id: '1', title: 'The Lord of the Rings: The Fellowship of the Ring', director: 'Peter Jackson', year: 2001 },
{ id: '2', title: 'The Shawshank Redemption', director: 'Frank Darabont', year: 1994 },
];

Daha sonra, resolver fonksiyonlarını tanımlayalım. Bu fonksiyonlar, sorgu ve mutasyon işlemlerini gerçekleştirecek kodları içerecektir. Resolver fonksiyonları, şemada tanımlanan alanlarla eşleşen fonksiyonlardır.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Resolver Functions
const root = {
movie: ({ id }) => movies.find(movie=> movie.id === id),
movies: () => movies,
addMovie: ({ title, director, year }) => {
const newMovie = { id: movies.length + 1, title, director, year };
movies.push(newMovie);
return newMovie;
},
updateMovie: ({ id, title, director, year }) => {
const movieIndex = movies.findIndex(movie=> movie.id === id);
if (movieIndex === -1) throw new Error('Film bulunamadı');
const updateMovie = { ...movies[movieIndex], title, director, year };
movies[movieIndex] = updateMovie;
return updateMovie;
},
};

Sorgu ve mutasyon işlemleri için gerekli olan resolver fonksiyonlarını tanımladık. movie fonksiyonu, belirli bir filmi ID’ye göre bulmak için kullanılırken, movies fonksiyonu tüm filmleri döndürmek için kullanılır. addMovie fonksiyonu yeni bir film eklemek için kullanılırken, updateMovie fonksiyonu mevcut bir filmin bilgilerini güncellemek için kullanılır.

Son olarak, Express uygulamasını oluşturup GraphQL middleware’i ekleyelim ve sunucuyu dinlemeye başlayalım.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const app = express();

// GraphQL Middleware
app.use(
'/graphql',
graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
})
);

// Listen Server
app.listen(3000, () => {
console.log('API run on port :3000. API Url : http://localhost:3000/graphql');
});

Express uygulamasını oluşturuyoruz. Ardından, /graphql endpoint’i üzerinden GraphQL middleware’ini ekliyoruz. Bu middleware, oluşturduğumuz şema (schema), resolver fonksiyonları (rootValue) ve GraphiQL arayüzünü (graphiql: true) kullanarak API’yi oluşturur.

Son olarak, sunucuyu belirtilen port üzerinden dinlemeye başlıyoruz.

API’ye Erişim

API’yi başarıyla oluşturduktan sonra, tarayıcınızdan http://localhost:3000/graphql adresine giderek API’ye erişebilirsiniz. GraphiQL arayüzünü göreceksiniz ve buradan örnek sorguları ve mutasyonları deneyebilirsiniz.

Örnek sorgu: Tüm filmleri almak için:

1
2
3
4
5
6
7
8
query {
movies {
id
title
director
year
}
}

Örnek mutasyon: Yeni bir film eklemek için:

1
2
3
4
5
6
7
8
mutation {
addMovie(title: "Inception", director: "Christopher Nolan", year: 2010) {
id
title
director
year
}
}

Bu örnekler, API’nin nasıl kullanıldığını göstermektedir. İstediğiniz sorguları ve mutasyonları deneyebilir ve API’nin sonuçlarını gözlemleyebilirsiniz.

Bu proje, Node.js ve GraphQL’in birlikte nasıl kullanıldığını göstermektedir. Express ile GraphQL’in entegrasyonu, API’lerin hızlı bir şekilde oluşturulmasını sağlar. GraphQL’in esnekliği sayesinde istemciler, ihtiyaç duydukları verileri özelleştirebilirler.

Projeye Github Üzerinden Erişim

Projeye ait kodları indirmek ve incelemek isterseniz Node.js GraphQL Example adresi üzerinden Github reposuna ulaşabilirsiniz.

Sonuç

GraphQL, istemcilerin ihtiyaç duydukları verileri daha etkili bir şekilde almasını sağlayan güçlü bir sorgulama dilidir. RESTful API’larla karşılaştırıldığında daha esnek ve verimlidir. Sorgular, mutasyonlar ve şematik tanımlama gibi temel bileşenlerle birlikte kullanılır. GraphQL, geliştiricilere veri taleplerinde daha fazla kontrol sağlar ve istemcilerin performansı artırırken veri alışverişini optimize etmelerine olanak tanır.

Bu blog yazısında, GraphQL’in ne olduğunu ve nasıl çalıştığını ayrıntılı bir şekilde ele aldık. Ayrıca, GraphQL sunucusu oluşturmak ve istemcilerle iletişim kurmak için kullanılan araçlardan bahsettik ve bir NodeJS ile GraphQL örneği yazdık.

Faydalı olması dileğiyle.