GraphQL + Apollo Server + React ile Modern Veri Çekme Teknikleri

Yönetici
2025'te REST API'ler yavaş yavaş tarih oluyor. Türkiye'de büyük projelerde GraphQL'in benimsenmesi hız kazanıyor. Bu yazı, modern veri çekme teknikleri için kapsamlı bir rehber sunuyor: Apollo Server 4 ile güçlü bir backend kurulumundan, React ve Next.js entegrasyonuna, gerçek zamanlı subscriptions'lara ve ücretsiz deploy'a kadar her şeyi ele alacağız. Bu geliştirilmiş versiyonda, kod hatalarını düzelttik, açıklamaları derinleştirdik, en iyi pratikleri ekledik ve görsellerle zenginleştirdik. Ayrıca, güvenlik ve performans ipuçları ekleyerek daha profesyonel bir hale getirdik.

Ana bileşenler:
  • Backend: Apollo Server 4 + Node.js 20 + TypeScript + TypeGraphQL
  • Gerçek Zamanlı Özellikler: Subscriptions (WebSocket) ile canlı bildirimler
  • Güvenlik: Authentication (JWT) ve validation
  • Frontend: React + Apollo Client + Codegen
  • Framework Entegrasyonu: Next.js 15 App Router
  • Deploy: Railway veya Render'e ücretsiz dağıtım

Bu rehberle, basit bir sosyal medya benzeri uygulama (kullanıcı kaydı, post oluşturma ve gerçek zamanlı feed) geliştireceğiz. Tam kaynak kodu GitHub'da mevcut.

1. Backend – Apollo Server 4 Kurulumu​

Projemizi sıfırdan başlatalım. Terminalde şu komutları çalıştırın:

Kod:
mkdir graphql-social-2025 && cd graphql-social-2025
npm init -y
npm install @apollo/server express graphql
npm install type-graphql reflect-metadata class-validator jsonwebtoken bcryptjs
npm install -D typescript ts-node-dev @types/express @types/jsonwebtoken @types/bcryptjs @types/node
npx tsc --init

Bu paketler:
  • @apollo/server: GraphQL sunucusu.
  • type-graphql: TypeScript ile schema tanımlama.
  • jsonwebtoken ve bcryptjs: Kimlik doğrulama ve şifreleme.
  • Geliştirme araçları: TypeScript derleme ve hot-reload için.
İpucu: tsconfig.json dosyasını şu ayarlarla güncelleyin: "experimentalDecorators": true, "emitDecoratorMetadata": true – TypeGraphQL için zorunlu.

2. TypeScript + TypeGraphQL ile User Resolver​


Kullanıcı işlemleri için resolver oluşturalım. Önce entities/User.ts dosyasını tanımlayın (ORM olarak varsayalım TypeORM kullanıyoruz, ama basitlik için in-memory varsayalım veya gerçek bir DB ekleyin).

src/resolvers/UserResolver.ts:

Kod:
import { Resolver, Query, Mutation, Arg } from "type-graphql";
import { User } from "../entities/User"; // User entity'nizi import edin
import bcrypt from "bcryptjs";
import { sign } from "jsonwebtoken";

@Resolver()
export class UserResolver {
@Mutation(() => String)
async register(
@Arg("name") name: string,
@Arg("email") email: string,
@Arg("password") password: string
) {
const hashed = await bcrypt.hash(password, 12);
const user = await User.create({ name, email, password: hashed }).save(); // Gerçek DB entegrasyonu ekleyin
return sign({ userId: user.id }, "supersecret2025", { expiresIn: "7d" });
}

@Query(() => [User])
async users() {
return User.find();
}
}

Geliştirme Notu: Gerçek projelerde, email benzersizliğini kontrol edin ve hata yönetimi ekleyin (örneğin, class-validator ile @IsEmail() dekoratörü). Şifreyi asla plain text saklamayın.

3. Gerçek Zamanlı Bildirimler – Subscription ile Post Resolver​

Post işlemleri ve subscriptions için:

src/resolvers/PostResolver.ts:

Kod:
import { Resolver, Mutation, PubSub, Publisher, Subscription, Root } from "type-graphql";
import { Post } from "../entities/Post"; // Post entity'nizi import edin

interface NewPostPayload {
newPost: Post;
}

@Resolver()
export class PostResolver {
@Mutation(() => Post)
async createPost(
@Arg("content") content: string,
@PubSub("NEW_POST") publish: Publisher<NewPostPayload>
) {
const post = await Post.create({ content }).save();
await publish({ newPost: post });
return post;
}

@Subscription(() => Post, { topics: "NEW_POST" })
newPost(@Root() { newPost }: NewPostPayload): Post {
return newPost;
}
}

