paint-brush
REST'e biraz dinlenme zamanı geldiğindeile@johnjvester
2,364 okumalar
2,364 okumalar

REST'e biraz dinlenme zamanı geldiğinde

ile John Vester13m2024/05/13
Read on Terminal Reader

Çok uzun; Okumak

Bu makale, veri alımı için GraphQL ve REST API'lerini karşılaştırarak GraphQL'in esnekliğinin ve verimliliğinin karmaşık senaryolarda nasıl üstün olduğunu ortaya koyuyor. Apollo Server'ın Heroku ile konuşlandırılmasını ayrıntılarıyla anlatıyor ve GraphQL'deki kimlik doğrulama ve gerçek zamanlı verilerle ilgili yakında yayınlanacak içeriği tanıtıyor.
featured image - REST'e biraz dinlenme zamanı geldiğinde
John Vester HackerNoon profile picture
0-item
1-item


Yıllar süren hizmet geliştirme sürecim boyunca, RESTful API benim ilk tercihim oldu. Ancak REST'in avantajları olmasına rağmen bu, her kullanım durumu için en iyi yaklaşım olduğu anlamına gelmez. Yıllar geçtikçe, bazen belirli senaryolar için daha iyi alternatiflerin bulunabileceğini öğrendim. Sırf bu konuda tutkulu olduğum için REST'e bağlı kalmak (doğru uyum olmadığında) yalnızca teknik borçla ve ürün sahibiyle gergin bir ilişkiyle sonuçlanır.


RESTful yaklaşımının en büyük sıkıntılı noktalarından biri, bir iş kararı için gerekli tüm bilgileri almak için birden fazla talepte bulunma ihtiyacıdır.


Örnek olarak, bir müşterinin 360 derecelik görüntüsünü istediğimi varsayalım. Aşağıdaki istekleri yapmam gerekecek:


  • GET /customers/{some_token} temel müşteri bilgilerini sağlar
  • GET /addresses/{some_token} gerekli adresi sağlar
  • GET /contacts/{some_token} iletişim bilgilerini döndürür
  • GET /credit/{some_token} önemli finansal bilgileri döndürür


REST'in temel amacının, yanıtları her kaynak için lazer odaklı tutmak olduğunu anlasam da, bu senaryo tüketici tarafında daha fazla çalışma yapılmasını sağlıyor. Bir kuruluşun müşteriyle gelecekteki işleriyle ilgili kararlar almasına yardımcı olacak bir kullanıcı arayüzü oluşturmak için tüketicinin birden fazla arama yapması gerekir.


