Web Geliştirme

Next.js 15 ile Full-Stack Web Uygulaması Geliştirme

Fatih Algül
13.03.2026 208 görüntülenme

Next.js 15 Nedir ve Neden Tercih Edilmeli?

Next.js, React tabanlı web uygulamaları geliştirmek için kullanılan en popüler framework'lerden biridir. Vercel tarafından geliştirilen bu framework, sunucu taraflı render (SSR), statik site oluşturma (SSG), API rotaları ve çok daha fazlasını tek bir çatı altında sunar. Next.js 15 sürümü ile birlikte gelen yenilikler, full-stack web uygulaması geliştirmeyi her zamankinden daha kolay ve performanslı hale getirmiştir.

Next.js 15'in öne çıkan özellikleri şunlardır:

  • React 19 desteği ile en güncel React özelliklerine erişim
  • Turbopack ile çok daha hızlı geliştirme deneyimi
  • Server Actions ile sunucu taraflı işlemler için basitleştirilmiş API
  • Partial Prerendering (PPR) ile hibrit render stratejileri
  • Geliştirilmiş önbellekleme (caching) mekanizmaları
  • App Router ile dosya tabanlı yönlendirme sistemi

Proje Kurulumu

Yeni bir Next.js 15 projesi oluşturmak oldukça basittir. Terminal üzerinden aşağıdaki komutu çalıştırmanız yeterlidir:

npx create-next-app@latest my-fullstack-app
cd my-fullstack-app
npm run dev

Kurulum sırasında size TypeScript, ESLint, Tailwind CSS, App Router gibi seçenekler sunulacaktır. Full-stack bir uygulama geliştiriyorsanız, bu seçeneklerin hepsini aktif etmenizi öneririm. Özellikle App Router seçeneğini mutlaka işaretleyin çünkü Next.js 15'in tüm yeni özellikleri bu yapı üzerine inşa edilmiştir.

Proje oluşturulduktan sonra dizin yapısı şu şekilde olacaktır:

my-fullstack-app/
├── app/
│   ├── layout.tsx
│   ├── page.tsx
│   ├── globals.css
│   └── api/
│       └── ...
├── public/
├── next.config.ts
├── package.json
├── tailwind.config.ts
└── tsconfig.json

App Router ile Sayfa Yapısı

Next.js 15'te App Router, dosya sistemi tabanlı bir yönlendirme mekanizması sunar. app/ dizini altında oluşturduğunuz her klasör bir rota haline gelir. Örneğin app/dashboard/page.tsx dosyası /dashboard URL'ine karşılık gelir.

// app/dashboard/page.tsx
export default function DashboardPage() {
  return (
    <div className="container mx-auto p-6">
      <h1 className="text-3xl font-bold mb-4">Dashboard</h1>
      <p>Hoş geldiniz! Bu sizin kontrol panelinizdir.</p>
    </div>
  );
}

Layout dosyaları ile sayfalar arasında ortak bir yapı paylaşabilirsiniz. Bu, başlık (header), kenar çubuğu (sidebar) ve alt bilgi (footer) gibi bileşenler için idealdir:

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="flex min-h-screen">
      <aside className="w-64 bg-gray-800 text-white p-4">
        <nav>
          <ul>
            <li><a href="/dashboard">Ana Sayfa</a></li>
            <li><a href="/dashboard/settings">Ayarlar</a></li>
            <li><a href="/dashboard/profile">Profil</a></li>
          </ul>
        </nav>
      </aside>
      <main className="flex-1 p-6">{children}</main>
    </div>
  );
}

Server Components ve Client Components

Next.js 15'te bileşenler varsayılan olarak Server Component'tir. Bu, bileşenlerin sunucuda render edildiği ve istemciye yalnızca HTML olarak gönderildiği anlamına gelir. Bu yaklaşım, JavaScript bundle boyutunu küçültür ve sayfa performansını artırır.

Eğer bir bileşende tarayıcı taraflı etkileşim (state, event handler, hook vb.) kullanmanız gerekiyorsa, dosyanın başına "use client" direktifini eklemeniz gerekir:

// app/components/Counter.tsx
"use client";

import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div className="flex items-center gap-4">
      <button
        onClick={() => setCount(count - 1)}
        className="px-4 py-2 bg-red-500 text-white rounded"
      >
        -
      </button>
      <span className="text-2xl font-bold">{count}</span>
      <button
        onClick={() => setCount(count + 1)}
        className="px-4 py-2 bg-green-500 text-white rounded"
      >
        +
      </button>
    </div>
  );
}

