Dalam ekosistem .NET modern, ASP.NET Core Web API hampir selalu menjadi pilihan awal ketika developer ingin membangun layanan backend. Alasannya cukup kuat, karena model HTTP+JSON mudah dipahami, tooling-nya sudah matang, integrasi dengan browser dan mobile sangat baik, serta dokumentasinya sangat luas. Namun, kebutuhan sistem hari ini tidak lagi berhenti pada skenario CRUD sederhana. Banyak aplikasi berkembang menjadi beberapa service yang saling berkomunikasi secara intensif, dan di titik itulah pertanyaan penting mulai muncul: apakah REST masih cukup efisien untuk komunikasi antarservice?
Di sinilah gRPC menjadi relevan. Dalam dokumentasi resminya, Microsoft mendeskripsikan gRPC sebagai framework high-performance Remote Procedure Call (RPC) yang menggunakan Protocol Buffers sebagai format pesan default dan berjalan di atas HTTP/2. Pendekatan ini membuat gRPC unggul untuk skenario low-latency, high-throughput, contract-first API, dan polyglot environments. Dengan kata lain, gRPC bukan sekadar “REST versi lebih cepat”, tetapi pendekatan komunikasi yang memang dirancang untuk kebutuhan sistem terdistribusi modern.
Namun demikian, gRPC juga bukan pengganti total untuk REST. Microsoft secara eksplisit membandingkan gRPC dengan HTTP APIs/JSON dan menekankan bahwa masing-masing memiliki konteks penggunaan yang berbeda. REST tetap sangat relevan untuk browser-accessible APIs, integrasi publik, dan skenario yang membutuhkan payload yang mudah dibaca manusia. Sebaliknya, gRPC lebih tepat saat performa, kontrak layanan yang ketat, dan efisiensi jaringan menjadi prioritas utama.
Artikel ini membahas bagaimana mengintegrasikan ASP.NET Core Web API dengan gRPC, menggunakan studi kasus sederhana, sekaligus memberikan panduan praktis kapan gRPC layak dipilih dibanding REST API, dan kapan pendekatan hybrid justru menjadi keputusan yang paling tepat secara arsitektural.
Memahami Posisi REST dan gRPC di Arsitektur Modern
Sebelum masuk ke implementasi, penting untuk memahami bahwa REST dan gRPC berangkat dari filosofi yang berbeda. REST berorientasi pada resource dan HTTP semantics contohnya GET /products/1, POST /orders, dan sebagainya. Sementara itu, gRPC berorientasi pada service contract dan remote method invocation contohnya GetPrice(), CalculateDiscount(), atau CreateOrder(). Pada gRPC, kontrak layanan didefinisikan secara eksplisit melalui file .proto, lalu digunakan untuk menghasilkan client dan server code yang strongly typed.
Perbedaan tersebut berimplikasi langsung pada pengalaman pengembangan. Dalam REST, kita biasanya mendefinisikan DTO, route, controller, serta dokumentasi API secara terpisah. Dalam gRPC, file .proto menjadi pusat definisi layanan: di sana kita mendeskripsikan service, method, dan message, lalu tooling seperti Grpc.Tools akan menghasilkan class yang diperlukan di sisi client dan server. Microsoft menyebut pendekatan ini sebagai contract-first API development, dan inilah salah satu alasan mengapa gRPC sangat menarik untuk tim besar.
Dari sisi transport, gRPC memanfaatkan HTTP/2, yang membawa keuntungan seperti multiplexing, binary framing, dan efisiensi koneksi dibanding pola komunikasi HTTP/1.x tradisional. Selain itu, karena payload dikirim dalam format Protobuf yang bersifat biner, ukuran pesan cenderung lebih kecil daripada JSON, dan proses serialisasi/deserialisasinya lebih cepat. Microsoft secara spesifik merekomendasikan gRPC untuk microservices, network-constrained environments, dan point-to-point real-time communication.
Tetapi keunggulan tersebut datang dengan trade-off. Format pesan Protobuf tidak human-readable seperti JSON, dan browser tidak dapat mengakses gRPC native secara langsung tanpa pendekatan tambahan seperti gRPC-Web atau JSON transcoding. Karena itu, jika API ditujukan untuk frontend browser, partner eksternal, atau public integration, REST masih menjadi pilihan yang paling natural. Inilah alasan mengapa dalam banyak sistem produksi, REST dan gRPC justru dipakai berdampingan, bukan saling menggantikan.
Pola Integrasi yang Paling Realistis: REST di depan, gRPC di belakang
Dalam praktik enterprise, salah satu pola yang paling sering digunakan adalah API Gateway atau Backend-for-Frontend berbasis REST, yang kemudian berkomunikasi dengan service internal menggunakan gRPC. Pendekatan ini menjaga kenyamanan akses bagi klien eksternal sekaligus memungkinkan efisiensi tinggi pada komunikasi internal. Microsoft juga menegaskan bahwa aplikasi ASP.NET Core dapat menjalankan gRPC services sekaligus endpoint lain pada pipeline yang sama, sehingga integrasi ini sangat cocok pada platform .NET.
Secara sederhana, arsitektur ini dapat digambarkan seperti berikut:
[ Web / Mobile App ] | v [ ASP.NET Core Web API Gateway ] | gRPC call | v [ Internal Service ]
Pada model ini, klien eksternal tetap memanggil endpoint REST biasa, misalnya GET /api/products/1/price?qty=2&customerType=member. Namun di belakang layar, Web API meneruskan permintaan tersebut ke internal service menggunakan gRPC. Hasil akhirnya adalah sebuah sistem yang mudah diakses dari luar, tetapi lebih efisien untuk proses di dalam.
Contoh Solusi
Kita akan membuat dua project:
- Pricing.GrpcService → ASP.NET Core gRPC service.
- Gateway.Api → ASP.NET Core Web API yang memanggil gRPC service.
Secara konsep, gRPC service di ASP.NET Core di-host seperti service ASP.NET Core biasa dan terintegrasi penuh dengan fitur seperti DI, logging, authentication, authorization, dan routing ASP.NET Core.
Membuat gRPC Service
dotnet new grpc -n Pricing.GrpcService
Template gRPC bawaan .NET memang dibuat untuk mempermudah pembuatan service, dan di lingkungan development biasanya sudah dikonfigurasi dengan HTTPS/TLS. gRPC di ASP.NET Core memerlukan HTTP/2, dan endpoint gRPC pada Kestrel sebaiknya diamankan dengan TLS.
File price.proto
syntax = "proto3";option csharp_namespace = "Pricing.GrpcService";package pricing;service PriceCalculator { rpc GetPrice (PriceRequest) returns (PriceReply);}message PriceRequest { int32 productId = 1; int32 quantity = 2; string customerType = 3;}message PriceReply { int32 productId = 1; double unitPrice = 2; int32 quantity = 3; double discount = 4; double total = 5; string note = 6;}
Di gRPC, file .proto adalah pusat kontrak. File ini mendefinisikan service, method, dan message yang akan digunakan client dan server. Dari file ini, tooling seperti Grpc.Tools akan menghasilkan class C# untuk base service dan strongly-typed client.
Implementasi PriceCalculatorService.cs
using Grpc.Core;namespace Pricing.GrpcService.Services;public class PriceCalculatorService : PriceCalculator.PriceCalculatorBase{ public override Task<PriceReply> GetPrice(PriceRequest request, ServerCallContext context) { double unitPrice = request.ProductId switch { 1 => 150000, 2 => 250000, 3 => 50000, _ => 100000 }; double subtotal = unitPrice * request.Quantity; double discount = request.CustomerType?.ToLower() == "member" ? subtotal * 0.10 : 0; double total = subtotal - discount; return Task.FromResult(new PriceReply { ProductId = request.ProductId, UnitPrice = unitPrice, Quantity = request.Quantity, Discount = discount, Total = total, Note = request.CustomerType?.ToLower() == "member" ? "Member discount 10%" : "Regular price" }); }}
Program.cs untuk gRPC Service
using Pricing.GrpcService.Services;var builder = WebApplication.CreateBuilder(args);builder.Services.AddGrpc();var app = builder.Build();app.MapGrpcService<PriceCalculatorService>();app.MapGet("/", () => "Gunakan gRPC client untuk mengakses endpoint ini.");app.Run();
Konfigurasi AddGrpc() dan MapGrpcService<T>() adalah pola standar untuk mengaktifkan gRPC di ASP.NET Core.
Membuat ASP.NET Core Web API sebagai Gateway
dotnet new webapi -n Gateway.Api
Lalu copy file price.proto ke project ini, misalnya di folder Protos/.
Tambahkan package yang dibutuhkan
Pada Gateway.Api.csproj:
<ItemGroup> <PackageReference Include="Grpc.Net.Client" Version="2.*" /> <PackageReference Include="Google.Protobuf" Version="3.*" /> <PackageReference Include="Grpc.Tools" Version="2.*"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference></ItemGroup><ItemGroup> <Protobuf Include="Protos\price.proto" GrpcServices="Client" /></ItemGroup>
Pada sisi client, Grpc.Net.Client, Google.Protobuf, dan Grpc.Tools adalah paket yang umum dipakai untuk memanggil gRPC service dan menghasilkan class client dari .proto.
Konfigurasi Program.cs
using Pricing.GrpcService;var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();builder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();builder.Services.AddGrpcClient<PriceCalculator.PriceCalculatorClient>(o =>{ o.Address = new Uri("https://localhost:7042");});var app = builder.Build();if (app.Environment.IsDevelopment()){ app.UseSwagger(); app.UseSwaggerUI();}app.UseHttpsRedirection();app.MapControllers();app.Run();
Di dokumentasi resmi, client gRPC pada .NET dibangun menggunakan channel ke alamat service, lalu client strongly-typed digunakan untuk memanggil method seperti SayHelloAsync. Pada contoh ini saya menggunakan pola client registration di DI agar lebih sesuai untuk ASP.NET Core Web API. Secara konsep tetap sama: Web API akan bertindak sebagai gRPC client terhadap service pricing.
Controller REST yang Memanggil gRPC
using Microsoft.AspNetCore.Mvc;using Pricing.GrpcService;namespace Gateway.Api.Controllers;[ApiController][Route("api/products")]public class ProductsController : ControllerBase{ private readonly PriceCalculator.PriceCalculatorClient _pricingClient; public ProductsController(PriceCalculator.PriceCalculatorClient pricingClient) { _pricingClient = pricingClient; } [HttpGet("{id}/price")] public async Task<IActionResult> GetPrice( int id, [FromQuery] int qty = 1, [FromQuery] string customerType = "regular") { var reply = await _pricingClient.GetPriceAsync(new PriceRequest { ProductId = id, Quantity = qty, CustomerType = customerType }); return Ok(new { reply.ProductId, reply.UnitPrice, reply.Quantity, reply.Discount, reply.Total, reply.Note }); }}``
Dengan begitu, client eksternal tetap seolah olah sedang memanggil REST API biasa:
GET /api/products/1/price?qty=2&customerType=member
Tetapi di belakang layar, Web API meneruskan request ke gRPC service. Inilah inti integrasi yang sering dipakai di sistem enterprise: REST untuk compatibility, gRPC untuk efficiency. Karena gRPC client bersifat strongly typed dan contract-first, integrasi antarservice juga lebih minim mismatch dibanding model “manual DTO + manual parsing” yang umum terjadi di REST internal.
Alur Request
- Frontend memanggil REST endpoint di
Gateway.Api - Controller menerima parameter
productId,qty, dancustomerTypeController membentukPriceRequest - Controller memanggil
GetPriceAsync()ke gRPC service - gRPC service menghitung harga dan mengembalikan
PriceReply - Gateway mengonversi hasilnya ke JSON dan mengirim respons ke client
Kapan gRPC Lebih Tepat Dibanding REST API?
Gunakan gRPC ketika:
- Komunikasi antarservice sangat intensif: Cocok jika anda punya microservices yang sering saling memanggil, overhead transfer file JSON bisa terasa. Microsoft merekomendasikan gRPC untuk lightweight microservices karena low latency, high throughput, dan payload Protobuf yang lebih kecil dibanding JSON.
- Kamu ingin kontrak API yang ketat dan code generation otomatis: Dengan
.proto, service contract menjadi eksplisit. Client dan server dapat dibangkitkan otomatis, sehingga risiko ketidaksesuaian model data jauh berkurang. Ini sangat membantu pada tim besar atau environment multi-language. - Anda membutuhkan streaming: gRPC mendukung unary, server streaming, client streaming, dan bidirectional streaming. Ini sulit dicapai dengan REST murni tanpa menambah teknologi lain seperti WebSocket atau SSE.
- Sistem polyglot: Jika ada service .NET, Go, Java, Python, dan lainnya, gRPC sangat nyaman karena
.protomenjadi kontrak lintas bahasa. - Bandwidth terbatas atau payload besar: Protobuf bersifat biner dan lebih ringkas daripada JSON, sehingga cocok untuk lingkungan mobile/internal network yang sensitif terhadap ukuran payload.
Skenario dimana lebih prefer menggunakan REST
- API akan diakses langsung dari browser atau pihak ketiga: REST jauh lebih universal. Browser tidak bisa memanggil gRPC native secara langsung tanpa solusi tambahan seperti gRPC-Web atau JSON transcoding.
- Anda butuh API yang human-readable dan mudah diuji cepat: JSON lebih mudah diinspeksi lewat browser devtools, curl, Postman, atau log biasa. gRPC menggunakan Protobuf biner sehingga debugging “raw payload” tidak semudah menggunakan REST.
- Kasusnya hanya CRUD sederhana: Kalau use case sekadar create, read, update, delete sederhana dan konsumennya beragam, REST biasanya tetap paling praktis.
Skenario Hybrid
Untuk banyak aplikasi modern, pilihan terbaik adalah mengkombinasikan keduanya:
- REST API untuk frontend, mobile app, partner integration, dan public exposure
- gRPC untuk komunikasi internal antarservice
- JSON transcoding bila ingin satu service gRPC sekaligus dapat diakses sebagai HTTP/JSON tanpa menulis controller terpisah
Microsoft menjelaskan bahwa gRPC JSON transcoding memungkinkan method gRPC dipanggil sebagai HTTP+JSON dengan menambahkan metadata HTTP pada .proto. Pendekatan ini berjalan in-process di ASP.NET Core, sehingga lebih sederhana daripada reverse-proxy terpisah, dan tetap memungkinkan satu service melayani dua gaya akses: gRPC dan REST-style JSON. Namun perlu dicatat, pada transcoding, streaming terbatas pada server streaming; client streaming dan bidirectional streaming tidak didukung.
Tantangan Teknis yang Perlu Diperhatikan
Ada beberapa hal penting saat menggunakan gRPC di ASP.NET Core:
- HTTP/2 dan TLS: gRPC pada Kestrel memerlukan HTTP/2, dan endpoint-nya sebaiknya menggunakan TLS. Di development, template gRPC sudah membantu; di production kamu perlu memastikan konfigurasi Kestrel/IIS/HTTP.sys mendukung HTTP/2 + TLS.
- Browser support: ika konsumen utamanya browser, perlu dipikirkan sejak awal apakah akan memakai REST, gRPC-Web, atau JSON transcoding. Jangan langsung membuat semua endpoint dalam bentuk gRPC native lalu sadar belakangan bahwa browser tidak bisa mengaksesnya langsung.
- Desain contract
.proto: Karena.protomenjadi kontrak inti, desain field dan message perlu dibuat dengan disiplin. Keuntungannya, kontrak menjadi jauh lebih jelas dan perubahan interface lebih terkontrol.
Jadi kesimpulannya gunakan REST untuk kompatibilitas, gunakan gRPC untuk efisiensi, dan gunakan arsitektur hybrid ketika kamu butuh keduanya.
Leave a comment