ASP.NET Core gRPC 앱의 gRPC-Web

작성자: James Newton-King

gRPC-Web 프로토콜을 사용하여 브라우저 앱에서 기존 ASP.NET Core gRPC 서비스를 호출할 수 있도록 구성하는 방법을 알아봅니다. gRPC-Web을 사용하여 브라우저 JavaScript 및 Blazor 앱에서 gRPC 서비스를 호출할 수 있습니다. 브라우저 기반 앱에서 HTTP/2 gRPC 서비스를 호출할 수는 없습니다. HTTP/2 gRPC와 함께 gRPC-Web을 지원하도록 ASP.NET Core에서 호스트된 gRPC 서비스를 구성할 수 있습니다.

기존 ASP.NET Core 앱에 gRPC 서비스를 추가하는 방법에 관한 지침은 ASP.NET Core 앱에 gRPC 서비스 추가를 참조하세요.

gRPC 프로젝트를 만드는 방법에 대한 지침은 ASP.NET Core에서 .NET Core gRPC 클라이언트 및 서버 만들기를 참조하세요.

ASP.NET Core gRPC-Web과 Envoy

ASP.NET Core 앱에 gRPC-Web을 추가하는 방법은 두 가지입니다.

  • ASP.NET Core에서 gRPC HTTP/2와 함께 gRPC-Web을 지원합니다. 이 옵션은 Grpc.AspNetCore.Web 패키지에서 제공하는 미들웨어를 사용합니다.
  • Envoy 프록시의 gRPC-Web 지원을 사용하여 gRPC-Web을 gRPC HTTP/2로 변환합니다. 그러면 변환된 호출이 ASP.NET Core 앱으로 전달됩니다.

각 접근 방식에는 장/단점이 있습니다. 앱 환경에서 Envoy를 프록시로 이미 사용하고 있는 경우 Envoy를 사용하여 gRPC-Web 지원을 제공하는 것이 적합할 수 있습니다. ASP.NET Core만 필요한 gRPC-Web을 위한 기본 솔루션의 경우 Grpc.AspNetCore.Web을 선택하는 것이 좋습니다.

ASP.NET Core에서 gRPC-Web 구성

HTTP/2 gRPC와 함께 gRPC-Web을 지원하도록 ASP.NET Core에서 호스트된 gRPC 서비스를 구성할 수 있습니다. gRPC-Web을 사용하기 위해 서비스를 변경할 필요는 없습니다. 유일한 수정 사항은 .에서 미들웨어를 설정하는 것입니다 Program.cs.

ASP.NET Core gRPC 서비스에서 gRPC-Web을 사용하도록 설정하려면 다음을 수행합니다.

  • Grpc.AspNetCore.Web 패키지에 대한 참조를 추가합니다.
  • Program.csUseGrpcWebEnableGrpcWeb을 추가하여 gRPC-Web을 사용하도록 앱을 구성합니다.
using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.UseGrpcWeb();

app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled and is callable from browser apps uisng the gRPC-Web protocal");

app.Run();

앞의 코드가 하는 역할은 다음과 같습니다.

  • 라우팅 이후, 엔드포인트 이전에 gRPC-Web 미들웨어인 UseGrpcWeb을 추가합니다.
  • EnableGrpcWeb을 사용하여 endpoints.MapGrpcService<GreeterService>() 메서드가 gRPC-Web을 지원하도록 지정합니다.

또는 모든 서비스가 기본적으로 gRPC-Web을 지원하고 EnableGrpcWeb이 필요하지 않도록 gRPC-Web 미들웨어를 구성할 수 있습니다. 미들웨어를 추가할 때 new GrpcWebOptions { DefaultEnabled = true }를 지정합니다.

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });

app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "All gRPC service are supported by default in this example, and are callable from browser apps uisng the gRPC-Web protocal");

app.Run();

참고 항목

.NET Core 3.x에서 HTTP.sys로 호스트될 때 gRPC-Web이 실패하는 알려진 문제가 있습니다.

gRPC-Web을 HTTP.sys에서 사용하기 위한 해결 방법은 Grpc-web 실험 및 UseHttpSys()?(grpc/grpc-dotnet #853)에 있습니다.

gRPC-Web 및 CORS

브라우저 보안 때문에 웹 페이지에서 해당 웹 페이지를 제공한 도메인이 아닌 다른 도메인에 요청을 수행할 수는 없습니다. 이 제한은 브라우저 앱에서 gRPC-Web 호출을 수행하는 데에도 적용됩니다. 예를 들어 https://www.contoso.com에서 제공하는 브라우저 앱은 https://services.contoso.com에서 호스트된 gRPC-Web 서비스를 호출할 수 없습니다. CORS(원본 간 리소스 공유)를 사용하여 이 제한을 완화할 수 있습니다.

브라우저 앱에서 원본 간 gRPC-Web 호출을 수행할 수 있게 하려면 ASP.NET Core에서 CORS를 설정합니다. 기본 제공 CORS 지원을 사용하고, WithExposedHeaders를 통해 gRPC 특정 헤더를 공개합니다.

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

builder.Services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
    builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));

