• 30.10.2026 18:59:26
  • İbrahim Gökyar

Çalışan yazılımcılar için Spring tabanlı REST API tasarımında en iyi uygulamalar, WebMVC vs WebFlux tercihleri, sürümleme, güvenlik, hata yönetimi ve performans optimizasyonlarını örnek kodlarla ele alıyoruz.

Spring ile Modern REST API Tasarımı: Pratik Yaklaşımlar ve Örnekler

Bu makale, Spring Framework kullanarak üretim kalitesinde REST API'ler geliştirmek isteyen deneyimli yazılımcılar için hazırlandı. Temel mimari kararlarından güvenlik, sürümleme ve performans optimizasyonuna kadar hem klasik Spring WebMVC hem de reaktif WebFlux seçeneklerini, OpenAPI/HATEOAS gibi sözleşme yaklaşımlarını örneklerle ele alacağız.

Neden Spring REST?

Spring, Java ekosisteminde olgunlaşmış, geniş bir kütüphane ve topluluk desteği sunan bir çatı. Spring Boot sayesinde proje başlatmak hızlı, Spring MVC ise senkron REST servisleri için hâlâ en yaygın tercih. Ancak mikroservis ve yüksek concurrency senaryolarında reaktif WebFlux düşünülebilir.

Spring'in avantajları arasında bağımlılık yönetimi, görüntülenebilirlik (Actuator), kolay test yazımı ve entegrasyon imkanları öne çıkar. Bu yazıda hedef, "doğru" tekniği seçmek değil; kullanım senaryosuna göre bilinçli tercih yapmanızı sağlamaktır.

Spring WebMVC vs Spring WebFlux: Ne zaman hangisini seçmeli?

Spring WebMVC, Servlet tabanlı, bloklama I/O'ya dayalı bir modeldir. Geleneksel CRUD uygulamalar, veritabanı çağrıları I/O-bound değilse veya istek sayısı yönetilebilir düzeydeyse WebMVC basit ve verimlidir. Hızlı geliştirme, maturity ve uyum açısından genellikle tercih edilir.

WebFlux ise reaktif, non-blocking bir model sunar. Yüksek eşzamanlılık, uzun süre açık kalan bağlantılar (ör. SSE, WebSocket) veya reaktif veri akışları (Reactive Streams) gerektiren senaryolarda avantaj sağlar. Ancak veritabanı sürücüleri, kütüphaneler ve ekip tecrübesi reaktif modele uygun olmalı.

<!-- Basit bir WebMVC Controller örneği -->
@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService service;

    public UserController(UserService service) {
        this.service = service;
    }

    @GetMapping("/{id}")
    public ResponseEntity<UserDto> getById(@PathVariable Long id) {
        return service.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
}

Sözleşmeler: OpenAPI, HATEOAS ve Sürümleme

API sözleşmesi, ekipler arası entegrasyonlarda kaynak noktasını oluşturur. OpenAPI (Swagger) dokümantasyonu otomatik üretmek, istemciler ve testler için hayat kurtarıcıdır. Springdoc-OpenAPI veya Springfox modern çözümlerden biridir; springdoc daha güncel ve Spring Boot ile daha uyumludur.

HATEOAS, kaynaklara ilişki yönlendirmeleri ekleyerek API'yi keşfedilebilir kılar, ancak tüm projelerde gerekli değildir. Basit CRUD servisler için iyi dokümante edilmiş OpenAPI genelde yeterlidir. Sürümleme (v1, v2) için URL tabanlı (/api/v1/...) veya header tabanlı yaklaşımlar kullanılabilir; URL sürümleme anlaşılması ve cache uyumluluğu açısından pratiktir.

<!-- springdoc OpenAPI konfigürasyonu (basit) -->
@Configuration
public class OpenApiConfig {
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
            .info(new Info().title("User API").version("v1").description("Kullanıcı servisi"));
    }
}

Güvenlik, Kimlik Doğrulama ve İzinler

Spring Security, yetkilendirme ve kimlik doğrulama için en güçlü araç. JWT tabanlı token akışları mikroservis dünyasında yaygın. Token doğrulama, kısıtlı erişim noktaları ve rol bazlı izinler sunmanız gerektiğinde Spring Security'nin geniş özelleştirme imkanlarından yararlanın.

Pratik tavsiye: endpoint-level güvenliği ile method-level (@PreAuthorize) güvenliği birlikte kullanın. Ayrıca CORS ayarlarını dikkatli yapılandırın; istemci uygulamalarla entegrasyonlarda hatalar genelde yanlış CORS konfigürasyonundan kaynaklanır.