Önemli kural: Mümkün olduğunca bileşenlerinizi Server Component olarak tutun. Yalnızca kullanıcı etkileşimi gerektiren bileşenleri Client Component yapın. Bu, uygulamanızın performansını önemli ölçüde artıracaktır.

Server Actions ile Veri İşlemleri

Next.js 15'in en güçlü özelliklerinden biri Server Actions'dır. Server Actions, form gönderimi ve veri mutasyonları gibi işlemleri doğrudan sunucuda çalıştırmanıza olanak tanır. Ayrı bir API endpoint oluşturmanıza gerek kalmaz.

// app/actions/user.ts
"use server";

import { revalidatePath } from "next/cache";

interface UserData {
  name: string;
  email: string;
}

export async function createUser(formData: FormData): Promise<void> {
  const name = formData.get("name") as string;
  const email = formData.get("email") as string;

  // Veritabanına kaydet (örnek: Prisma kullanımı)
  await prisma.user.create({
    data: { name, email },
  });

  // İlgili sayfanın önbelleğini temizle
  revalidatePath("/users");
}

export async function deleteUser(userId: string): Promise<void> {
  await prisma.user.delete({
    where: { id: userId },
  });

  revalidatePath("/users");
}

Bu Server Action'ı bir form içinde kullanmak son derece kolaydır:

// app/users/new/page.tsx
import { createUser } from "@/app/actions/user";

export default function NewUserPage() {
  return (
    <form action={createUser} className="max-w-md mx-auto space-y-4">
      <div>
        <label htmlFor="name" className="block text-sm font-medium">
          Ad Soyad
        </label>
        <input
          type="text"
          id="name"
          name="name"
          required
          className="mt-1 block w-full rounded border-gray-300 p-2"
        />
      </div>
      <div>
        <label htmlFor="email" className="block text-sm font-medium">
          E-posta
        </label>
        <input
          type="email"
          id="email"
          name="email"
          required
          className="mt-1 block w-full rounded border-gray-300 p-2"
        />
      </div>
      <button
        type="submit"
        className="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700"
      >
        Kullanıcı Oluştur
      </button>
    </form>
  );
}

Veritabanı Entegrasyonu: Prisma ile Çalışmak

Full-stack bir uygulamanın olmazsa olmazı veritabanıdır. Next.js projelerinde en yaygın kullanılan ORM aracı Prisma'dır. Kurulum için aşağıdaki adımları izleyin:

npm install prisma @prisma/client
npx prisma init

Prisma şemanızı tanımlayın:

// prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        String   @id @default(cuid())
  name      String
  email     String   @unique
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Post {
  id        String   @id @default(cuid())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

Prisma istemcisini tekil (singleton) olarak oluşturmak, geliştirme ortamında bağlantı sızıntılarını önler:

// lib/prisma.ts
import { PrismaClient } from "@prisma/client";

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined;
};

export const prisma = globalForPrisma.prisma ?? new PrismaClient();

if (process.env.NODE_ENV !== "production") {
  globalForPrisma.prisma = prisma;
}

Veri Çekme: Sunucu Taraflı Veri Yükleme

Next.js 15'te veri çekmek, Server Component'ler sayesinde son derece sezgiseldir. Doğrudan bileşen içinde async/await kullanarak veritabanınızdan veri çekebilirsiniz:

// app/users/page.tsx
import { prisma } from "@/lib/prisma";
import { deleteUser } from "@/app/actions/user";
import Link from "next/link";

export default async function UsersPage() {
  const users = await prisma.user.findMany({
    include: { posts: true },
    orderBy: { createdAt: "desc" },
  });

  return (
    <div className="container mx-auto p-6">
      <div className="flex justify-between items-center mb-6">
        <h1 className="text-3xl font-bold">Kullanıcılar</h1>
        <Link
          href="/users/new"
          className="bg-blue-600 text-white px-4 py-2 rounded"
        >
          Yeni Kullanıcı
        </Link>
      </div>
      <div className="grid gap-4">
        {users.map((user) => (
          <div key={user.id} className="border rounded p-4">
            <h2 className="text-xl font-semibold">{user.name}</h2>
            <p className="text-gray-600">{user.email}</p>
            <p className="text-sm text-gray-400">
              {user.posts.length} yazı
            </p>
          </div>
        ))}
      </div>
    </div>
  );
}