var app = builder.Build();

app.UseGrpcWeb();
app.UseCors();

app.MapGrpcService<GreeterService>().EnableGrpcWeb()
                                    .RequireCors("AllowAll");

app.MapGet("/", () => "This gRPC service is gRPC-Web enabled, CORS enabled, and is callable from browser apps uisng the gRPC-Web protocal");

app.Run();

앞의 코드가 하는 역할은 다음과 같습니다.

  • AddCors를 호출하여 CORS 서비스를 추가하고 gRPC 특정 헤더를 공개하는 CORS 정책을 구성합니다.
  • UseCors를 호출하여 라우팅 구성 이후, 엔드포인트 구성 이전에 CORS 미들웨어를 추가합니다.
  • RequireCors를 사용하여 endpoints.MapGrpcService<GreeterService>() 메서드가 CORS를 지원하도록 지정합니다.

gRPC-Web 및 스트리밍

기존의 HTTP/2를 통한 gRPC는 클라이언트, 서버 및 양방향 스트리밍을 지원합니다. gRPC-Web은 스트리밍을 제한적으로 지원합니다.

  • gRPC-Web 브라우저 클라이언트는 클라이언트 스트리밍 및 양방향 스트리밍 메서드 호출을 지원하지 않습니다.
  • gRPC-Web .NET 클라이언트는 HTTP/1.1을 통해 클라이언트 스트리밍 및 양방향 스트리밍 메서드 호출을 지원하지 않습니다.
  • Azure App Service 및 IIS에서 호스트되는 ASP.NET Core gRPC 서비스는 양방향 스트리밍을 지원하지 않습니다.

gRPC-Web을 사용하는 경우 단항 메서드 및 서버 스트리밍 메서드를 사용하는 것이 좋습니다.

HTTP 프로토콜

.NET SDK에 포함된 ASP.NET Core gRPC 서비스 템플릿은 HTTP/2에 대해서만 구성된 앱을 만듭니다. 이는 앱이 기존의 HTTP/2를 통한 gRPC만 지원하는 경우에 좋은 기본값입니다. 그러나 gRPC-Web은 HTTP/1.1 및 HTTP/2 모두에서 작동합니다. UWP 또는 Unity와 같은 일부 플랫폼은 HTTP/2를 사용할 수 없습니다. 모든 클라이언트 앱을 지원하려면 HTTP/1.1 및 HTTP/2를 사용하도록 서버를 구성합니다.

appsettings.json에서 기본 프로토콜을 업데이트합니다.

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

또는 시작 코드에서 Kestrel 엔드포인트를 구성합니다.

동일한 포트에서 HTTP/1.1 및 HTTP/2를 사용하도록 설정하려면 프로토콜 협상을 위해 TLS가 필요합니다. 자세한 내용은 ASP.NET Core gRPC 프로토콜 협상을 참조하세요.

브라우저에서 gRPC-Web 호출

브라우저 앱은 gRPC-Web을 사용하여 gRPC 서비스를 호출할 수 있습니다. 브라우저에서 gRPC-Web을 사용하여 gRPC 서비스를 호출하는 경우 다음과 같은 몇 가지 요구 사항과 제한 사항이 있습니다.

  • 서버는 gRPC-Web을 지원하는 구성을 포함해야 합니다.
  • 클라이언트 스트리밍 및 양방향 스트리밍 호출이 지원되지 않습니다. 서버 스트리밍이 지원됩니다.
  • 다른 도메인에 있는 gRPC 서비스를 호출하려면 서버에 CORS 구성이 필요합니다.

JavaScript gRPC-Web 클라이언트

JavaScript gRPC-Web 클라이언트가 있습니다. JavaScript에서 gRPC-Web을 사용하는 방법에 대한 자세한 내용은 gRPC-Web을 사용하여 JavaScript 클라이언트 코드 작성을 참조하세요.

.NET gRPC 클라이언트를 사용하여 gRPC-Web 구성

