GraphQL nedir? Mülakat soruları ve cevapları. Örnek Spring boot uygulamaları.
byAli Turgut BOZKURT-
0
GraphQL, bir API sorgulama dili ve sunucusu tarafı çalışma zamanıdır. Facebook tarafından 2012 yılında geliştirildi ve 2015'te halka açıldı. REST API'lerin aksine, GraphQL, client tarafına hangi verinin döneceğini belirleme yeteneği vererek ağ verimliliğini artırır. Birçok farklı dilde sunucu tarafı implementasyonları bulunmaktadır ve Spring Boot da bunlardan biridir.
GraphQL Nedir? Rest ile GraphQL Farkları Nelerdir? - GraphQL Dersleri #1
Mehmet Seven
Java Spring Boot GraphQL API geliştirme ve GraphiQL testleri nasil yapilir, nasil kullan
Haydi Kodlayalim
GraphQL'in Temel Parçaları:
Schema: GraphQL'in en önemli parçalarından biridir. Tüm veri tiplerini, bu tipler arasındaki ilişkileri ve kullanılabilir sorgu/mutasyonları tanımlar.
Query: Bir GraphQL servisinden veri talep etmek için kullanılır.
Mutation: Veriyi değiştirmek için kullanılır, genellikle POST, PUT, PATCH veya DELETE işlemlerini temsil eder.
Resolver: Her alan için bir fonksiyondur ve bu alanın nasıl çözüleceğini belirler.
GraphQL mülakat soruları ve cevapları
* GraphQL'ın REST API'lerine göre avantajları nelerdir? Cevap: GraphQL, istemcilerin ihtiyaç duydukları tam veriyi belirtmelerine izin verir. Bu da ağ verimliliğini artırır çünkü istemciler gereksiz veri indirmek zorunda kalmazlar. GraphQL ayrıca bir çok endpoint kullanmak yerine tek bir endpoint kullanarak işlemleri daha basit ve daha verimli hale getirir. Ayrıca, GraphQL tipli bir sistemdir, bu sayede hatalar genellikle compile aşamasında bulunur.
* GraphQL'da bir Schema nedir? Cevap: Schema, GraphQL API'nin tüm tiplerini ve yeteneklerini tanımlar. Bu, istemcilerin ne tür bir bilgi alabileceklerini ve API'nın hangi veri türlerini kabul edeceğini belirtir. Bir schema ayrıca mutasyonları ve abonelikleri de belirler.
* GraphQL'da bir Resolver nedir? Cevap: Resolver, GraphQL isteğinin belirli bir alanının nasıl çözüleceğini tanımlayan bir işlevdir. Genellikle bir veritabanına erişim ve veri çekme işlemlerini içerir. Her alanın kendi resolver'ı vardır.
* GraphQL'da Mutasyon nedir? Cevap: Mutasyonlar, GraphQL'deki değişiklikleri yapmak için kullanılan işlemlerdir. Bu genellikle veritabanında CREATE, UPDATE ve DELETE işlemlerini temsil eder.
* GraphQL'da bir Query nedir? Cevap: Query, GraphQL'deki veri okuma işlemini temsil eder. Bu, bir veritabanından veri çekmekle karşılaştırılabilir.
* GraphQL'da veri tipleri nelerdir? Cevap: GraphQL'da beş tane yerleşik skalar tip bulunmaktadır: Int, Float, String, Boolean ve ID. Bunun yanı sıra özel skalar tipler, enum tipleri ve null olabilen tipler de mevcuttur. Kullanıcılar ayrıca kendi özel tiplerini, giriş tiplerini ve birleştirme tiplerini tanımlayabilirler.
* GraphQL'da Fragment ne demektir? Cevap: Fragmentlar, GraphQL sorgularında yeniden kullanılabilir birimlerdir. Sorguların parçalarını tanımlarlar ve bu parçaları birleştirerek karmaşık sorgular oluşturabiliriz. Bu, kodun tekrar kullanılabilirliğini artırır ve kod tekrarını azaltır.
* GraphQL'da Subscription nedir? Cevap: Subscriptionlar, GraphQL'deki gerçek zamanlı veri akışı işlemlerini temsil eder. Bir abonelik oluşturulduğunda, belirli bir olayın meydana gelmesi durumunda istemciye bir bildirim gönderilir.
* GraphQL'ın sürüm yönetimi nasıldır? Cevap: GraphQL, sürüm yönetimi için genellikle yeni sürümler veya versiyonlar yayınlamaz. Bunun yerine, yeni özellikler eklemek için yeni tipler, alanlar, bağlantılar vb. eklenir. Eski özellikler ise nadiren kaldırılır veya değiştirilir, bu nedenle bir API'nın mevcut kullanıcıları genellikle etkilenmez.
* GraphQL'da bir Directive nedir? Cevap: Directives, bir Schema, tip veya alanın davranışını değiştirebilecek bir işlevsellik sağlar. Direktifler, özel bir işlevsellik eklemek veya belirli bir alanı değiştirmek için kullanılır.
* GraphQL'ın dezavantajları nelerdir? Cevap: GraphQL'ın birkaç dezavantajı bulunmaktadır. Örneğin, sunucuda yüksek işlem yükü oluşturabilir çünkü istemciden karmaşık sorgular gelebilir. Bu, sunucunun kaynaklarının aşırı kullanımına ve potansiyel performans sorunlarına yol açabilir. Ayrıca, öğrenme eğrisi REST'e kıyasla biraz daha dik olabilir ve tüm durumlar için en iyi çözüm olmayabilir.
* GraphQL'da Introspection nedir? Cevap: Introspection, GraphQL schema hakkında detaylı bilgiler sağlar. Bu sayede istemciler hangi işlemlerin mümkün olduğunu, hangi tiplerin mevcut olduğunu ve hangi alanların bu tiplerde bulunduğunu öğrenebilirler.
* Bir GraphQL servisini nasıl güvende tutarsınız? Cevap: GraphQL servislerini güvende tutmak için birkaç yöntem vardır. Örneğin, yetkilendirme ve kimlik doğrulama mekanizmaları kullanılabilir. Ayrıca, kullanıcıların karmaşık sorgular göndererek sunucuyu boğmasını önlemek için sorgu derinliği ve karmaşıklık sınırlamaları uygulanabilir.
* GraphQL'da Scalar Type ne anlama gelir?
Cevap: Scalar tipler, GraphQL schema'sında terminal veri noktalarını temsil ederler. GraphQL'de birkaç yerleşik skalar tip vardır - String, Int, Float, Boolean ve ID. Bunların dışında, kullanıcılar kendi özel skalar tiplerini tanımlayabilirler.
* GraphQL ve gRPC arasındaki farklar nelerdir?
Cevap: GraphQL ve gRPC, farklı hedefler ve kullanım durumları için tasarlanmış iki farklı API teknolojisidir. GraphQL, istemcilerin tam olarak neye ihtiyaç duyduklarını belirtmelerine ve tek bir istekte birden çok kaynağı sorgulamalarına izin verir. gRPC ise Google tarafından geliştirilmiştir ve düşük gecikme süresi ve yüksek performansı hedefler. gRPC, Protobuf (Protocol Buffers) ile birlikte kullanılarak veri serializasyonunu optimize eder.
* GraphQL'da Pagination nasıl yapılır?
Cevap: GraphQL, bir listeyi sorgularken pagination için çeşitli yöntemler sunar. En yaygın olanı limit-offset tabanlı pagination'dır. Burada, limit sorgu sonuçlarının sayısını ve offset hangi sonuçta başlanacağını belirtir. Bir başka popüler yöntem ise cursor-based pagination'dır. Burada, bir cursor, bir sonraki veri kümesini getirmek için kullanılan bir işaretçidir.
* GraphQL'da Union ve Interface arasındaki fark nedir?
Cevap: Hem Union hem de Interface, GraphQL'de farklı tipler arasında ortak bir alan oluşturmanıza olanak sağlar. Ancak, Interface'ler aynı alanları paylaşan tipleri tanımlar, örneğin aynı alanlara ve/veya metodlara sahip olan nesneler. Union tipi ise aynı alanları paylaşmayan farklı tipleri birleştirebilir, ama belirli bir alanda ortak bir tür sağlar.
* GraphQL'da Batch Request'ler nasıl yapılır?
Cevap: GraphQL, tek bir HTTP isteği içinde birden çok query veya mutation yapabilme yeteneği ile batch request'leri destekler. Bu, bir istemcinin tek bir round-trip içinde birden çok işlem yapmasını sağlar, bu da performansı artırabilir.
Bu sorular ve cevaplar, GraphQL ile ilgili genel bir bakış sağlamalıdır. Ancak unutmayın ki mülakatlar, adayın deneyimine, projelere ve belirli bir iş pozisyonuna bağlı olarak çok daha spesifik veya detaylı olabilir.
* GraphQL'da Error Handling nasıl yapılır?
Cevap: GraphQL, hataları işlemek için özel bir error formatına sahiptir. Her istek yanıtında bir errors adında bir alan olabilir. Bu alan, her biri bir hata mesajı, bir konum ve belki de bir path alanı içeren hata nesnelerinin bir listesini içerir. Ayrıca, GraphQL servisinizde resolver'ları ve diğer işlevleri sarmak için error handling middleware'ları kullanabilirsiniz.
* GraphQL'da Abstract Types ne anlama gelir?
Cevap: Abstract types, bir GraphQL schema'da birden çok tür arasında bir ilişki belirtmek için kullanılır. İki türü vardır: Interface ve Union. Interface, bir dizi alanı paylaşan türler için bir temel sağlar. Union ise birden çok belirli türün aynı alanı doldurabileceğini belirtir, ancak bu türlerin paylaşılan alanları olmayabilir.
* GraphQL'de bir Field nedir?
Cevap: Bir field, GraphQL şemasında bir türün özelliğidir. Bir field, bir türün bir parçasını veya bir türle ilişkili bir alt öğeyi temsil eder. Bir field, çeşitli tiplerde olabilir ve bir resolver tarafından doldurulur.
* GraphQL'de Inline Fragment ne anlama gelir?
Cevap: Inline Fragmentlar, bir türü belirtmek ve bu türle ilişkili field'ları seçmek için kullanılır. Bu, bir türdeki belirli field'ları sorgulamanıza ve belirli türler için özelleştirilmiş bir sorgu oluşturmanıza olanak sağlar.
* GraphQL'da derinlik sınırlaması nedir ve neden önemlidir?
Cevap: Derinlik sınırlaması, bir GraphQL sorgusunun ne kadar "derin" olabileceğini belirler. Bu, istemcinin sunucuyu karmaşık ve potansiyel olarak performansı düşüren sorgularla bombardımana uğratmasını önler. Derinlik sınırlaması genellikle bir GraphQL sunucusunun güvenlik ve performans stratejisinin önemli bir parçasıdır.
* GraphQL API'nizi nasıl test edersiniz?
Cevap: GraphQL API'lerini test etmek için çeşitli araçlar ve yaklaşımlar bulunmaktadır. Unit testing ve integration testing yaygın olarak kullanılır. Bunun yanında, daha karmaşık senaryolar için end-to-end testing de yapılabilir. GraphQL sunucularını test etmek için kullanılabilecek popüler araçlardan bazıları Jest, Mocha ve Apollo'nun kendi testing kitidir.
* Soru: GraphQL'in herhangi bir istemci tarafı kütüphanesi var mıdır?
* Cevap: Evet, GraphQL istemci tarafında çeşitli kütüphaneler ile desteklenir. Bu kütüphanelerden en popüler olanları Apollo Client ve Relay'dir. Apollo, çeşitli programlama dilleri ve çerçeveleri ile kullanılabilen geniş bir GraphQL ekosistemine sahiptir. Relay ise React ile birlikte kullanılmak üzere Facebook tarafından oluşturulmuştur.
* Soru: GraphQL, veriler arasındaki ilişkileri nasıl ele alır?
* Cevap: GraphQL, veriler arasındaki ilişkileri çözmek için "resolvers" adı verilen fonksiyonları kullanır. Resolvers, belirli bir tipin belirli bir alanı için çağrılır ve GraphQL isteği boyunca uygulanır. Bu, GraphQL'in bir sorgu içinde birden fazla kaynağı ve ilişkili veriyi çözebilmesini sağlar.
* Soru: GraphQL ve REST arasındaki temel farklar nelerdir?
* Cevap: Her ikisi de API'ler için popüler tasarım stilleridir ancak birkaç önemli fark vardır:
* Veri alımı: REST, sunucu tarafından belirlenen veri setlerini döndürür. GraphQL'de ise istemciler, ihtiyaç duydukları spesifik veriyi belirleyebilirler.
* Versiyonlama: REST API'ler genellikle yeni veri gereksinimlerini karşılamak için yeni versiyonlara ihtiyaç duyarlar. GraphQL ise yeni alanları ekleyerek ve eski alanları koruyarak bu ihtiyacı azaltır.
* Performans: REST API'ler genellikle çok sayıda uç noktaya ihtiyaç duyar ve bu da gereksiz veri getirme veya çok fazla istek yapma durumlarına yol açabilir. GraphQL, bir istekte birden fazla veriyi getirme yeteneği ve istemcilerin sadece ihtiyaç duydukları veriyi belirlemeleri sayesinde bu sorunları çözer.
* Soru: GraphQL sorguları hangi HTTP metodları ile gönderilir?
* Cevap: GraphQL sorguları ve mutasyonları genellikle HTTP POST metodları ile gönderilir. Ancak, sorgular HTTP GET metodları ile de gönderilebilir. Bununla birlikte, standart bir yaklaşım olarak genellikle POST kullanılır.
* Soru: GraphQL'de veri doğrulama nasıl yapılır?
* Cevap: GraphQL'de veri doğrulama, genellikle istemci tarafında ve sunucu tarafında olmak üzere iki seviyede yapılır. İstemci tarafında, GraphQL şeması istemciye hangi türlerin mevcut olduğunu ve hangi alanların hangi türde olduğunu belirtir. Bu bilgi, istemcinin veri göndermeden önce doğru tiplere sahip olduğunu doğrulamasına yardımcı olur. Sunucu tarafında, GraphQL, veri türlerini ve yapılarını belirten şemaya dayalı olarak veriyi doğrular. Eğer veri, şemanın belirttiği formata uymuyorsa, GraphQL bir hata döndürür.
* Soru: GraphQL ve SQL arasında bir bağlantı var mı?
* Cevap: Hayır, GraphQL ve SQL arasında doğrudan bir bağlantı yoktur. GraphQL bir API sorgulama dili ve runtime iken, SQL bir veritabanı sorgulama dilidir. Ancak, bir GraphQL servisi, bir SQL veritabanıyla iletişim kurmak için bir resolver içinde SQL sorgularını kullanabilir. Bu, GraphQL'in veri kaynaklarına bağımsız olduğu anlamına gelir: SQL veritabanları, NoSQL veritabanları, diğer API'ler veya hatta statik dosyalar kullanabilir.
* Soru: GraphQL'de hata yönetimi nasıl gerçekleştirilir?
* Cevap: GraphQL'de hatalar genellikle iki şekilde işlenir: GraphQL sistem hataları ve iş hataları. Sistem hataları, sorgu analizinde veya veri çözümleme aşamasında meydana gelir ve genellikle sunucunun bir errors alanıyla yanıt vermesiyle sonuçlanır. İş hataları, iş mantığı hatası olduğunda resolver tarafından döndürülür. İş hataları genellikle ilgili alanın null ve errors alanında ayrıntılı bir mesajla sonuçlanır. Bu yaklaşım, iş hatalarını ve sistem hatalarını ayırt etmeyi ve hataları daha iyi yönetmeyi sağlar.
Spring Boot ile GraphQL Uygulaması Örneği:
Öncelikle, Spring Boot projesi oluşturmalı ve aşağıdaki GraphQL Java bağımlılıklarını eklemelisiniz:
Şimdi, bir ID ile bir Person sorgulayabiliriz. Bu, bir HTTP POST isteği ile localhost:8080/graphql adresine yapılabilir ve aşağıdaki gibi bir istek gövdesi içerebilir:
json
Copy code
{
"query
Özür dilerim, yanlışlıkla mesajımı tamamlamadan gönderdim. İstek gövdesi aşağıdaki gibi olmalı:
json
Copy code
{
"query": "{findPersonById(id: 1){name, age}}"
}
Bu istek, ID'si 1 olan kişinin adını ve yaşını sorgular.
Veri döndürme ve değiştirme dışında, bir GraphQL API'si hataları yönetme, doğrulama ve otomatik tamamlama gibi diğer önemli özellikler de sunar. Örneğin, bir alanın yanlış bir veri tipi ile döndürülmesi durumunda, GraphQL bunu bir hata olarak işaretler ve hata detaylarını yanıtta döndürür.
Son olarak, GraphQL bir API sorgulama dili olmasının yanı sıra, istemcilerin ihtiyaçlarına göre özelleştirilmiş veri almasını sağlayan bir yapıdır. Bu, verinin gereksiz ağ trafiğini azaltır ve genellikle daha verimli ve hızlı bir uygulama deneyimi sağlar.
Bu örnek basit bir GraphQL uygulamasıdır ve daha karmaşık senaryolar, birden çok tip ve ilişki, karmaşık veri döndürme ve mutasyonlar, hata yönetimi ve yetkilendirme gibi özellikleri içerebilir. Bu özelliklerin her biri, GraphQL'in gücünü ve esnekliğini daha da gösterir ve bir GraphQL API'sinin nasıl tasarlanacağı ve geliştirileceği konusunda daha derin bir anlayış sağlar.
Daha karmaşık bir senaryoyu Spring Boot örnek kodlarıyla yazar mısın?
Tabii ki, bir blog uygulaması için daha karmaşık bir GraphQL senaryosunu inceleyelim. Bu uygulama, blog yazılarını ve bu yazılara ait yorumları yönetir. Öncelikle, bu senaryonun GraphQL şemasını tanımlamalıyız. Bu, src/main/resources/schema.graphqls dosyasında aşağıdaki gibi olabilir:
graphql
Copy code
type Query{
findAllPosts: [Post]
findPostById(id: ID): Post
}
type Mutation{
savePost(post: PostInput): Post
}
input PostInput{
title: String
content: String
author: String
}
type Post{
id: ID
title: String
content: String
author: String
comments: [Comment]
}
type Comment{
id: ID
text: String
post: Post
}
Bu şemada, Query ve Mutation tipleri ile birlikte Post ve Comment tipleri tanımlanmıştır. PostInput tipi, bir Post oluştururken kullanılır.
Ardından, Post ve Comment için model sınıflarını oluşturmalıyız:
java
Copy code
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String content;
private String author;
@OneToMany(mappedBy = "post")
private List<Comment> comments;
// getters and setters
}
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String text;
@ManyToOne
@JoinColumn(name = "post_id", nullable = false)
private Post post;
// getters and setters
}
Post ve Comment için repository sınıfları oluşturmalıyız:
java
Copy code
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
}
@Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
}
Sonra bir GraphQLQueryResolver ve GraphQLMutationResolver oluşturmalıyız:
java
Copy code
@Component
public class PostQueryResolver implements GraphQLQueryResolver {
private PostRepository postRepository;
public PostQueryResolver(PostRepository postRepository) {
this.postRepository = postRepository;
}
public List<Post> findAllPosts() {
return postRepository.findAll();
}
public Post findPostById(Long id) {
return postRepository.findById(id).orElse(null);
}
}
@Component
public class PostMutationResolver implements GraphQLMutationResolver {
private PostRepository postRepository;
public PostMutationResolver(PostRepository postRepository) {
this.postRepository = postRepository;
}
public Post savePost(String title, String content, String author) {
Post post = new Post();
post.setTitle(title);
post.setContent(content);
post.setAuthor(author);
return postRepository.save(post);
}
}
Bu kodlarla birlikte artık GraphQL API'niz üzerinden blog yazıları oluşturabilir, tüm blog yazılarını listeleyebilir ve belirli bir ID'ye sahip bir blog yazısını sorgulayabilirsiniz. Her Post nesnesi, ilişkili Comment nesnelerini içerir.
Bu, GraphQL'in tek bir sorgu içinde ilişkili nesneleri alma yeteneğinin bir örneğidir. Bu senaryoyu daha karmaşık hale getirmek için, yorumları da işlemek için bir GraphQLMutationResolver oluşturabilirsiniz. İşte bir örneği:
java
Copy code
@Component
public class CommentMutationResolver implements GraphQLMutationResolver {
private PostRepository postRepository;
private CommentRepository commentRepository;
public CommentMutationResolver(PostRepository postRepository, CommentRepository commentRepository) {
this.postRepository = postRepository;
this.commentRepository = commentRepository;
}
public Comment saveComment(String text, Long postId) {
Comment comment = new Comment();
comment.setText(text);
Post post = postRepository.findById(postId).orElseThrow(() -> new RuntimeException("Post not found"));
comment.setPost(post);
return commentRepository.save(comment);
}
}
Bu kod ile, bir blog yazısına yorum ekleyebiliriz. GraphQL, birden çok model arasında ilişkiler oluşturma ve yönetme yeteneği sayesinde bu tür karmaşık senaryoları kolayca destekler.
Bu örnek, bir GraphQL API'sini nasıl oluşturacağınız ve Spring Boot ile nasıl entegre edeceğiniz konusunda genel bir bakış sunmaktadır. Daha karmaşık uygulamalar, hata yönetimi, kimlik doğrulama ve yetkilendirme, performans iyileştirmeleri ve diğer özellikler ekleyebilir. Ancak, bu temel yapı, GraphQL ile bir API oluşturmanın ana hatlarını çizmektedir.
Sınırlı sayıda özellik query ettiğimizbir senaryoyu Spring Boot örnek kodlarıyla yazar mısın?
Tabii ki, GraphQL'in en güçlü özelliklerinden biri olan, yalnızca belirli alanları sorgulama yeteneğini ele alalım. Bu durum, kullanıcının yalnızca belirli bir Post'un başlığına ve yazarına ihtiyaç duyduğu, ancak içeriğine veya yorumlarına ihtiyaç duymadığı bir senaryoyu ele alalım.
Öncelikle, daha önceki örnekte oluşturduğumuz Post modeline bakalım:
java
Copy code
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String content;
private String author;
@OneToMany(mappedBy = "post")
private List<Comment> comments;
// getters and setters
}
Bu Post modelinde, title, content, author ve comments alanları bulunmaktadır.
GraphQL kullanarak, bir kullanıcı yalnızca title ve author bilgilerine sahip bir Post sorgulayabilir. İşte bu sorgunun nasıl görüneceği:
json
Copy code
{
"query": "{findPostById(id: 1){title, author}}"
}
Bu sorgu, Post'un tamamını yüklemek yerine, yalnızca title ve author alanlarını döndürür. Bu, ağ verimliliğini artırır ve gereksiz verilerin yüklenmesini önler.
GraphQL'in bu yeteneği, Post'un başlığına ve yazarına ihtiyaç duyan bir front-end bileşeni için çok yararlı olabilir. Bu bileşen, gerektiğinde daha fazla ayrıntı istemek için başka bir sorgu yapabilir. Bu, hem sunucu hem de istemci tarafında verimliliği artırır.
Ayrıca, GraphQL sunucuları genellikle bir Post'un comments alanını yüklemek için ayrı bir resolver kullanır. Bu, yalnızca comments alanı sorgulandığında yorumların yüklenmesini sağlar. Bu, veri yüklemesini daha da verimli hale getirir ve yalnızca gerekli olan verinin yüklenmesini sağlar. Bu yaklaşım, "veri yığınları" veya "veri yükleme" olarak bilinir ve GraphQL'in veri verimliliğini daha da artırır.