C#을 사용하는 gRPC 서비스

이 문서에서는 C#으로 gRPC 앱을 작성하는 데 필요한 개념을 간략하게 설명합니다. 여기에서 설명하는 내용은 C-core 기반 gRPC 앱과 ASP.NET Core 기반 gRPC 앱에 모두 적용됩니다.

proto 파일

gRPC는 API 개발에 계약 중심 접근 방식을 사용합니다. 기본적으로 프로토콜 버퍼(protobuf)가 IDL(Interface Design Language)로 사용됩니다. .proto 파일에는 다음 항목이 포함되어 있습니다.

  • gRPC 서비스 정의
  • 클라이언트와 서버 간에 전송된 메시지

Protobuf 파일 구문에 대한 자세한 내용은 .NET 앱에 대한 Protobuf 메시지 만들기를 참조하세요.

예를 들어 gRPC 서비스 시작에서 사용된 greet.proto 파일의 내용은 다음과 같습니다.

  • Greeter 서비스를 정의합니다.
  • Greeter 서비스가 SayHello 호출을 정의합니다.
  • SayHelloHelloRequest 메시지를 보내고 HelloReply 메시지를 받습니다.
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

영어 이외의 언어로 번역된 코드 주석을 보려면 이 GitHub 토론 이슈에서 알려주세요.

C# 앱에 .proto 파일 추가

.proto 파일을 <Protobuf> 항목 그룹에 추가하여 프로젝트에 포함합니다.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

기본적으로 <Protobuf> 참조는 구체적인 클라이언트 및 서비스 기본 클래스를 생성합니다. reference 요소의 GrpcServices 특성을 사용하여 C# 자산 생성을 제한할 수 있습니다. 유효한 GrpcServices 옵션은 다음과 같습니다.

  • Both(없을 경우 기본값)
  • Server
  • Client
  • None

.proto 파일에 대한 C# 도구 지원

.proto 파일에서 C# 자산을 생성하려면 도구 패키지 Grpc.Tools가 필요합니다. 생성된 자산(파일)과 관련해서 다음 사항을 확인합니다.

  • 프로젝트를 빌드할 때마다 필요에 따라 생성됩니다.
  • 프로젝트에 추가되거나 소스 제어에 체크 인되지 않습니다.
  • obj 디렉터리에 포함된 빌드 아티팩트입니다.

이 패키지는 서버 프로젝트와 클라이언트 프로젝트에서 모두 필요합니다. Grpc.AspNetCore 메타패키지에는 Grpc.Tools에 대한 참조가 포함됩니다. 서버 프로젝트는 Visual Studio의 패키지 관리자를 사용하거나 프로젝트 파일에 <PackageReference>를 추가하여 Grpc.AspNetCore를 추가할 수 있습니다.

<PackageReference Include="Grpc.AspNetCore" Version="2.32.0" />

클라이언트 프로젝트는 gRPC 클라이언트를 사용하는 데 필요한 다른 패키지와 함께 Grpc.Tools를 직접 참조해야 합니다. 도구 패키지는 런타임에 필요하지 않으므로 종속성이 PrivateAssets="All"로 표시됩니다.

<PackageReference Include="Google.Protobuf" Version="3.18.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  <PrivateAssets>all</PrivateAssets>
</PackageReference>

생성된 C# 자산

도구 패키지는 포함된 .proto 파일에서 정의된 메시지를 나타내는 C# 형식을 생성합니다.

서버 쪽 자산의 경우, 추상 서비스 기본 형식이 생성됩니다. 기본 형식은 파일에 포함된 모든 gRPC 호출의 정의를 포함합니다 .proto . 이 기본 형식에서 파생되고 gRPC 호출의 논리를 구현하는 구체적인 서비스 구현을 만듭니다. 앞에서 설명한 예제인 greet.proto의 경우, 가상 SayHello 메서드를 포함하는 추상 GreeterBase 형식이 생성됩니다. 구체적인 구현 GreeterService는 메서드를 재정의하고, gRPC 호출을 처리하는 논리를 구현합니다.

public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }

    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

클라이언트 쪽 자산의 경우, 구체적인 클라이언트 형식이 생성됩니다. 파일의 .proto gRPC 호출은 구체적인 형식의 메서드로 변환되어 호출할 수 있습니다. 앞에서 설명한 예제인 greet.proto의 경우, 구체적인 GreeterClient 형식이 생성됩니다. GreeterClient.SayHelloAsync를 호출하여 서버에 대한 gRPC 호출을 시작합니다.

// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7042");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

기본적으로 <Protobuf> 항목 그룹에 포함된 각 .proto 파일에 대해 서버 자산과 클라이언트 자산이 생성됩니다. 서버 프로젝트에서 서버 자산만 생성되도록 하려면 GrpcServices 특성을 Server로 설정합니다.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

마찬가지로, 클라이언트 프로젝트에서는 특성을 Client로 설정합니다.

추가 리소스