gRPC-Web 호출을 수행하도록 .NET gRPC 클라이언트를 구성할 수 있습니다. 이 기능은 브라우저에서 호스트되고 JavaScript 코드와 동일한 HTTP 제한 사항이 있는 Blazor WebAssembly 앱에 유용합니다. .NET 클라이언트를 사용한 gRPC-Web 호출은 HTTP/2 gRPC와 동일합니다. 채널을 만드는 방법만 수정하면 됩니다.

gRPC-Web을 사용하려면 다음을 수행합니다.

  • Grpc.Net.Client.Web 패키지에 대한 참조를 추가합니다.
  • Grpc.Net.Client 패키지에 대한 참조가 버전 2.29.0 이상인지 확인합니다.
  • GrpcWebHandler를 사용하도록 채널을 구성합니다.
var channel = GrpcChannel.ForAddress("https://localhost:53305", new GrpcChannelOptions
{
    HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});

var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });

앞의 코드가 하는 역할은 다음과 같습니다.

  • gRPC-Web을 사용하도록 채널을 구성합니다.
  • 클라이언트를 만들고 채널을 사용하여 호출합니다.

GrpcWebHandler에는 다음과 같은 구성 옵션이 있습니다.

  • InnerHandler: gRPC HTTP 요청을 만드는 기본 HttpMessageHandler 입니다(예: .) HttpClientHandler.
  • GrpcWebMode: gRPC HTTP 요청 Content-Type 이 있는지 여부를 지정하는 열거형 형식입니다 application/grpc-webapplication/grpc-web-text.
    • GrpcWebMode.GrpcWeb은 인코딩 없이 콘텐츠를 전송하도록 구성합니다. 기본값입니다.
    • GrpcWebMode.GrpcWebText는 base64 인코딩된 텍스트를 구성합니다. 브라우저에서 서버 스트리밍 호출을 수행하는 데 필요합니다.
  • HttpVersion: 기본 gRPC HTTP 요청에 설정하는 HttpRequestMessage.Version 데 사용되는 HTTP 프로토콜 Version 입니다. gRPC-Web은 특정 버전이 필요하지 않으며, 지정하지 않을 경우 기본값을 재정의하지 않습니다.

Important

생성된 gRPC 클라이언트에는 단항 메서드를 호출하기 위한 동기 및 비동기 메서드가 있습니다. 예를 들어 SayHello는 동기식이며 SayHelloAsync는 비동기식입니다. Blazor WebAssembly에는 항상 비동기 메서드가 필요합니다. Blazor WebAssembly 앱에서 동기 메서드를 호출하면 앱이 응답하지 않게 됩니다.

gRPC-Web과 함께 gRPC 클라이언트 팩터리 사용

gRPC 클라이언트 팩터리를 사용하여 gRPC-Web과 호환되는 .NET 클라이언트를 만듭니다.

  • 다음 패키지에 대한 프로젝트 파일에 패키지 참조를 추가합니다.
  • 제네릭 AddGrpcClient 확장 메서드를 사용하여 DI(종속성 주입)에 gRPC 클라이언트를 등록합니다. Blazor WebAssembly 앱에서 서비스는 Program.cs의 DI에 등록됩니다.
  • ConfigurePrimaryHttpMessageHandler 확장 메서드를 사용하여 GrpcWebHandler를 구성합니다.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

자세한 내용은 .NET의 gRPC 클라이언트 팩터리 통합을 참조하세요.

추가 리소스

gRPC-Web 프로토콜을 사용하여 브라우저 앱에서 기존 ASP.NET Core gRPC 서비스를 호출할 수 있도록 구성하는 방법을 알아봅니다. gRPC-Web을 사용하여 브라우저 JavaScript 및 Blazor 앱에서 gRPC 서비스를 호출할 수 있습니다. 브라우저 기반 앱에서 HTTP/2 gRPC 서비스를 호출할 수는 없습니다. HTTP/2 gRPC와 함께 gRPC-Web을 지원하도록 ASP.NET Core에서 호스트된 gRPC 서비스를 구성할 수 있습니다.

기존 ASP.NET Core 앱에 gRPC 서비스를 추가하는 방법에 관한 지침은 ASP.NET Core 앱에 gRPC 서비스 추가를 참조하세요.

gRPC 프로젝트를 만드는 방법에 대한 지침은 ASP.NET Core에서 .NET Core gRPC 클라이언트 및 서버 만들기를 참조하세요.

ASP.NET Core gRPC-Web과 Envoy

ASP.NET Core 앱에 gRPC-Web을 추가하는 방법은 두 가지입니다.

  • ASP.NET Core에서 gRPC HTTP/2와 함께 gRPC-Web을 지원합니다. 이 옵션은 Grpc.AspNetCore.Web 패키지에서 제공하는 미들웨어를 사용합니다.
  • Envoy 프록시의 gRPC-Web 지원을 사용하여 gRPC-Web을 gRPC HTTP/2로 변환합니다. 그러면 변환된 호출이 ASP.NET Core 앱으로 전달됩니다.