Bu makalede, GraphQL'in neden bir RESTful API'ye göre tercih edilen yaklaşım olduğunu göstereceğim ve GraphQL ile hızlı bir şekilde çalışmaya başlamak için Apollo Sunucusunun (ve Apollo Explorer'ın) nasıl dağıtılacağını göstereceğim.


Çözümümü Node.js ile oluşturmayı ve çözümümü Heroku'ya dağıtmayı planlıyorum.

REST yerine GraphQL ne zaman kullanılmalı?

GraphQL'in REST'ten daha iyi bir yaklaşım olduğu birkaç yaygın kullanım durumu vardır:


  • Veri alma şekliniz konusunda esnekliğe ihtiyacınız olduğunda: Çeşitli kaynaklardan karmaşık verileri tek bir istekle alabilirsiniz. (Bu makalede bu yola değineceğim.)
  • Ön uç ekibinin kullanıcı arayüzünü sık sık geliştirmesi gerektiğinde: Hızla değişen veri gereksinimleri, arka ucun uç noktaları ayarlamasını ve engelleyicilere neden olmasını gerektirmez.
  • Aşırı ve yetersiz getirmeyi en aza indirmek istediğinizde: Bazen REST, ihtiyacınız olan tüm verileri toplamak için birden fazla uç noktaya ulaşmanızı gerektirir (yetersiz getirme) veya tek bir uç noktaya basmak, gerçekte ihtiyacınız olandan çok daha fazla veri döndürür (aşırı - getiriliyor).
  • Karmaşık sistemler ve mikro hizmetlerle çalışırken: Bazen birden fazla kaynağın, verileri için yalnızca tek bir API katmanını kullanması gerekir. GraphQL bu esnekliği tek bir API çağrısı aracılığıyla sağlayabilir.
  • Size gönderilen gerçek zamanlı verilere ihtiyacınız olduğunda: GraphQL, gerçek zamanlı güncellemeler sağlayan aboneliklere sahiptir. Bu, sohbet uygulamaları veya canlı veri yayınları durumunda kullanışlıdır. (Bu faydayı bir sonraki makalede daha ayrıntılı olarak ele alacağım.)

Apollo Sunucusu Nedir?

GraphQL ile ilgili becerilerim pek gelişmiş olmadığından bu makale için Apollo Server'ı kullanmaya karar verdim.


Apollo Server, herhangi bir GraphQL şemasıyla çalışan bir GraphQL sunucusudur. Amaç, GraphQL API oluşturma sürecini basitleştirmektir. Temel tasarım, Express veya Koa gibi çerçevelerle iyi bir şekilde bütünleşir. Bir sonraki makalemde gerçek zamanlı veriler için aboneliklerden ( graphql-ws kütüphanesi aracılığıyla) yararlanma yeteneğini keşfedeceğim.


Apollo Server'ın gerçekten parladığı yer, geliştiricilerin GraphQL API'lerini keşfetmek ve test etmek için kullanabilecekleri yerleşik bir web arayüzü olan Apollo Explorer'dır. Sorguların kolay oluşturulmasına ve API şemasının grafiksel formatta görüntülenmesine olanak sağladığı için stüdyo benim için mükemmel bir seçim olacaktır.

Müşterim 360 Kullanım Örneği

Bu örnekte, müşterinin 360 derecelik görünümünü sağlamak için aşağıdaki şemaya ihtiyacımız olduğunu varsayalım:


 type Customer { token: String name: String sic_code: String } type Address { token: String customer_token: String address_line1: String address_line2: String city: String state: String postal_code: String } type Contact { token: String customer_token: String first_name: String last_name: String email: String phone: String } type Credit { token: String customer_token: String credit_limit: Float balance: Float credit_score: Int }


Aşağıdaki GraphQL sorgularına odaklanmayı planlıyorum:


 type Query { addresses: [Address] address(customer_token: String): Address contacts: [Contact] contact(customer_token: String): Contact customers: [Customer] customer(token: String): Customer credits: [Credit] credit(customer_token: String): Credit }


Tüketiciler, görüntülemek istedikleri Müşteriye jetonu sağlayacaktır. Ayrıca uygun Adres, Kişi ve Kredi nesnelerini de almayı bekliyoruz. Amaç, tüm bu bilgiler için tek bir API çağrısı yerine dört farklı API çağrısı yapmaktan kaçınmaktır.

Apollo Sunucusuna Başlarken

Yerel iş istasyonumda graphql-server-customer adında yeni bir klasör oluşturarak başladım. Daha sonra Apollo Sunucu belgelerinin Başlarken bölümünü kullanarak TypeScript yaklaşımını kullanarak birinci ve ikinci adımları izledim.


Daha sonra şemamı tanımladım ve test için bazı statik verileri de ekledim. Normalde bir veritabanına bağlanırdık, ancak statik veriler bu demoda iyi çalışacaktır.


Güncellenmiş index.ts dosyam aşağıdadır:


 import { ApolloServer } from '@apollo/server'; import { startStandaloneServer } from '@apollo/server/standalone'; const typeDefs = `#graphql type Customer { token: String name: String sic_code: String } type Address { token: String customer_token: String address_line1: String address_line2: String city: String state: String postal_code: String } type Contact { token: String customer_token: String first_name: String last_name: String email: String phone: String } type Credit { token: String customer_token: String credit_limit: Float balance: Float credit_score: Int } type Query { addresses: [Address] address(customer_token: String): Address contacts: [Contact] contact(customer_token: String): Contact customers: [Customer] customer(token: String): Customer credits: [Credit] credit(customer_token: String): Credit } `; const resolvers = { Query: { addresses: () => addresses, address: (parent, args, context) => { const customer_token = args.customer_token; return addresses.find(address => address.customer_token === customer_token); }, contacts: () => contacts, contact: (parent, args, context) => { const customer_token = args.customer_token; return contacts.find(contact => contact.customer_token === customer_token); }, customers: () => customers, customer: (parent, args, context) => { const token = args.token; return customers.find(customer => customer.token === token); }, credits: () => credits, credit: (parent, args, context) => { const customer_token = args.customer_token; return credits.find(credit => credit.customer_token === customer_token); } }, }; const server = new ApolloServer({ typeDefs, resolvers, }); const { url } = await startStandaloneServer(server, { listen: { port: 4000 }, }); console.log(`Apollo Server ready at: ${url}`); const customers = [ { token: 'customer-token-1', name: 'Acme Inc.', sic_code: '1234' }, { token: 'customer-token-2', name: 'Widget Co.', sic_code: '5678' } ]; const addresses = [ { token: 'address-token-1', customer_token: 'customer-token-1', address_line1: '123 Main St.', address_line2: '', city: 'Anytown', state: 'CA', postal_code: '12345' }, { token: 'address-token-22', customer_token: 'customer-token-2', address_line1: '456 Elm St.', address_line2: '', city: 'Othertown', state: 'NY', postal_code: '67890' } ]; const contacts = [ { token: 'contact-token-1', customer_token: 'customer-token-1', first_name: 'John', last_name: 'Doe', email: '[email protected]', phone: '123-456-7890' } ]; const credits = [ { token: 'credit-token-1', customer_token: 'customer-token-1', credit_limit: 10000.00, balance: 2500.00, credit_score: 750 } ];


Her şey beklendiği gibi yapılandırıldığında, sunucuyu başlatmak için aşağıdaki komutu çalıştırıyoruz:


 $ npm start


Apollo sunucusu 4000 numaralı bağlantı noktasında çalışırken, Apollo Explorer'a erişmek için http://localhost:4000/ URL'sini kullandım. Daha sonra aşağıdaki örnek sorguyu oluşturdum:


 query ExampleQuery { addresses { token } contacts { token } customers { token } }


Apollo Explorer'da şöyle görünüyor:


Örnek Sorgu düğmesine basarak yanıt yükünün index.ts dosyasında sağladığım statik verilerle uyumlu olduğunu doğruladım:


 { "data": { "addresses": [ { "token": "address-token-1" }, { "token": "address-token-22" } ], "contacts": [ { "token": "contact-token-1" } ], "customers": [ { "token": "customer-token-1" }, { "token": "customer-token-2" } ] } }


Müşteri 360 kullanım durumumu ele alma konusunda daha ileri gitmeden önce bu hizmeti bulutta çalıştırmak istedim.

Apollo Sunucusunu Heroku'ya Dağıtma

Bu makale tamamen yeni bir şey yapmakla ilgili olduğundan Apollo sunucumu Heroku'ya dağıtmanın ne kadar zor olacağını görmek istedim.


Yerel olarak çalıştırma ile bulutta bir yerde çalıştırma arasındaki bağlantı noktası numarası farklılıklarını çözmem gerektiğini biliyordum. Sunucuyu başlatmak için kodumu aşağıda gösterildiği gibi güncelledim:


 const { url } = await startStandaloneServer(server, { listen: { port: Number.parseInt(process.env.PORT) || 4000 }, });


Bu güncellemeyle birlikte, bir ortam değişkeninde PORT değeri belirtilmediği sürece 4000 numaralı bağlantı noktasını kullanacağız.


Gitlab'ı kullanarak bu dosyalar için yeni bir proje oluşturdum ve Heroku komut satırı arayüzünü (CLI) kullanarak Heroku hesabımda oturum açtım:


 $ heroku login


Heroku'da CLI veya Heroku kontrol paneli web kullanıcı arayüzüyle yeni bir uygulama oluşturabilirsiniz. Bu makale için CLI'yi kullanacağız:


 $ heroku create jvc-graphql-server-customer


CLI komutu aşağıdaki yanıtı döndürdü:


 Creating ⬢ jvc-graphql-server-customer... done https://jvc-graphql-server-customer-b62b17a2c949.herokuapp.com/ | https://git.heroku.com/jvc-graphql-server-customer.git


Komut ayrıca Heroku tarafından uzaktan kumanda olarak kullanılan depoyu da otomatik olarak ekledi:


 $ git remote heroku origin


Apollo Server, üretim ortamlarında Apollo Explorer'ı varsayılan olarak devre dışı bırakır. Demom için onu Heroku'da çalışır durumda bırakmak istiyorum. Bunu yapmak için NODE_ENV ortam değişkenini geliştirmeye ayarlamam gerekiyor. Bunu aşağıdaki CLI komutuyla ayarlayabilirim:


 $ heroku config:set NODE_ENV=development


CLI komutu aşağıdaki yanıtı döndürdü:


 Setting NODE_ENV and restarting ⬢ jvc-graphql-server-customer... done, v3 NODE_ENV: development


Artık kodumuzu Heroku'ya dağıtabilecek konumdayız:


 $ git commit --allow-empty -m 'Deploy to Heroku' $ git push heroku


Heroku Kontrol Paneline hızlı bir bakış, Apollo Sunucumun sorunsuz çalıştığını gösteriyor:


Heroku'da yeniyseniz bu kılavuz size nasıl yeni bir hesap oluşturacağınızı ve Heroku CLI'yi nasıl yükleyeceğinizi gösterecektir.

Kabul Kriterleri Karşılandı: Müşterim 360 Örneği

GraphQL ile Müşteri 360 kullanım durumum için kabul kriterlerini aşağıdaki sorguyla karşılayabilirim:


 query CustomerData($token: String) { customer(token: $token) { name sic_code token }, address(customer_token: $token) { token customer_token address_line1 address_line2 city state postal_code }, contact(customer_token: $token) { token, customer_token, first_name, last_name, email, phone }, credit(customer_token: $token) { token, customer_token, credit_limit, balance, credit_score } }


Tek yapmam gereken customer-token-1 değerine sahip tek bir Customer token değişkenini iletmek:


 { "token": "customer-token-1" }


Tek bir GraphQL API çağrısı kullanarak tüm verilere ulaşabiliriz:


 { "data": { "customer": { "name": "Acme Inc.", "sic_code": "1234", "token": "customer-token-1" }, "address": { "token": "address-token-1", "customer_token": "customer-token-1", "address_line1": "123 Main St.", "address_line2": "", "city": "Anytown", "state": "CA", "postal_code": "12345" }, "contact": { "token": "contact-token-1", "customer_token": "customer-token-1", "first_name": "John", "last_name": "Doe", "email": "[email protected]", "phone": "123-456-7890" }, "credit": { "token": "credit-token-1", "customer_token": "customer-token-1", "credit_limit": 10000, "balance": 2500, "credit_score": 750 } } }


Aşağıda Heroku uygulamamdan çalıştırılan Apollo Explorer'ın ekran görüntüsü var:


Çözüm

Kariyerimin başlarında Java ve C#'ın geliştiricilerin benimsenmesi için birbirleriyle rekabet ettiği zamanları hatırlıyorum. Tartışmanın her iki tarafındaki savunucular, seçtikleri teknolojinin en iyi seçim olduğunu kanıtlamaya hazırdı… öyle olmasa bile.


Bu örnekte Müşteri 360 kullanım senaryomu birden fazla şekilde karşılayabilirdik. Kanıtlanmış bir RESTful API kullanmak işe yarayabilirdi ancak gerekli tüm verileri almak için birden fazla API çağrısı yapılması gerekirdi. Apollo Server ve GraphQL'i kullanmak, tek bir API çağrısıyla hedeflerime ulaşmamı sağladı.


Ayrıca terminalimdeki birkaç komutla GraphQL sunucumu Heroku'ya dağıtmanın ne kadar kolay olduğunu da seviyorum. Bu, altyapının yükünü hafifleterek ve kodumu güvenilir bir üçüncü taraf sağlayıcıda çalıştırarak uygulamaya odaklanmamı sağlıyor. En önemlisi, bu benim kişisel misyon beyanımla tam olarak örtüşüyor:


“Zamanınızı fikri mülkiyetinizin değerini artıran özellikler/işlevsellik sunmaya odaklayın. Diğer her şey için çerçevelerden, ürünlerden ve hizmetlerden yararlanın."

– J. Vester


Bu makalenin kaynak koduyla ilgileniyorsanız GitLab'da mevcuttur.


Ama durun… dahası da var!


Takip eden yazımda, aboneliklerle kimlik doğrulama ve gerçek zamanlı veri alımını uygulamak için GraphQL sunucumuzu daha da geliştireceğiz.


Gerçekten harika bir gün geçirin!