Middleware ile Kimlik Doğrulama

Full-stack uygulamalarda kimlik doğrulama kritik bir bileşendir. Next.js 15'te middleware kullanarak belirli rotalara erişimi kontrol edebilirsiniz:

// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  const token = request.cookies.get("session-token")?.value;

  // Korumalı rotalara erişim kontrolü
  if (request.nextUrl.pathname.startsWith("/dashboard")) {
    if (!token) {
      return NextResponse.redirect(new URL("/login", request.url));
    }
  }

  // Giriş yapmış kullanıcıları login sayfasından yönlendir
  if (request.nextUrl.pathname === "/login" && token) {
    return NextResponse.redirect(new URL("/dashboard", request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard/:path*", "/login"],
};

API Route'ları

Server Actions birçok kullanım senaryosunu karşılasa da, harici servisler veya webhook'lar için hâlâ API route'larına ihtiyaç duyabilirsiniz. Next.js 15'te Route Handler'lar şu şekilde tanımlanır:

// app/api/users/route.ts
import { prisma } from "@/lib/prisma";
import { NextRequest, NextResponse } from "next/server";

export async function GET() {
  const users = await prisma.user.findMany();
  return NextResponse.json(users);
}

export async function POST(request: NextRequest) {
  const body = await request.json();

  const user = await prisma.user.create({
    data: {
      name: body.name,
      email: body.email,
    },
  });

  return NextResponse.json(user, { status: 201 });
}

Turbopack ile Hızlı Geliştirme

Next.js 15, geliştirme sunucusu için Turbopack'i varsayılan olarak kullanır. Webpack'e kıyasla çok daha hızlı modül çözümleme ve Hot Module Replacement (HMR) sunan Turbopack, büyük projelerde bile anlık geri bildirim sağlar. Herhangi bir ek yapılandırma gerekmez; npm run dev komutu otomatik olarak Turbopack'i kullanacaktır.

Dağıtım (Deployment)

Next.js uygulamanızı dağıtmak için birkaç seçeneğiniz vardır:

  1. Vercel: Next.js'in resmi platformu olduğundan en sorunsuz deneyimi sunar. Git reponuzu bağlamanız yeterlidir.
  2. Docker: Kendi sunucunuzda çalıştırmak istiyorsanız Docker kullanabilirsiniz.
  3. Node.js sunucusu: next build ve next start komutları ile herhangi bir Node.js sunucusunda çalıştırabilirsiniz.
# Üretim derlemesi oluşturun
npm run build

# Üretim sunucusunu başlatın
npm run start

Sonuç ve Öneriler

Next.js 15, modern full-stack web uygulaması geliştirmek için ihtiyacınız olan hemen her şeyi sunan kapsamlı bir framework'tür. Server Components ile performanslı render, Server Actions ile basitleştirilmiş veri mutasyonları, App Router ile sezgisel yönlendirme ve Turbopack ile hızlı geliştirme deneyimi bir araya geldiğinde, son derece üretken bir geliştirme ortamı elde edersiniz.

Başarılı bir Next.js 15 projesi için şu önerileri aklınızda tutun:

  • Bileşenlerinizi mümkün olduğunca Server Component olarak tutun
  • Veri mutasyonları için Server Actions kullanmayı tercih edin
  • Veritabanı işlemleri için Prisma gibi güvenilir bir ORM seçin
  • Kimlik doğrulama için middleware katmanını etkin şekilde kullanın
  • TypeScript kullanarak tip güvenliği sağlayın
  • loading.tsx ve error.tsx dosyalarını her rota segmentinde tanımlayarak kullanıcı deneyimini iyileştirin
  • Önbellekleme stratejilerinizi bilinçli şekilde yönetin; revalidatePath ve revalidateTag fonksiyonlarını uygun yerlerde kullanın

Next.js ekosistemi hızla büyümeye devam ediyor. Resmi dokümantasyonu takip ederek ve topluluk kaynaklarını değerlendirerek bilginizi güncel tutabilirsiniz. Full-stack geliştirme dünyasında Next.js 15, hem küçük projeler hem de kurumsal ölçekli uygulamalar için güçlü ve esnek bir temel sunmaktadır.

Yazar Hakkında
Fatih Algül
TechSoft Solutions
Proje mi var?

Yazılım, IoT veya otomasyon konularında destek almak ister misiniz?

İletişime Geç