각 접근 방식에는 장/단점이 있습니다. 앱 환경에서 Envoy를 프록시로 이미 사용하고 있는 경우 Envoy를 사용하여 gRPC-Web 지원을 제공하는 것이 적합할 수 있습니다. ASP.NET Core만 필요한 gRPC-Web을 위한 기본 솔루션의 경우 Grpc.AspNetCore.Web을 선택하는 것이 좋습니다.

ASP.NET Core에서 gRPC-Web 구성

HTTP/2 gRPC와 함께 gRPC-Web을 지원하도록 ASP.NET Core에서 호스트된 gRPC 서비스를 구성할 수 있습니다. gRPC-Web을 사용하기 위해 서비스를 변경할 필요는 없습니다. 유일한 수정 사항은 .에서 middelware를 설정하는 것입니다 Program.cs.

ASP.NET Core gRPC 서비스에서 gRPC-Web을 사용하도록 설정하려면 다음을 수행합니다.

  • Grpc.AspNetCore.Web 패키지에 대한 참조를 추가합니다.
  • Program.csUseGrpcWebEnableGrpcWeb을 추가하여 gRPC-Web을 사용하도록 앱을 구성합니다.
using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.UseGrpcWeb();

app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled and is callable from browser apps uisng the gRPC-Web protocal");

app.Run();

앞의 코드가 하는 역할은 다음과 같습니다.

  • 라우팅 이후, 엔드포인트 이전에 gRPC-Web 미들웨어인 UseGrpcWeb을 추가합니다.
  • EnableGrpcWeb을 사용하여 endpoints.MapGrpcService<GreeterService>() 메서드가 gRPC-Web을 지원하도록 지정합니다.

또는 모든 서비스가 기본적으로 gRPC-Web을 지원하고 EnableGrpcWeb이 필요하지 않도록 gRPC-Web 미들웨어를 구성할 수 있습니다. 미들웨어를 추가할 때 new GrpcWebOptions { DefaultEnabled = true }를 지정합니다.

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });

app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "All gRPC service are supported by default in this example, and are callable from browser apps uisng the gRPC-Web protocal");

app.Run();

참고 항목

.NET Core 3.x에서 HTTP.sys로 호스트될 때 gRPC-Web이 실패하는 알려진 문제가 있습니다.

gRPC-Web을 HTTP.sys에서 사용하기 위한 해결 방법은 Grpc-web 실험 및 UseHttpSys()?(grpc/grpc-dotnet #853)에 있습니다.

gRPC-Web 및 CORS

브라우저 보안 때문에 웹 페이지에서 해당 웹 페이지를 제공한 도메인이 아닌 다른 도메인에 요청을 수행할 수는 없습니다. 이 제한은 브라우저 앱에서 gRPC-Web 호출을 수행하는 데에도 적용됩니다. 예를 들어 https://www.contoso.com에서 제공하는 브라우저 앱은 https://services.contoso.com에서 호스트된 gRPC-Web 서비스를 호출할 수 없습니다. CORS(원본 간 리소스 공유)를 사용하여 이 제한을 완화할 수 있습니다.

브라우저 앱에서 원본 간 gRPC-Web 호출을 수행할 수 있게 하려면 ASP.NET Core에서 CORS를 설정합니다. 기본 제공 CORS 지원을 사용하고, WithExposedHeaders를 통해 gRPC 특정 헤더를 공개합니다.

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

builder.Services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
    builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));

var app = builder.Build();

app.UseGrpcWeb();
app.UseCors();

app.MapGrpcService<GreeterService>().EnableGrpcWeb()
                                    .RequireCors("AllowAll");

app.MapGet("/", () => "This gRPC service is gRPC-Web enabled, CORS enabled, and is callable from browser apps uisng the gRPC-Web protocal");

app.Run();

앞의 코드가 하는 역할은 다음과 같습니다.

  • AddCors를 호출하여 CORS 서비스를 추가하고 gRPC 특정 헤더를 공개하는 CORS 정책을 구성합니다.
  • UseCors를 호출하여 라우팅 구성 이후, 엔드포인트 구성 이전에 CORS 미들웨어를 추가합니다.
  • RequireCors를 사용하여 endpoints.MapGrpcService<GreeterService>() 메서드가 CORS를 지원하도록 지정합니다.

gRPC-Web 및 스트리밍