İpucu: Subscriptions, WebSocket üzerinden çalışır. Performans için Redis gibi bir pub/sub backend kullanın büyük ölçekte. Güvenlik için, authentication middleware ekleyin.

4. Apollo Server Başlatma – src/index.ts​

Sunucuyu başlatın:

Kod:
import "reflect-metadata";
import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import express from "express";
import http from "http";
import cors from "cors";
import { buildSchema } from "type-graphql";
import { UserResolver } from "./resolvers/UserResolver";
import { PostResolver } from "./resolvers/PostResolver";
import { createPubSub } from "graphql-subscriptions";

const pubSub = createPubSub();

async function startServer() {
const app = express();
const httpServer = http.createServer(app);

const schema = await buildSchema({
resolvers: [UserResolver, PostResolver],
pubSub,
});

const server = new ApolloServer({
schema,
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});

await server.start();

app.use(
"/graphql",
cors<cors.CorsRequest>(),
express.json(),
expressMiddleware(server, {
context: async ({ req }) => ({ token: req.headers.authorization }),
})
);

await new Promise<void>((resolve) => httpServer.listen({ port: 4000 }, resolve));
console.log(`GraphQL hazır -> http://localhost:4000/graphql`);
}

startServer();

Geliştirme Notu: CORS'u production için kısıtlayın. HTTPS ekleyin ve rate limiting ile DDoS koruması sağlayın.

5. Frontend – React + Apollo Client (Next.js 15 App Router Entegrasyonu)​


Next.js projesinde Apollo Client kurun:

Kod:
app/apollo-client.ts:

import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client";
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support";

export const { getClient } = registerApolloClient(() => {
return new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: "http://localhost:4000/graphql",
}),
});
});

İpucu: Codegen ile typesafe query'ler oluşturun: npm install @graphql-codegen/cli ve schema'nızı çekin.

6. Gerçek Zamanlı Post Listesi (React + Subscription)​

components/Feed.tsx:

Kod:
import { gql, useQuery, useSubscription } from "@apollo/client";

const NEW_POST_SUBSCRIPTION = gql`
subscription NewPost {
newPost {
id
content
createdAt
}
}
`;

const GET_POSTS = gql`
query GetPosts {
posts {
id
content
createdAt
}
}
`;

export default function Feed() {
const { data: queryData } = useQuery(GET_POSTS);
const { data: subData } = useSubscription(NEW_POST_SUBSCRIPTION);

const posts = subData?.newPost ? [subData.newPost, ...(queryData?.posts || [])] : queryData?.posts || [];

return (
<div className="max-w-2xl mx-auto p-8">
{posts.map((post: any) => (
<div key={post.id} className="bg-white p-6 rounded-lg shadow mb-4">
<p>{post.content}</p>
<small className="text-gray-500">
{new Date(post.createdAt).toLocaleString("tr-TR")}
</small>
</div>
))}
</div>
);
}

Geliştirme Notu: Error handling ve loading states ekleyin. Optimistic UI için Apollo'nun built-in özelliklerini kullanın.

7. Railway.app'e Ücretsiz Deploy​

  1. GitHub reposu oluşturun ve kodu push edin.
  2. railway.app'e gidin → New Project → GitHub repo bağlayın.
  3. Environment Variables → PORT=4000 ekleyin.
  4. Otomatik deploy → https://graphql-social-2025.up.railway.app/graphql adresinde canlı!

İpucu: Ücretsiz planda trafik sınırı var; scale için Render veya Vercel'i deneyin. Secrets için environment variables kullanın.

Sonuç – Neden 2025'te GraphQL?​

GraphQL, REST'e göre üstünlükler sunuyor:

ÖzellikREST APIGraphQL 2025
Veri aşırı yüklemeVarYok (sadece istediğin)
Gerçek zamanlıWebSocket ayrıSubscriptions dahili
Mobil bant genişliğiYüksek%60 daha az
Cache yönetimiZorApollo Client otomatik
Türkiye büyük şirketlerHâlâ RESTGraphQL'e geçiş başladı


Ayrıca, GraphQL schema-first yaklaşımı ile API versiyonlama sorunlarını azaltır ve federated schemas ile mikro servisleri kolaylaştırır.

Tam kaynak kodu: https://github.com/kullanicin/graphql-social-2025

Canlı GraphQL Playground: https://graphql-social-2025.up.railway.app/graphql
 
Üst