Swift Digest
Blog | Swift.org Blog

gRPC Swift 2 の発表

Introducing gRPC Swift 2

このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら

この記事の要点

何が発表されたのか

gRPC は、ネットワーク越しにシステム同士が効率的に通信するための、モダンで高性能なサービス API 構築フレームワークです。サービスとクライアントは別々の言語で書かれることが多いため、多くの gRPC サービスは Protocol Buffers(protobuf)を使って API とやり取りするメッセージを定義します。API の契約は、特定の実装に依存しない中立的な形式である .proto ファイルで記述します。これがサービスの土台となり、効率的なバイナリシリアライゼーションのおかげで、メッセージは JSON など他の標準形式よりも小さく高速に処理できます。

gRPC Swift は、この Protocol Buffers の契約をもとに Swift のコードを生成し、契約に沿ったクライアント・サーバーを簡単に構築できるようにするツールです。今回の gRPC Swift 2 は、Swift らしい(idiomatic)API と、cross-platform・高性能・多機能を兼ね備えたライブラリへの大きなアップデートです。

gRPC Swift が最初に開発された 2018 年当時、Swift にはまだ async/await などの並行処理機能がなく、SwiftNIO のイベント駆動型の並行処理モデルに基づいていました。これらの概念に馴染みのない開発者にとっては学習コストが高いものでしたが、Swift のモダンな並行処理モデルが定着した今、Apple での大規模サービス構築の経験を踏まえて、現在の Swift に合わせて gRPC Swift を再設計したのが gRPC Swift 2 です。

主なハイライトは次のとおりです。

何に使えるのか

挨拶を返すだけの典型的な「hello world」サービスを例にとると、.proto ファイルでは次のように API を定義します。

syntax = "proto3";

service GreetingService {
  // Returns a personalized greeting.
  rpc SayHello(SayHelloRequest) returns (SayHelloResponse);
}

message SayHelloRequest {
  // The name of the person to greet.
  string name = 1;
}

message SayHelloResponse {
  // The personalized greeting message.
  string message = 1;
}

この定義から、ビジネスロジックを実装するためのサービスコードと、サービスを呼び出すためのクライアントコードを生成できます。メッセージのコードは SwiftProtobuf が生成し、gRPC が生成するコードと組み合わせて使います。

生成されたサービスコードを使う

生成されるコードには、サービス定義の rpc ごとに 1 つのメソッドを持つ Swift のプロトコルが含まれます。ビジネスロジックを実装するには、このサービス用プロトコルのいずれかを実装します。下の例で使っている SimpleServiceProtocol は最も高レベルな API で、より柔軟性が必要な場合は簡潔さと引き換えに ServiceProtocolStreamingServiceProtocol も選べます。

サービスを起動するには、transport を設定したサーバーとサービスのインスタンスを作成します。

import GRPCCore
import GRPCNIOTransportHTTP2

struct Greeter: GreetingService.SimpleServiceProtocol {
  func sayHello(
    request: SayHelloRequest,
    context: ServerContext
  ) async throws -> SayHelloResponse {
    return SayHelloResponse.with {
      $0.message = "Hello, \(request.name)!"
    }
  }
}

@main
struct GreeterServer {
  static func main() async throws {
    // Create a plaintext server using the SwiftNIO based HTTP/2 transport
    // listening on 127.0.0.1:8080.
    let server = GRPCServer(
      transport: .http2NIOPosix(
        address: .ipv4(host: "127.0.0.1", port: 8080),
        transportSecurity: .plaintext
      ),
      services: [Greeter()]
    )

    // Start serving indefinitely.
    try await server.serve()
  }
}

生成されたクライアントコードを使う

クライアント側では、Swift らしいクライアントが生成され、サービスの呼び出しが簡単になります。まず生のクライアントを作成し、それをサービス専用の生成クライアントでラップします。これにより、型安全な方法でサービスとやり取りできます。

import GRPCCore
import GRPCNIOTransportHTTP2

@main
struct SayHello {
  static func main() async throws {
    // Create a plaintext client using the SwiftNIO based HTTP/2 transport
    // connecting to a service listening on 127.0.0.1:8080.
    try await withGRPCClient(
      transport: .http2NIOPosix(
        target: .dns(host: "127.0.0.1", port: 8080),
        transportSecurity: .plaintext
      )
    ) { client in
      let greeter = GreetingService.Client(wrapping: client)
      let greeting = try await greeter.sayHello(.with { $0.name = "swift.org" })
      print(greeting.message)
    }
  }
}

導入・今後の位置づけ

gRPC Swift 2 は柔軟性を重視して設計されており、複数のパッケージの集合として提供されます。必要なコンポーネントだけを選んで使えます。

始めるには、Swift Package Index 上のチュートリアルとドキュメントを参照するか、grpc/grpc-swift-2 リポジトリのサンプルを試すよう案内されています。機能リクエストやバグ報告、貢献は GitHub または Swift フォーラムで受け付けられています。

関連リンク