기존의 HTTP/2를 통한 gRPC는 클라이언트, 서버 및 양방향 스트리밍을 지원합니다. gRPC-Web은 스트리밍을 제한적으로 지원합니다.

  • gRPC-Web 브라우저 클라이언트는 클라이언트 스트리밍 및 양방향 스트리밍 메서드 호출을 지원하지 않습니다.
  • gRPC-Web .NET 클라이언트는 HTTP/1.1을 통해 클라이언트 스트리밍 및 양방향 스트리밍 메서드 호출을 지원하지 않습니다.
  • Azure App Service 및 IIS에서 호스트되는 ASP.NET Core gRPC 서비스는 양방향 스트리밍을 지원하지 않습니다.

gRPC-Web을 사용하는 경우 단항 메서드 및 서버 스트리밍 메서드를 사용하는 것이 좋습니다.

HTTP 프로토콜

.NET SDK에 포함된 ASP.NET Core gRPC 서비스 템플릿은 HTTP/2에 대해서만 구성된 앱을 만듭니다. 이는 앱이 기존의 HTTP/2를 통한 gRPC만 지원하는 경우에 좋은 기본값입니다. 그러나 gRPC-Web은 HTTP/1.1 및 HTTP/2 모두에서 작동합니다. UWP 또는 Unity와 같은 일부 플랫폼은 HTTP/2를 사용할 수 없습니다. 모든 클라이언트 앱을 지원하려면 HTTP/1.1 및 HTTP/2를 사용하도록 서버를 구성합니다.

appsettings.json에서 기본 프로토콜을 업데이트합니다.

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

또는 시작 코드에서 Kestrel 엔드포인트를 구성합니다.

동일한 포트에서 HTTP/1.1 및 HTTP/2를 사용하도록 설정하려면 프로토콜 협상을 위해 TLS가 필요합니다. 자세한 내용은 ASP.NET Core gRPC 프로토콜 협상을 참조하세요.

브라우저에서 gRPC-Web 호출

브라우저 앱은 gRPC-Web을 사용하여 gRPC 서비스를 호출할 수 있습니다. 브라우저에서 gRPC-Web을 사용하여 gRPC 서비스를 호출하는 경우 다음과 같은 몇 가지 요구 사항과 제한 사항이 있습니다.

  • 서버는 gRPC-Web을 지원하는 구성을 포함해야 합니다.
  • 클라이언트 스트리밍 및 양방향 스트리밍 호출이 지원되지 않습니다. 서버 스트리밍이 지원됩니다.
  • 다른 도메인에 있는 gRPC 서비스를 호출하려면 서버에 CORS 구성이 필요합니다.

JavaScript gRPC-Web 클라이언트

JavaScript gRPC-Web 클라이언트가 있습니다. JavaScript에서 gRPC-Web을 사용하는 방법에 대한 자세한 내용은 gRPC-Web을 사용하여 JavaScript 클라이언트 코드 작성을 참조하세요.

.NET gRPC 클라이언트를 사용하여 gRPC-Web 구성

gRPC-Web 호출을 수행하도록 .NET gRPC 클라이언트를 구성할 수 있습니다. 이 기능은 브라우저에서 호스트되고 JavaScript 코드와 동일한 HTTP 제한 사항이 있는 Blazor WebAssembly 앱에 유용합니다. .NET 클라이언트를 사용한 gRPC-Web 호출은 HTTP/2 gRPC와 동일합니다. 채널을 만드는 방법만 수정하면 됩니다.

gRPC-Web을 사용하려면 다음을 수행합니다.

  • Grpc.Net.Client.Web 패키지에 대한 참조를 추가합니다.
  • Grpc.Net.Client 패키지에 대한 참조가 버전 2.29.0 이상인지 확인합니다.
  • GrpcWebHandler를 사용하도록 채널을 구성합니다.
var channel = GrpcChannel.ForAddress("https://localhost:53305", new GrpcChannelOptions
{
    HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});

var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });

앞의 코드가 하는 역할은 다음과 같습니다.

  • gRPC-Web을 사용하도록 채널을 구성합니다.
  • 클라이언트를 만들고 채널을 사용하여 호출합니다.

GrpcWebHandler에는 다음과 같은 구성 옵션이 있습니다.

  • InnerHandler: gRPC HTTP 요청을 만드는 기본 HttpMessageHandler 입니다(예: .) HttpClientHandler.
  • GrpcWebMode: gRPC HTTP 요청 Content-Type 이 있는지 여부를 지정하는 열거형 형식입니다 application/grpc-webapplication/grpc-web-text.
    • GrpcWebMode.GrpcWeb은 인코딩 없이 콘텐츠를 전송하도록 구성합니다. 기본값입니다.
    • GrpcWebMode.GrpcWebText는 base64 인코딩된 텍스트를 구성합니다. 브라우저에서 서버 스트리밍 호출을 수행하는 데 필요합니다.
  • HttpVersion: 기본 gRPC HTTP 요청에 설정하는 HttpRequestMessage.Version 데 사용되는 HTTP 프로토콜 Version 입니다. gRPC-Web은 특정 버전이 필요하지 않으며, 지정하지 않을 경우 기본값을 재정의하지 않습니다.

