GraphQL: Veri Erişiminde Yeni Bir Bakış Açısı
Geliştirdiğimiz bir projede, çok sayıda anlık istek alan sayfalar nedeniyle Restful mimarisinin ve MVC’nin getirdiği bazı zorluklarla karşılaştık. Zaman içerisinde proje büyüdükçe, bilhassa veri sorgulama ile veriye erişim modelimizle ilgili sıkıntılar yaşadık ve sorunları gidermek için doğru olmayan çözümler üretmek zorunda kaldık. Yaşadığımız sorunları göz önünde bulundurarak, veriye erişimde ve sorgulamada yeni bir alternatif ihtiyacının belirginleştiğini ekip olarak görmeye başladık.
Bu sorunların üzerine okuduğum bazı makaleler ve mail gruplarından gelen bazı iletilerde dikkatimi çeken bişey olmuştu. Artık veriye erişim ve veriyi sorgulama modelimizin yeni alternatifler içinde yeniden tanımlanmaya başlandığını gördüm. Klasik REST mimarisi yerine, “resource/kaynak bazlı bir istek modeli yerine(/api/products gibi)”, istemcinin ihtiyacı olan veriyi kendinin tanımladığı bir model olan GraphQL dikkatimi çekti.
Son birkaç yıldır, başta Netflix ve Facebook olmak üzere, “veriye erişim/sorgulama modeli” konusu sektörde sıkça konuşulmaya başlandı ve tüm bunların neticesinde yeni bir alternatif olan GraphQL mimarisi ile daha alt seviye bir çözüm olan Falcor ortaya çıktı. GraphQL, sorunlara mimari olarak bir çözüm arayışındayken, Falcor daha alt seviye bir model / ara çözümle benzer sorunlara çözüm arıyordu.
Facebook tarafından geliştirilen/standartlaştırılan GraphQL “veri sorgulama ve erişimi” için yeni bir yaklaşım tarzı sunuyor. GraphQL, ayrıca Restful mimariye de tamamen yeni bir alternatif olma özelliğiyle dikkat çekiyor.
Bu yazıda son günlerde sıkça duyulan GraphQL’i tanıtmaya çalışacağım. İlerleyen günlerde de bu yazının devamı niteliğinde olan GraphQL Servers, Relay ve Apollo Stack gibi yeni yaklaşımlar üzerine bir yazıyı yine Devnot.com adresinden yayınlayacağım.
GraphQL Nedir?
İsme baktığımızda “GraphQL” i aslında biraz “kafa karışıtırıcı (en azından benim için öyleydi)” bulabilirsiniz. Sanki, Sunucu tarafında Graph veritabanlarını sorgulama için yeni bir dil gibi gelmişti. Ama işin doğrusu GraphQL için “Application Level Query Language” tanımı görebilmekteyiz. Yani bir veri tabanı sorgulama dili vs değil . Çözmeye çalıştığı problem, application level / uygulama seviyesinde istemciler için bir sorgulama ara yüzü oluşturmak.
Application levelden kastımız, sunucu tarafında oluşturulan Query Interface ile istemci tarafında bu interface uygun olarak istemcinin kendi sorgularını oluşturabilme imkanını kazanması yeteneği diye düşünebiliriz.
Bu noktaya kadar hala soyut olarak konuştuğumuz “GraphQL” i biraz daha iyi anlayabilmek için bir örnek karşılaştırma ile devam edelim. Ve şöyle bir ihtiyacımız olsun;
- İstemcimizin, veri tabanımızdan x ürününü istediğini düşünün
- /api/product/x
- Ayrıca bu ürünün stok durumu ve bu ürün ü de kapsayan son 20 satışa da ihtiyacımız olsun
- /api/product/x/stok
- /api/product/x/sales?limit=20
- Sonra, ürünle ilgili resimleri de ilgili tablodan sorgulayalım
- /api/product/x/pictures
Yukarıda, API alt yapınızı nasıl yapılandırdığınıza bağlı olarak (bizim örneğimizde çok kullanılan nested resource routing) 4 ayrı istekde bulunduk. Son 5-6 senedir bir çok framework tarafından(Rails, Laravel, ASP.NET MVC vs.) uyarlanan ve yaygın kullanılan bu restfull / MVC yapı ile istemcimiz sunucudan veri talebinde bulunmuş oldu.
Her bir kaynak veya o kaynağın ilişkisi olan diğer kaynak için ayrı ayrı endpoint ler tanımlayıp, sorgulamalar yaptığımız bu model yerine , yukarıdaki işlemi bir GraphQL sorgusu ile eşleştirmeye çalışalım.
{ urun(x){ _id, name, price, stok { count }, sales(limit:20) { customer, total }, pictures{ thumbs, name } } }
İlk olarak GraphQL sorgumuza baktığımızda, sorgunun kendini açıklayan ve kolay bir yapıda olduğunu görmekteyiz. Ayrıca, istemcinin, örneğin “ürün” alanı için sadece , “id,name ve price” alanlarını istediğini ve yine ürünle ilgili son 20 satışı ve ürünün resimlerini de beklediğini açıkca anlamaktayız.
REST veya MVC örneğimizde ise istemci, sadece belirli end-point lere istekler göndererek sunucudan talepde bulunuyor, uygulamanın içinde her bir alt birim kendi istekleri için sürekli farklı veya aynı noktalara istekler yapıyor. İlk modelimizde(REST/MVC), ilgili ürünleri almanız sonrasında bu ürün için tekrar tekrar istekde bulunmanız gerekecek.
REST/MVC mimarisiyle ilgili başka bir sıkıntıyı ve GraphQL’in bu konudaki yardımını yine bir pratik karşılaştırma yaparak anlamaya çalışalım;
Uygulamamizin bir yerinde, ürünümüzün “ismi,fiyatı ve markasını” göstermemiz gereksin. Örnek istek şöyle:
şöyle bir cevap alalım;
{ id:22, name:"televizyon", price:"12.32", brand:"Vestel", model:"y1233", isOnSale:false, isOnHomePage:false, lastUpdatedByUserId:232, created_at:"132132133", updated_at:"132142135" }
Bu tür bir cevap yerine(ürünün sadece şu 3 alanına ihtiyacımız varken “ismi,fiyatı ve markası” ) istemcimiz ürün bilgisinin tamamını alacaktır. Uygulamanın başka bir noktasında ise ürünün sadece id alanına ihtiyaç duyabiliriz. GraphQL örneğinde, istemci neye ihtiyacı olduğunu kendisi belirteceği için sunucu tarafında aynı alt yapı ile istemcinin hemen hemen tüm ihtiyaçlarına cevap verebileceğiz.
{ urun(x) { name, price, brand } }
veya;
urun(x) { _id }
gibi.
Üstelik, GraphQL frameworklerin bir çoğunun dahili olarak sağladığı caching(önbellekleme) ile zaten istemcide bulunan verileri tekrar sorgulamadan, mevcut veriyi cache’den kolayca alma yeteneği var.
Aşağıdaki iki resme bakarak GraphQL ve REST/MVC yapıları arasındaki ilk ayrışımı görebiliriz.
Klasik MVC/Rest
GraphQL
İkinci ayrımız olan “istemcinin isteğini kendi ihtiyacına göre tanımlayabilmesi” konusu için aşağıdaki sorguya bakalım;
Yukarıdaki görüntüde sol taraftaki GraphQL sorgumuzun ne kadar anlaşılır ve “declarative” olduğunu görüyoruz. Sorgumuzun aldığı cevap ise sağ tarafta. Klasik Rest/MVC yapısı ile en az 2-3 farklı controller gerektiren ve birkaç HTTP Request ile yapabileceğimiz işlemin GraphQL ile ne kadar sade bir şekilde gerçekleştiği aşikar.
Şimdiye dek konuştuğumuz konulara bir kaç ekleme daha yaparak devam edelim. GraphQL, mimarisi iki parçalı bir yapıdan oluşmakta;
- GraphQL sunucusu (Aplicaton Level Query Layer ) ve
- GraphQL istemcisi, (sorguları düzgün bir şekilde oluşturup, sunucu ile iletişimi kuracak client)
Hemen belirtelim, GraphQL istemcisi çok karışık komplex bir yapı değil ve teknik olarak zorunluda değil, sorgularımızı bu tür bir yardımcı olmadan da kendimiz oluşuturup sunucuya gönderebiliriz ve cevabı kendi kendimize işleyebiliriz. Ama Tahmin edeceğiniz gibi bu durum çok iş yükü getirecektir, o yüzden hazır istemcilerden birini seçip kullanmak en ideali. Yazının devamında bu konuya tekrar döneceğiz.
Sunucu tarafındaki GraphQL alt yapısı ise yine hazır bir framework kullanmadan ve GraphQL standartlarına uyarak hemen hemen her türlü dil ve platform için gerçeklenebilir.Ama sıfırdan kendi GraphQL sunucumuzu oluşturmak muhtemelen pek isteyeceğimiz bir durum degil. Yazınnın devamında bugün itibariyle kullanabileceğimiz bazı alternatiflerden bahsedeceğiz ama genel olarak bir GraphQL sunucusu aşağıdaki gibi bir yapıya sahip diyebiliriz;
- schema — GraphQL yapısı gereği, strongly typed / veri tipi zorunluluğu gerektiren bir veri katmanına ihtiyaç duymakta. GraphQL standartlarına göre bu veri şemalarımıza yada bir başka değişle “data types” ihtiyacımız var.
- resolve functions , GraphQL sunucumuzun verileri nerden ve nasıl temin edeceğini tanımlaycak fonksiyonlar.
Yukarıdaki iki maddeye başka eklemeler yapılabilir ama, bunları en önemli iki madde olarak düşünebiliriz.
Eğer, .NET geliştiricisiyseniz, GraphQL mimariyi anlamanıza yardımcı olacak güzel bir örnek olarak “LINQ” i düşünebilirsiniz. Basitçe, IQueryable Arayüzünü implement eden her collection ı LINQ ile sorgulayabilme, filitreleme yada eğer immutable yapı adına izin veriyorsa manipüle edebilmekteyiz.
GraphQL örneğimizle kıyasalayacak olursak, IQueryable ara yüzünü uygulama seviyesinde sunucumuzun implement etmesini GraphQL sunucusu olarak düşünebiliriz, GraphQL istemcimizi ise LINQ in kendisine benzetebiliriz. Elinizde IQueryable arayüzünü implement etmiş bir http end point var ve istemci tarafında LINQ e sahipsiniz gibi düşünebilirsiniz.
Bu tanım teknik bir kıyaslama değil tabiiki, sadece mantık benzerliği ile yardımcı olmak adına belirttim.
Şimdi, GraphQL e biraz daha yakından bakmak adına GraphQL sunucuları için geliştirilmiş, bir test ve bir yönüyle dökümantasyon oluşturma aracı olan “GraphQL IDE yada diğer ismiyle GraphiQL ” e bakarak devam edelim.(isim de i harfi fazla GraphiQL)
GraphiQL, sunucumuzda GraphQL data types ile senkronize olarak çalışacağı için, sunucumuzda yaptığımız her değişim otomatik olarak hemen test ortamımıza yansımış olacak ayrıca aynı şekilde dökümentasyonumuzda otomatik olarak güncellenmiş olacak.
https://sandbox.learngraphql.com/ adresinde online olarak deneyebileceğimiz bir GraphiQL uygulaması çalışmakta şimdi bu adrese girip bir kaç deneme yapalım;
Görüntüden de görebileceğiniz gibi çok hızlı ve sade bir şekilde sorgularımızı oluşturabiliyoruz. Bir başka güzel tarafta, Auto Complete özelliği. Ayrıca hem test ortamı hemde dökümantasyon olarak kullanılabilmekte.
Şimdiye dek her hangi bir kurulumdan vs bahsetmedik, çünkü GraphQL in kendisi bir framework yada kütüphane değil dedik, Facebook bünyesinde geliştirilen yeni bir dizayn kalıbı ve veri erişimi/sorgulaması için yeni bir alternatifin tanımlanıp standartlaştırılmasından ibaret.( facebook kendi uyarlamasını Relay ile birlikte 2012 den beri kullanmakta)
GraphQL mimari ile uygulama geliştirmek için, bu mimariyi gerçekleyen kütüphanelere ihtiyacımız var. İşte bu noktada GraphQL mimari yi baz alan aşağıdaki alternatifler ortaya çıkmaktadır.
Bir sonraki yazıda GraphQL Servers, Relay ve Apollo Stack konularıyla görüşmek üzere.
Bazı Kaynaklar:
https://facebook.github.io/relay/docs/thinking-in-graphql.html
http://graphql.nodaljs.com/
http://graphql.org/docs/getting-started/
https://learngraphql.com/basics/introduction
5 Comments
serdar
14 Nisan 2017 at 21:35Çok güzel bir yazı olmuş. Klavyenize sağlık. Rest’e alışamadan alternatifi çıktı yine Bu tür değerli türkçe kaynakların artması dileğiyle.
Yakup
20 Nisan 2017 at 19:13Graphql kullanımına ilişkin;
apollo graphql client ve graphql-express server hazırlanmış bu projeyi inceleyebilirsiniz.
https://github.com/arunoda/try-apollo
Mert Köseoğlu
26 Haziran 2017 at 02:25Sevgili Hüseyin, harika bir yazı olmuş. Kutlarım.
Ramazan Karagöz
27 Nisan 2018 at 15:15Çok güzel bir yazı olmuş.Teşekkürler.
Süleyman GÜNDÜZ
9 Temmuz 2018 at 11:55Güzel bir anlatım olmuş , teşekkürler.