Frontend-Backend İletişimi ve BFF Pattern: Modern Web Uygulamalarında API Tasarımı
Modern web uygulamaları, frontend (SPA, mobil) ve backend (mikroservisler) arasında sağlam ve verimli bir iletişim hattı gerektirir. Ancak farklı frontend istemcileri (web, mobil, 3. parti) farklı veri formatları, performans gereksinimleri ve ağ koşullarına sahiptir. BFF (Backend for Frontend) deseni, her frontend istemcisi için özel bir backend katmanı oluşturarak bu farklılıkları yönetmeyi ve istemci-özel optimizasyonları mümkün kılmayı hedefler. Bu yazıda, frontend-backend iletişim yöntemlerini, API tasarım prensiplerini, BFF desenini ve .NET'te uygulama stratejilerini detaylıca ele alacağız.
1. Frontend-Backend İletişim Yöntemleri
| Yöntem | Açıklama | Avantajlar | Dezavantajlar | .NET Uygulama |
|---|---|---|---|---|
| REST (HTTP/JSON) | Kaynak odaklı, HTTP metotları (GET, POST, PUT, DELETE) kullanır. | Basit, yaygın, cacheable, idempotent. | Over/under-fetching sorunu, çok sayıda endpoint, büyük payload'lar. | ASP.NET Core Web API |
| GraphQL | İstemci, ihtiyaç duyduğu veriyi tek bir sorguda talep eder. | Over-fetching yok, tek endpoint, güçlü tip sistemi. | Öğrenme eğrisi, cache zorluğu, N+1 sorunu, karmaşık güvenlik. | Hot Chocolate, GraphQL.NET |
| gRPC | Protobuf ile binary serileştirme, HTTP/2 üzerinde çalışır. | Yüksek performans, düşük gecikme, güçlü contract, bi-directional streaming. | Tarayıcı desteği sınırlı (gRPC-Web), HTTP/2 zorunluluğu. | gRPC for .NET |
2. API Tasarımı ve Frontend İhtiyaçları
Modern frontend uygulamaları, backend API'lerinden farklı beklentilere sahiptir:
-
Özel Veri Şekilleri: Web, mobil veya TV uygulamaları farklı veri setlerine ve formatlarına ihtiyaç duyar.
-
Farklı Ağ Koşulları: Mobil istemciler daha yavaş ve güvenilmez ağlarda çalışır; daha küçük payload'lar ve daha az istek gerekir.
-
Güvenlik: Kimlik doğrulama ve yetkilendirme mekanizmaları (JWT, OAuth2) her istemci için tutarlı olmalıdır.
-
CORS: Tarayıcı tabanlı istemciler için CORS ayarlarının doğru yapılandırılması gerekir.
3. BFF (Backend for Frontend) Deseni
BFF, her frontend istemcisi (web, mobil, tablet) için ayrı bir backend katmanı oluşturmayı önerir. Bu katman, genel mikroservisleri çağırarak verileri toplar, dönüştürür ve istemcinin ihtiyaç duyduğu formatta sunar.
Neden BFF?
-
Over-fetching/Under-fetching'in Önlenmesi: İstemci sadece ihtiyacı olan veriyi alır.
-
Performans Optimizasyonu: Mobil cihazlar için daha az istek ve daha küçük payload.
-
Güvenlik: Genel API'leri doğrudan frontend'e açmak yerine BFF, güvenlik politikalarını merkezi olarak uygular.
-
Bağımsız Evrim: Frontend değişiklikleri, backend servislerini etkilemeden BFF üzerinden yapılabilir.
BFF Mimarisi (Örnek):
text
(Web BFF) --> Web Uygulaması
/
Servis A, B, C
\
(Mobil BFF) --> Mobil Uygulama
Her BFF, yalnızca o istemcinin ihtiyaç duyduğu endpoint'leri ve veri şekillerini sunar.
4. .NET'te BFF Uygulama Yöntemleri
A. Ayrı ASP.NET Core Web API Projeleri
En yaygın yöntem. Her frontend için ayrı bir API projesi oluşturulur.
csharp
// Web BFF Controller
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
[HttpGet]
public async Task<IEnumerable<ProductWebDto>> GetProducts()
{
// Servis çağrısı ve veri dönüşümü
var products = await _productService.GetAllAsync();
return products.Select(p => new ProductWebDto
{
Id = p.Id,
Name = p.Name,
Price = p.Price,
ImageUrl = p.ImageUrl
});
}
}
// Mobil BFF Controller
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
public async Task<IEnumerable<ProductMobileDto>> GetProducts()
{
// Mobil için farklı veri yapısı (ör. sadece id, name)
var products = await _productService.GetAllAsync();
return products.Select(p => new ProductMobileDto
{
Id = p.Id,
Name = p.Name
});
}
}
B. YARP (Yet Another Reverse Proxy) ile API Gateway + BFF
YARP, reverse proxy olarak kullanılabilir ve istekleri farklı BFF'lere veya doğrudan mikroservislere yönlendirebilir.
json
// YARP konfigürasyonu
{
"ReverseProxy": {
"Routes": {
"web-bff": {
"ClusterId": "web-bff-cluster",
"Match": { "Path": "/web/{**catch-all}" }
},
"mobile-bff": {
"ClusterId": "mobile-bff-cluster",
"Match": { "Path": "/mobile/{**catch-all}" }
}
},
"Clusters": {
"web-bff-cluster": { "Destinations": { "dest1": { "Address": "https://localhost:7001/" } } },
"mobile-bff-cluster": { "Destinations": { "dest1": { "Address": "https://localhost:7002/" } } }
}
}
}
C. Blazor ve BFF
Blazor WebAssembly ve Blazor Server, BFF ile doğal olarak çalışır. Blazor WASM, BFF üzerinden API çağrıları yaparak güvenliği ve performansı artırır.
5. BFF ile İlgili Sık Yapılan Hatalar
| Hata | Çözüm |
|---|---|
| Tüm iş mantığını BFF'e taşımak | BFF sadece koordinasyon ve veri dönüşümü yapmalı; iş mantığı mikroservislerde kalmalı. |
| Her frontend için ayrı BFF yerine tek BFF | Farklı istemci ihtiyaçlarını tek bir API'de birleştirmek ölçeklenebilirlik ve bakım zorlukları getirir. |
| Veri önbelleğini BFF'de yönetmemek | BFF, sık kullanılan verileri önbelleğe alarak performansı artırabilir. |
| Güvenlik kontrollerini BFF yerine mikroservislere dağıtmak | BFF, kimlik doğrulama ve yetkilendirmeyi merkezi olarak yönetmeli, mikroservisler güvenilir (trusted) olarak kabul edilmeli. |
6. Güvenlik ve Kimlik Doğrulama
-
JWT: BFF, kullanıcı token'ını doğrular ve güvenli bir şekilde mikroservislere iletebilir.
-
OAuth2 / OpenID Connect: BFF, authentication provider ile iletişim kurar ve token'ları yönetir.
-
CORS: BFF, frontend kaynaklarına (origins) izin verecek şekilde yapılandırılmalıdır.
csharp
// BFF'de JWT doğrulama
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://your-identity-server";
options.Audience = "bff-api";
});
7. API Gateway ve BFF Farkları
| Özellik | API Gateway | BFF |
|---|---|---|
| Amaç | Tüm istemciler için tek giriş noktası | İstemciye özel veri dönüşümü ve optimizasyon |
| Veri Dönüşümü | Sınırlı (genelde proxy) | Kapsamlı (DTO dönüşümü, veri birleştirme) |
| Ölçeklenebilirlik | Yüksek (her istemci için ayrı instance) | İstemci sayısı kadar BFF instance'ı |
| Kullanım | Routing, rate limiting, auth | Veri agreagasyonu, format dönüşümü, istemci özel logic |
Öneri: BFF'ler genellikle API Gateway'in arkasında çalışır. Gateway, routing ve güvenlik sağlar; BFF ise veri dönüşümü ve özel mantığı.
8. BFF Deseni Ne Zaman Kullanılmalı?
-
Birden fazla frontend istemcisi (web, mobil, desktop) varsa.
-
İstemciler farklı veri ihtiyaçlarına sahipse.
-
Güvenlik ve performans gereksinimleri istemciye göre değişiyorsa.
-
Mikroservis mimarisi kullanılıyorsa.
BFF Kullanılmaması Gereken Durumlar:
-
Basit, tek istemcili uygulamalar.
-
GraphQL veya gRPC kullanılıyorsa (bu araçlar zaten veri ihtiyaçlarını karşılıyorsa).
-
Küçük ekipler ve prototipler.
9. En İyi Pratikler
-
BFF'yi Hafif Tutun: İş mantığı yerine sadece koordinasyon ve veri dönüşümü yapmalıdır.
-
Doğru Veri Dönüşümü: DTO'lar kullanarak frontend'e özel veri yapıları oluşturun.
-
Önbellekleme: Sık kullanılan verileri BFF'de önbelleğe alın.
-
Hata Yönetimi: BFF, mikroservis hatalarını anlamlı HTTP status kodlarına dönüştürmelidir.
-
API Versiyonlama: BFF'ler, frontend sürümleriyle uyumlu olmalıdır.
-
Observability: BFF'leri loglamak ve izlemek, sorun tespitini kolaylaştırır.
Sonuç:
Frontend-backend iletişimi, modern uygulama mimarisinin belkemiğidir. REST, GraphQL veya gRPC arasındaki seçim, proje ihtiyaçlarına bağlıdır. BFF deseni ise, özellikle mikroservis ve çoklu-istemci ortamlarında, istemcilere özel optimize edilmiş bir API katmanı sunarak performans, güvenlik ve bakım kolaylığı sağlar.
.NET ekosistemi, BFF uygulamak için güçlü araçlar sunar: ASP.NET Core Web API, YARP, Blazor, JWT ve OAuth2 entegrasyonları. Doğru tasarlanmış bir BFF, frontend geliştiricilerinin backend ile etkileşimini basitleştirir ve uygulamanın ölçeklenebilirliğini artırır.