Important

생성된 gRPC 클라이언트에는 단항 메서드를 호출하기 위한 동기 및 비동기 메서드가 있습니다. 예를 들어 SayHello는 동기식이며 SayHelloAsync는 비동기식입니다. Blazor WebAssembly에는 항상 비동기 메서드가 필요합니다. Blazor WebAssembly 앱에서 동기 메서드를 호출하면 앱이 응답하지 않게 됩니다.

gRPC-Web과 함께 gRPC 클라이언트 팩터리 사용

gRPC 클라이언트 팩터리를 사용하여 gRPC-Web과 호환되는 .NET 클라이언트를 만듭니다.

  • 다음 패키지에 대한 프로젝트 파일에 패키지 참조를 추가합니다.
  • 제네릭 AddGrpcClient 확장 메서드를 사용하여 DI(종속성 주입)에 gRPC 클라이언트를 등록합니다. Blazor WebAssembly 앱에서 서비스는 Program.cs의 DI에 등록됩니다.
  • ConfigurePrimaryHttpMessageHandler 확장 메서드를 사용하여 GrpcWebHandler를 구성합니다.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

자세한 내용은 .NET의 gRPC 클라이언트 팩터리 통합을 참조하세요.

추가 리소스

gRPC-Web 프로토콜을 사용하여 브라우저 앱에서 기존 ASP.NET Core gRPC 서비스를 호출할 수 있도록 구성하는 방법을 알아봅니다. gRPC-Web을 사용하여 브라우저 JavaScript 및 Blazor 앱에서 gRPC 서비스를 호출할 수 있습니다. 브라우저 기반 앱에서 HTTP/2 gRPC 서비스를 호출할 수는 없습니다. HTTP/2 gRPC와 함께 gRPC-Web을 지원하도록 ASP.NET Core에서 호스트된 gRPC 서비스를 구성할 수 있습니다.

기존 ASP.NET Core 앱에 gRPC 서비스를 추가하는 방법에 관한 지침은 ASP.NET Core 앱에 gRPC 서비스 추가를 참조하세요.

gRPC 프로젝트를 만드는 방법에 대한 지침은 ASP.NET Core에서 .NET Core gRPC 클라이언트 및 서버 만들기를 참조하세요.

ASP.NET Core gRPC-Web과 Envoy

ASP.NET Core 앱에 gRPC-Web을 추가하는 방법은 두 가지입니다.

  • ASP.NET Core에서 gRPC HTTP/2와 함께 gRPC-Web을 지원합니다. 이 옵션은 Grpc.AspNetCore.Web 패키지에서 제공하는 미들웨어를 사용합니다.
  • Envoy 프록시의 gRPC-Web 지원을 사용하여 gRPC-Web을 gRPC HTTP/2로 변환합니다. 그러면 변환된 호출이 ASP.NET Core 앱으로 전달됩니다.

각 접근 방식에는 장/단점이 있습니다. 앱 환경에서 Envoy를 프록시로 이미 사용하고 있는 경우 Envoy를 사용하여 gRPC-Web 지원을 제공하는 것이 적합할 수 있습니다. ASP.NET Core만 필요한 gRPC-Web을 위한 기본 솔루션의 경우 Grpc.AspNetCore.Web을 선택하는 것이 좋습니다.

ASP.NET Core에서 gRPC-Web 구성

HTTP/2 gRPC와 함께 gRPC-Web을 지원하도록 ASP.NET Core에서 호스트된 gRPC 서비스를 구성할 수 있습니다. gRPC-Web을 사용하기 위해 서비스를 변경할 필요는 없습니다. 시작 구성만 수정하면 됩니다.

ASP.NET Core gRPC 서비스에서 gRPC-Web을 사용하도록 설정하려면 다음을 수행합니다.

  • Grpc.AspNetCore.Web 패키지에 대한 참조를 추가합니다.
  • Startup.csUseGrpcWebEnableGrpcWeb을 추가하여 gRPC-Web을 사용하도록 앱을 구성합니다.
public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc();
}

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseGrpcWeb(); // Must be added between UseRouting and UseEndpoints

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb();
    });
}