이 문서에서는 C#으로 gRPC 앱을 작성하는 데 필요한 개념을 간략하게 설명합니다. 여기에서 설명하는 내용은 C-core 기반 gRPC 앱과 ASP.NET Core 기반 gRPC 앱에 모두 적용됩니다.

proto 파일

gRPC는 API 개발에 계약 중심 접근 방식을 사용합니다. 기본적으로 프로토콜 버퍼(protobuf)가 IDL(Interface Design Language)로 사용됩니다. .proto 파일에는 다음 항목이 포함되어 있습니다.

  • gRPC 서비스 정의
  • 클라이언트와 서버 간에 전송된 메시지

Protobuf 파일 구문에 대한 자세한 내용은 .NET 앱에 대한 Protobuf 메시지 만들기를 참조하세요.

예를 들어 gRPC 서비스 시작에서 사용된 greet.proto 파일의 내용은 다음과 같습니다.

  • Greeter 서비스를 정의합니다.
  • Greeter 서비스가 SayHello 호출을 정의합니다.
  • SayHelloHelloRequest 메시지를 보내고 HelloReply 메시지를 받습니다.
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

영어 이외의 언어로 번역된 코드 주석을 보려면 이 GitHub 토론 이슈에서 알려주세요.

C# 앱에 .proto 파일 추가

.proto 파일을 <Protobuf> 항목 그룹에 추가하여 프로젝트에 포함합니다.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

기본적으로 <Protobuf> 참조는 구체적인 클라이언트 및 서비스 기본 클래스를 생성합니다. reference 요소의 GrpcServices 특성을 사용하여 C# 자산 생성을 제한할 수 있습니다. 유효한 GrpcServices 옵션은 다음과 같습니다.

  • Both(없을 경우 기본값)
  • Server
  • Client
  • None

.proto 파일에 대한 C# 도구 지원

.proto 파일에서 C# 자산을 생성하려면 도구 패키지 Grpc.Tools가 필요합니다. 생성된 자산(파일)과 관련해서 다음 사항을 확인합니다.

  • 프로젝트를 빌드할 때마다 필요에 따라 생성됩니다.
  • 프로젝트에 추가되거나 소스 제어에 체크 인되지 않습니다.
  • obj 디렉터리에 포함된 빌드 아티팩트입니다.

이 패키지는 서버 프로젝트와 클라이언트 프로젝트에서 모두 필요합니다. Grpc.AspNetCore 메타패키지에는 Grpc.Tools에 대한 참조가 포함됩니다. 서버 프로젝트는 Visual Studio의 패키지 관리자를 사용하거나 프로젝트 파일에 <PackageReference>를 추가하여 Grpc.AspNetCore를 추가할 수 있습니다.

<PackageReference Include="Grpc.AspNetCore" Version="2.28.0" />

클라이언트 프로젝트는 gRPC 클라이언트를 사용하는 데 필요한 다른 패키지와 함께 Grpc.Tools를 직접 참조해야 합니다. 도구 패키지는 런타임에 필요하지 않으므로 종속성이 PrivateAssets="All"로 표시됩니다.

<PackageReference Include="Google.Protobuf" Version="3.11.4" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.28.1">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

생성된 C# 자산

도구 패키지는 포함된 .proto 파일에서 정의된 메시지를 나타내는 C# 형식을 생성합니다.

서버 쪽 자산의 경우, 추상 서비스 기본 형식이 생성됩니다. 기본 형식은 파일에 포함된 모든 gRPC 호출의 정의를 포함합니다 .proto . 이 기본 형식에서 파생되고 gRPC 호출의 논리를 구현하는 구체적인 서비스 구현을 만듭니다. 앞에서 설명한 예제인 greet.proto의 경우, 가상 SayHello 메서드를 포함하는 추상 GreeterBase 형식이 생성됩니다. 구체적인 구현 GreeterService는 메서드를 재정의하고, gRPC 호출을 처리하는 논리를 구현합니다.

public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }

    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

클라이언트 쪽 자산의 경우, 구체적인 클라이언트 형식이 생성됩니다. 파일의 .proto gRPC 호출은 구체적인 형식의 메서드로 변환되어 호출할 수 있습니다. 앞에서 설명한 예제인 greet.proto의 경우, 구체적인 GreeterClient 형식이 생성됩니다. GreeterClient.SayHelloAsync를 호출하여 서버에 대한 gRPC 호출을 시작합니다.

static async Task Main(string[] args)
{
    // The port number(5001) must match the port of the gRPC server.
    using var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(
                      new HelloRequest { Name = "GreeterClient" });
    Console.WriteLine("Greeting: " + reply.Message);
    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
}

기본적으로 <Protobuf> 항목 그룹에 포함된 각 .proto 파일에 대해 서버 자산과 클라이언트 자산이 생성됩니다. 서버 프로젝트에서 서버 자산만 생성되도록 하려면 GrpcServices 특성을 Server로 설정합니다.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

마찬가지로, 클라이언트 프로젝트에서는 특성을 Client로 설정합니다.

추가 리소스