Yükleniyor...

GraphQL: Mobil Uygulama Geliştirmede Modern API Rehberi

Yazar: Burak Balkı | Kategori: Mobile Development | Okuma Süresi: 8 dk

GraphQL'in mobil uygulama geliştirmedeki rolünü, REST ile farklarını, şema tasarımını, Apollo entegrasyonunu ve performans optimizasyonlarını teknik detaylar...

## GraphQL Nedir ve Mobil Dünyada Neden Önemlidir? **GraphQL**, 2012 yılında Facebook tarafından geliştirilen ve 2015 yılında açık kaynak hale getirilen, API'lar için bir sorgulama dili ve mevcut verilerinizle bu sorguları yerine getirmek için kullanılan bir çalışma zamanıdır (runtime). Geleneksel REST mimarisinin aksine, GraphQL istemciye tam olarak neye ihtiyacı olduğunu sorma gücü verir. Mobil uygulama geliştirmede, bant genişliği kısıtlamaları ve değişken ağ hızları nedeniyle veri transferinin minimize edilmesi kritiktir. GraphQL, **over-fetching** (gereğinden fazla veri çekme) ve **under-fetching** (yetersiz veri çekme) sorunlarını ortadan kaldırarak mobil performansını maksimize eder. ## GraphQL Tip Sistemi (Type System) ve Şema Tasarımı GraphQL'in kalbinde güçlü bir tip sistemi yatar. Her GraphQL servisi, o serviste sorgulanabilecek verileri tanımlayan bir **Schema** (Şema) kullanır. Şema, istemcinin hangi verileri talep edebileceğini ve bu veriler arasındaki ilişkileri belirler. **SDL** (Schema Definition Language) kullanılarak yazılır. ```graphql type User { id: ID! username: String! email: String! posts: [Post] } type Post { id: ID! title: String! content: String author: User! } ``` Yukarıdaki örnekte `!` işareti, alanın **non-nullable** (boş olamaz) olduğunu belirtir. Bu yapısal disiplin, mobil geliştiricilerin API'dan ne tür bir veri döneceğini kesin olarak bilmesini sağlar ve çalışma zamanı hatalarını azaltır. ## Sorgu Yapısı: Query, Mutation ve Subscription Kavramları GraphQL üç ana operasyon tipi üzerine kuruludur: 1. **Query:** Veri okuma işlemleri için kullanılır. REST'teki GET isteğine tekabül eder. 2. **Mutation:** Veri yazma, güncelleme veya silme işlemleri için kullanılır. POST, PUT, DELETE işlemlerini kapsar. 3. **Subscription:** Gerçek zamanlı veri akışı sağlar. WebSockets protokolü üzerinden çalışır. ### Örnek Query ```graphql query GetUserProfile($userId: ID!) { user(id: $userId) { username email posts { title } } } ``` ### Örnek Mutation ```graphql mutation CreateNewPost($input: PostInput!) { createPost(input: $input) { id title } } ``` ## GraphQL vs. REST: Mobil Performans Karşılaştırması | Özellik | REST API | GraphQL | | :--- | :--- | :--- | | **Veri Çekme** | Çoklu endpoint, sabit veri yapısı | Tek endpoint, esnek veri yapısı | | **Over-fetching** | Yaygın (Gereksiz veri yükü) | Yok (Sadece istenen veri) | | **Hız** | Ağ gecikmesi (Latency) yüksek | Optimize edilmiş tek istek | | **Tip Güvenliği** | Zayıf (JSON şeması gerekebilir) | Güçlü (Dahili Tip Sistemi) | | **Versiyonlama** | v1, v2 gibi versiyonlama gerektirir | Versiyonlamaya gerek duymaz | ## GraphQL Sunucusu Kurulumu: Node.js ve Apollo Server Bir GraphQL ekosistemi kurmak için en popüler araçlardan biri **Apollo Server**'dır. Node.js üzerinde hızlıca bir sunucu ayağa kaldırmak için aşağıdaki yapı kullanılır: ```javascript const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type Book { title: String author: String } type Query { books: [Book] } `; const books = [ { title: 'The Awakening', author: 'Kate Chopin' }, { title: 'City of Glass', author: 'Paul Auster' }, ]; const resolvers = { Query: { books: () => books, }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`馃殌 Server ready at ${url}`); }); ``` ## Mobil İstemci Entegrasyonu: Apollo Client Kullanımı React Native veya Flutter gibi mobil frameworklerde GraphQL kullanmak için **Apollo Client** endüstri standardıdır. Apollo Client, verileri önbelleğe alır ve UI bileşenlerini otomatik olarak günceller. ```javascript import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'; const client = new ApolloClient({ uri: 'https://api.example.com/graphql', cache: new InMemoryCache() }); // Uygulama sarmalayıcı const App = () => ( ); ``` ## Fragments ve Directives ile Sorgu Optimizasyonu **Fragments**, tekrar eden sorgu parçalarını modüler hale getirmek için kullanılır. Özellikle büyük mobil projelerde kodun yeniden kullanılabilirliğini artırır. ```graphql fragment UserDetails on User { id username avatarUrl } query GetFeed { recentPosts { author { ...UserDetails } } } ``` **Directives** (@include, @skip) ise sorguları koşullu hale getirir. Örneğin, kullanıcının cihazı düşük veri modundaysa bazı alanları çekmemek için kullanılabilir: ```graphql query GetProduct($id: ID!, $withDetails: Boolean!) { product(id: $id) { name description @include(if: $withDetails) } } ``` ## GraphQL Güvenliği: Authentication ve Authorization GraphQL'de güvenlik, genellikle **Resolvers** seviyesinde veya bir **Middleware** katmanında yönetilir. REST'ten farklı olarak, tüm istekler tek bir endpoint üzerinden geldiği için yetkilendirme her alan (field) bazında yapılabilir. ```javascript const resolvers = { Query: { sensitiveData: (parent, args, context) => { if (!context.user) { throw new Error('Yetkisiz erişim!'); } return fetchData(); }, }, }; ``` > **Not:** GraphQL API'nizi korumak için sorgu derinliğini (query depth limiting) sınırlamak, kötü niyetli karmaşık sorguların sunucuyu çökertmesini engeller. ## Hata Yönetimi ve Debugging Stratejileri GraphQL'de HTTP durum kodu genellikle `200 OK` döner. Hatalar, JSON yanıtı içindeki bir `errors` dizisinde yer alır. Bu durum, mobil tarafta özel bir hata yakalama mekanizması gerektirir. ```json { "data": null, "errors": [ { "message": "User not found", "locations": [{ "line": 2, "column": 3 }], "path": ["user"] } ] } ``` ## Veri Önbelleğe Alma (Caching) ve State Yönetimi Apollo Client gibi kütüphaneler, **Normalized Cache** kullanarak verileri yerel bir veritabanı gibi yönetir. Bir sorgu sonucu dönen veri, `__typename` ve `id` kombinasyonu ile benzersiz bir şekilde saklanır. Bu sayede, aynı veri başka bir ekranda istendiğinde ağa gitmeden anında gösterilir. ```javascript import { useQuery, gql } from '@apollo/client'; const GET_USER = gql`query GetUser { user { id name } }`; function Profile() { const { loading, error, data } = useQuery(GET_USER); if (loading) return ; if (error) return ; return {data.user.name}; } ``` ## Modern Best Practices ve Mimari Yaklaşımlar 1. **Dataloader Kullanımı:** N+1 probleminden kaçınmak için veritabanı isteklerini batch haline getirin. 2. **Persisted Queries:** Sorgu boyutunu küçültmek ve güvenliği artırmak için sorgu hash'lerini kullanın. 3. **Schema First Approach:** Geliştirmeye şemayı tasarlayarak başlayın; bu, frontend ve backend ekiplerinin paralel çalışmasını sağlar. 4. **Pagination:** Büyük listeleri çekmek için `Relay-style cursor pagination` yapısını tercih edin. ## GraphQL'in Geleceği ve Sonuç GraphQL, mobil uygulama geliştirme süreçlerinde sağladığı esneklik ve performans kazanımları ile modern mimarilerin vazgeçilmez bir parçası haline gelmiştir. Özellikle mikroservis mimarilerinde bir **API Gateway** görevi görerek karmaşıklığı istemciden gizlemesi, geliştirici deneyimini (DX) en üst düzeye çıkarır. Mobil ekosistem büyüdükçe, veri verimliliği odaklı bu teknolojinin kullanımı artmaya devam edecektir. ---