앞의 코드가 하는 역할은 다음과 같습니다.

  • 라우팅 이후, 엔드포인트 이전에 gRPC-Web 미들웨어인 UseGrpcWeb을 추가합니다.
  • EnableGrpcWeb을 사용하여 endpoints.MapGrpcService<GreeterService>() 메서드가 gRPC-Web을 지원하도록 지정합니다.

또는 모든 서비스가 기본적으로 gRPC-Web을 지원하고 EnableGrpcWeb이 필요하지 않도록 gRPC-Web 미들웨어를 구성할 수 있습니다. 미들웨어를 추가할 때 new GrpcWebOptions { DefaultEnabled = true }를 지정합니다.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGrpc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

        app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapGrpcService<GreeterService>();
        });
    }
}

참고 항목

.NET Core 3.x에서 HTTP.sys로 호스트될 때 gRPC-Web이 실패하는 알려진 문제가 있습니다.

gRPC-Web을 HTTP.sys에서 사용하기 위한 해결 방법은 Grpc-web 실험 및 UseHttpSys()?(grpc/grpc-dotnet #853)에 있습니다.

gRPC-Web 및 CORS

브라우저 보안 때문에 웹 페이지에서 해당 웹 페이지를 제공한 도메인이 아닌 다른 도메인에 요청을 수행할 수는 없습니다. 이 제한은 브라우저 앱에서 gRPC-Web 호출을 수행하는 데에도 적용됩니다. 예를 들어 https://www.contoso.com에서 제공하는 브라우저 앱은 https://services.contoso.com에서 호스트된 gRPC-Web 서비스를 호출할 수 없습니다. CORS(원본 간 리소스 공유)를 사용하여 이 제한을 완화할 수 있습니다.

브라우저 앱에서 원본 간 gRPC-Web 호출을 수행할 수 있게 하려면 ASP.NET Core에서 CORS를 설정합니다. 기본 제공 CORS 지원을 사용하고, WithExposedHeaders를 통해 gRPC 특정 헤더를 공개합니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc();

    services.AddCors(o => o.AddPolicy("AllowAll", builder =>
    {
        builder.AllowAnyOrigin()
               .AllowAnyMethod()
               .AllowAnyHeader()
               .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
    }));
}

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseGrpcWeb();
    app.UseCors();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb()
                                                  .RequireCors("AllowAll");
    });
}

앞의 코드가 하는 역할은 다음과 같습니다.

  • AddCors를 호출하여 CORS 서비스를 추가하고 gRPC 특정 헤더를 공개하는 CORS 정책을 구성합니다.
  • UseCors를 호출하여 라우팅 구성 이후, 엔드포인트 구성 이전에 CORS 미들웨어를 추가합니다.
  • RequireCors를 사용하여 endpoints.MapGrpcService<GreeterService>() 메서드가 CORS를 지원하도록 지정합니다.

gRPC-Web 및 스트리밍

기존의 HTTP/2를 통한 gRPC는 클라이언트, 서버 및 양방향 스트리밍을 지원합니다. gRPC-Web은 스트리밍을 제한적으로 지원합니다.

  • gRPC-Web 브라우저 클라이언트는 클라이언트 스트리밍 및 양방향 스트리밍 메서드 호출을 지원하지 않습니다.
  • gRPC-Web .NET 클라이언트는 HTTP/1.1을 통해 클라이언트 스트리밍 및 양방향 스트리밍 메서드 호출을 지원하지 않습니다.
  • Azure App Service 및 IIS에서 호스트되는 ASP.NET Core gRPC 서비스는 양방향 스트리밍을 지원하지 않습니다.

gRPC-Web을 사용하는 경우 단항 메서드 및 서버 스트리밍 메서드를 사용하는 것이 좋습니다.

HTTP 프로토콜

.NET SDK에 포함된 ASP.NET Core gRPC 서비스 템플릿은 HTTP/2에 대해서만 구성된 앱을 만듭니다. 이는 앱이 기존의 HTTP/2를 통한 gRPC만 지원하는 경우에 좋은 기본값입니다. 그러나 gRPC-Web은 HTTP/1.1 및 HTTP/2 모두에서 작동합니다. UWP 또는 Unity와 같은 일부 플랫폼은 HTTP/2를 사용할 수 없습니다. 모든 클라이언트 앱을 지원하려면 HTTP/1.1 및 HTTP/2를 사용하도록 서버를 구성합니다.

appsettings.json에서 기본 프로토콜을 업데이트합니다.

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

또는 시작 코드에서 Kestrel 엔드포인트를 구성합니다.

동일한 포트에서 HTTP/1.1 및 HTTP/2를 사용하도록 설정하려면 프로토콜 협상을 위해 TLS가 필요합니다. 자세한 내용은 ASP.NET Core gRPC 프로토콜 협상을 참조하세요.