<!-- Basit JWT filtre örneği (konsept) -->
public class JwtAuthFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws ServletException, IOException {
        String token = resolveToken(req);
        if (token != null && validate(token)) {
            Authentication auth = getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(auth);
        }
        chain.doFilter(req, res);
    }
}

Hata Yönetimi ve Tutarlı Yanıt Yapıları

Tutarlı hata yanıtları, istemci tarafı ve otomatik testler için kritik. Spring'de @ControllerAdvice ile global hata yönetimi uygulayabilirsiniz. Yanıtları standart bir envelope (status, message, data, errors) yapısında döndürmek, loglama ve izleme açısından faydalıdır.

Validation için javax.validation (Bean Validation) kullanın ve hataları okunabilir biçimde toplayıp döndürün. Ayrıca correlation-id gibi istek-sitelerine izleme bilgileri ekleyerek dağıtık izlemeyi kolaylaştırın.

<!-- Basit Global Exception Handler -->
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity<ApiError> handleNotFound(EntityNotFoundException ex) {
        ApiError err = new ApiError("NOT_FOUND", ex.getMessage());
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(err);
    }

}

Performans, Ölçeklenebilirlik ve Operasyonel İpuçları

Öncelikle metrikleri (Prometheus, Micrometer) ve log düzeyini (structured logging) kurun; ölçmeden optimizasyon yapmak körleştirir. Spring Actuator, uygulamanın sağlık, metrik ve thread durumu gibi bilgilerini sağlar ve üretimde olmazsa olmazdır.

Veritabanı bağlantı havuzunu (HikariCP varsayılan) doğru boyutlandırın; I/O-bandwidth, sorgu optimizasyonu ve indeksleme sıklıkla en büyük performans kazançlarını verir. Cache katmanları (Redis, Caffeine) ile read-heavy yükleri rahatlatabilirsiniz. Ayrıca, isteklerinizi ölçün ve GC ayarlarını JVM profiline göre uyarlayın.

Modern Geçişler: Eski Yaklaşımlardan Günümüze

Geçmişte monolitik Spring uygulamaları yaygındı; bugün mikroservis, container ve Kubernetes temelli dağıtımlar daha revaçta. Geçiş planı yaparken küçük adımlarla hareket edin: öncelikle servis sınırlarını belirleyin, API sözleşmelerini sabit tutun ve sağlık kontrollerini ekleyin.

Ayrıca SOAP veya RPC tabanlı eski entegrasyonlarınız varsa REST/HTTP veya gRPC'ye aşamalı geçiş düşünün. gRPC, düşük gecikme ve sıkı veri şeması gerektiren servisler için iyi bir alternatiftir; ancak herkesin anlayacağı HTTP/JSON yerine ikili protokoller kullanır.

Sık Sorulan Sorular

1. WebFlux'e geçmeli miyim?

WebFlux'e geçiş, uygulamanızın gereksinimlerine bağlıdır. Yüksek eşzamanlılık, uzun süreli bağlantılar veya uçtan uca reaktif veri akışları gerekmiyorsa WebMVC yeterli ve daha az karmaşıktır. Reaktif ekosistem ve kullandığınız bağımlılıkların reaktif sürümlerinin olmasına dikkat edin.

2. API sürümlendirmesini nasıl yönetmeliyim?

URL tabanlı sürümlendirme (/api/v1/...) en basit ve cache uyumlu yaklaşımdır. Header tabanlı sürümlendirme daha şık olabilir ancak istemci karmaşıklığını artırır. Uzun vadede geriye dönük uyumluluk (backward compatibility) stratejisi belirleyin ve breaking change'leri minimize edin.

3. Hangi ölçümler (metrics) öncelikli olmalı?

İlk etapta yanıt süreleri (p95, p99), hata oranı, istek başına CPU ve bellek tüketimi, GC durumu ve veritabanı sorgu süreleri (slow queries) izlenmeli. Bu metrikler performans darboğazlarını hızlıca tespit etmenize yardımcı olur.

Sonuç

Spring ile REST API geliştirmek geniş bir konu ama doğru kararlar seçildikçe projeleriniz daha sürdürülebilir, güvenli ve performanslı olur. WebMVC mi yoksa WebFlux mi kullanılacağı, API sözleşmesi, güvenlik, hata yönetimi ve operasyonel ölçümler gibi alanlarda bilinçli tercihler yapın. Kod örnekleri ve prensipler burada bir başlangıç; gerçek projede takım tecrübesi ve mevcut altyapı göz önünde bulundurularak adım adım ilerleyin.

📚 Bu konuyu Opendart Akademi'de öğrenin: Spring Boot eğitimi · Java Spring Boot eğitimi hakkında · YouTube video dersleri · Abone ol