브라우저에서 gRPC-Web 호출

브라우저 앱은 gRPC-Web을 사용하여 gRPC 서비스를 호출할 수 있습니다. 브라우저에서 gRPC-Web을 사용하여 gRPC 서비스를 호출하는 경우 다음과 같은 몇 가지 요구 사항과 제한 사항이 있습니다.

  • 서버는 gRPC-Web을 지원하는 구성을 포함해야 합니다.
  • 클라이언트 스트리밍 및 양방향 스트리밍 호출이 지원되지 않습니다. 서버 스트리밍이 지원됩니다.
  • 다른 도메인에 있는 gRPC 서비스를 호출하려면 서버에 CORS 구성이 필요합니다.

JavaScript gRPC-Web 클라이언트

JavaScript gRPC-Web 클라이언트가 있습니다. JavaScript에서 gRPC-Web을 사용하는 방법에 대한 자세한 내용은 gRPC-Web을 사용하여 JavaScript 클라이언트 코드 작성을 참조하세요.

.NET gRPC 클라이언트를 사용하여 gRPC-Web 구성

gRPC-Web 호출을 수행하도록 .NET gRPC 클라이언트를 구성할 수 있습니다. 이 기능은 브라우저에서 호스트되고 JavaScript 코드와 동일한 HTTP 제한 사항이 있는 Blazor WebAssembly 앱에 유용합니다. .NET 클라이언트를 사용한 gRPC-Web 호출은 HTTP/2 gRPC와 동일합니다. 채널을 만드는 방법만 수정하면 됩니다.

gRPC-Web을 사용하려면 다음을 수행합니다.

  • Grpc.Net.Client.Web 패키지에 대한 참조를 추가합니다.
  • Grpc.Net.Client 패키지에 대한 참조가 버전 2.29.0 이상인지 확인합니다.
  • GrpcWebHandler를 사용하도록 채널을 구성합니다.
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
    {
        HttpHandler = new GrpcWebHandler(new HttpClientHandler())
    });

var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });

앞의 코드가 하는 역할은 다음과 같습니다.

  • gRPC-Web을 사용하도록 채널을 구성합니다.
  • 클라이언트를 만들고 채널을 사용하여 호출합니다.

GrpcWebHandler에는 다음과 같은 구성 옵션이 있습니다.

  • InnerHandler: gRPC HTTP 요청을 만드는 기본 HttpMessageHandler 입니다(예: .) HttpClientHandler.
  • GrpcWebMode: gRPC HTTP 요청 Content-Type 이 있는지 여부를 지정하는 열거형 형식입니다 application/grpc-webapplication/grpc-web-text.
    • GrpcWebMode.GrpcWeb은 인코딩 없이 콘텐츠를 전송하도록 구성합니다. 기본값입니다.
    • GrpcWebMode.GrpcWebText는 base64 인코딩된 텍스트를 구성합니다. 브라우저에서 서버 스트리밍 호출을 수행하는 데 필요합니다.
  • HttpVersion: 기본 gRPC HTTP 요청에 설정하는 HttpRequestMessage.Version 데 사용되는 HTTP 프로토콜 Version 입니다. gRPC-Web은 특정 버전이 필요하지 않으며, 지정하지 않을 경우 기본값을 재정의하지 않습니다.

Important

생성된 gRPC 클라이언트에는 단항 메서드를 호출하기 위한 동기 및 비동기 메서드가 있습니다. 예를 들어 SayHello는 동기식이며 SayHelloAsync는 비동기식입니다. Blazor WebAssembly에는 항상 비동기 메서드가 필요합니다. Blazor WebAssembly 앱에서 동기 메서드를 호출하면 앱이 응답하지 않게 됩니다.

gRPC-Web과 함께 gRPC 클라이언트 팩터리 사용

gRPC 클라이언트 팩터리를 사용하여 gRPC-Web과 호환되는 .NET 클라이언트를 만듭니다.

  • 다음 패키지에 대한 프로젝트 파일에 패키지 참조를 추가합니다.
  • 제네릭 AddGrpcClient 확장 메서드를 사용하여 DI(종속성 주입)에 gRPC 클라이언트를 등록합니다. Blazor WebAssembly 앱에서 서비스는 Program.cs의 DI에 등록됩니다.
  • ConfigurePrimaryHttpMessageHandler 확장 메서드를 사용하여 GrpcWebHandler를 구성합니다.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

자세한 내용은 .NET의 gRPC 클라이언트 팩터리 통합을 참조하세요.

추가 리소스