tRPCとは?TypeScriptでAPIの型安全性を高める注目のRPCフレームワーク

古川2022.09.30

TypeScriptによる静的型付けがWebアプリケーションのベストプラクティスの1つになりつつある昨今ですが、フロントエンドとバックエンド、もしくはBFF (Backends for Frontends)とのやりとりにおいて型を安全に保つ必要性が求められています。

この課題を解決するため、APIに静的な型をつけることができるtRPCというフレームワークが最近人気を博しているそうです。

そこで、今回はtRPCについて調べてみました。

RPC(Remote Procedure Call:リモートプロシージャコール)とは

そもそもRPCとは、ネットワークで接続された他のコンピューターでプログラムを呼び出し実行させるための手法、あるいはそのプロトコルのことを言います。

ネットワーク経由でプログラムの処理を呼び出し・実行することで、遠隔地にあるコンピューターが処理を行い、その処理結果を受け取ることができます。

分散システムにおいてネットワーク経由で遠隔地のコンピューターに処理を行わせるには、TCP/IPやUDPなどの低レベルの通信レイヤーを利用する必要があります。しかし、機能ごとにプロトコルを設計するのは非効率的なので、関数による呼び出しを抽象化し、共通規格にしたのがRPCです。

RPCは昔からある考え方でしたが、どのようなフォーマットでデータをやり取りするかは時代に応じて変化しています。例えばデータフォーマットにXMLを利用するXML-RPCや、JSONを利用するJSON-RCPがあります。これらは広く普及しているXMLやJSONを利用するため導入しやすいといった利点がありますが、テキストベースで情報を交換するので転送効率が悪く、バイナリ形式のデータが扱いにくいなどの問題がありました。

これらが抱えていた問題を解決するために考えられたのがgRPCというオープンソースのRPCフレームワークです。Googleが開発したプロトコルで、Protocol Buffersを使ってデータをシリアライズし、高速な通信を実現している点が特長です。また、C++/Python/Node/JavaScriptなど、さまざまな言語がサポートされています。

tRPCとは?

先ほどご紹介したgRPCと名前が似ているので、tRPCはgRPCと同じような技術なのかと思いきや、実際はそうでありません。tRPCはスキーマなどを必要とせず、APIエンドポイントを静的に型付けし、クライアントとサーバー間でそれを共有できるRPCフレームワークです。tRPCのtはTypeScriptを指します。

最近GitHubのスター数が急上昇していて、フロントエンド界隈では盛り上がりを見せているプロジェクトです。

なぜtRPCがこれほど人気なのかというと、理由はさまざまありますが、やはり「APIの型情報クライアントとサーバー間で簡単に共有できる」ところではないでしょうか。

APIとのやりとりで代表的なものといえばRESTful API(REST API)ですが、REST APIに静的な型を付けるには、何か別の仕組みを導入しなければいけません。有名なライブラリにaspidaというものがありますが、これを用いる際は、自分でAPI用の型定義ファイルを用意する必要があります。

また、GraphQLはAPIの定義にスキーマを利用しますが、この型をTypeScriptでも利用できるようにするには、型ファイルをジェネレーターなどを用いて生成する必要があります。

tRPCはというと、サーバー側で定義したAPI定義から型を取得する形で、クライアント側が利用できるというものです。クライアントとサーバー共通の型を用いることができるため、別途型定義ファイルを用意する必要がありません。そのためクライアントを開発するときに、サーバーが提供する型に完全に一致するオートコンプリートや、インテリセンスをエディタ上などで利用できます。

この辺りのざっくりとした仕組みをお伝えするため、Next.jsのAPI Routersを利用したtRPCのAPIの例をポイントを抜粋して見てみます。

// pages/api/trpc/[trpc].ts

import { initTRPC } from '@trpc/server';
import * as trpcNext from '@trpc/server/adapters/next';
import { z } from 'zod';

export const t = initTRPC.create();

export const appRouter = t.router({
  hello: t.procedure
    .input(
      z
        .object({
          text: z.string().nullish(),
        })
        .nullish(),
    )
    .query(({ input }) => {
      return {
        greeting: `hello ${input?.text ?? 'world'}`,
      };
    }),
});

// export type definition of API
export type AppRouter = typeof appRouter;

// export API handler
export default trpcNext.createNextApiHandler({
  router: appRouter,
  createContext: () => ({}),
});

このサンプルコードを簡単に説明すると、まず、appRouterという名前でRouterを定義しています。

続いてt.procedure.input()の部分で、入力された値を検証します。サンプルのコードでは、ZodというTypeScriptのバリデーションライブラリを利用しています。

t.procedure.query()では、クライアントにAPIが返却する内容を定義しています。

そしてその下のexport type AppRouteで、型定義のみをエクスポートしています。

この後サンプルではtRPCを利用するフックをcreateReactQueryHooksというtRPCが用意しているHooksで定義し、Context APIを使ってアプリケーション全体で利用できるように繋ぎ、クライアント側から以下のコードで呼び出します。フックなどを実装する際は、上記でエクスポートされている型定義を直接呼び出して使います。

続いて、APIを直接呼び出すクライアントの実装を見てみましょう。

// pages/index.tsx
import { trpc } from '../utils/trpc';

export default function IndexPage() {
  const hello = trpc.hello.useQuery({ text: 'client' });

if (!hello.data) {
    return <div>Loading...</div>;
  }

return (
    <div>
      <p>{hello.data.greeting}</p>
    </div>
  );
}

ここまで実装した上でNext.jsのローカルサーバーを起動し、ブラウザで表示すると「hello client」と表示されます。

上記をご覧いただくとわかる通り、フロントエンドにはなじみ深い技術や言語が使われているため、何をやっているのか初見でもなんとなく理解できると思います。

比較的学習コストが低いのかなと感じる反面、よくも悪くもAPIにおいてクライアントとサーバーが密結合になる点や、サーバー側もJavaScriptを使えることが前提になる点が気になります。

それらを考慮すると、ユースケースとしては、例えばフロントエンドがBFFを実装するといった場合が考えられるなと思いました。

また今回はNext.jsの例をご紹介しましたが、

tRPC comes with many adapters, allowing you to create a server using your favorite framework like Next.js, the Fetch API (Astro, Remix, SvelteKit, Cloudflare Workers, etc.), Express, Fastify, AWS Lambda, or a vanilla Node HTTP server.

と公式サイトにもあるように、tRPCではさまざまなAPIを提供するフレームワークやプラットフォームに対応しています。

まとめ

tRPCはフロントエンドとバックエンド間で型安全にやりとりを行うためのRPCフレームワークであることがわかりました。

tRPCの公式ドキュメントではさまざまなサンプルアプリを提供していますので、興味を持たれた方はぜひ参考にしてください。

最近、フロントエンド界隈でT3 Stackという考え方が提唱されているそうです。T3 Stackは「simplicity(シンプルさ)」「modularity(モジュール性)」「full-stack typesafety(フルスタックの型安全性)」に焦点を当てたWebアプリケーション開発の考え方です。3つの要素を備えたWebアプリケーションを開発するために、T3 Stackでは6つの技術スタックを提示しています。その中にtRPCが含まれているそうです。

マイクロサービスアーキテクチャを考える上で、各サービスが対話するための技術は非常に重要な役割を果たします。今の動向を見るに、モダンWebアプリケーション開発を行う上で「Type Safety (型安全性)」というキーワードは重要になってくるかもしれません。今後の動向に注目したいです。


ミツエーリンクスTSDでは一緒に働く仲間を募集中です!

オンライン面談にも対応しておりますので、みなさまのご応募お待ちしています!

エントリーはこちらから 📧

この記事を書いた人

古川

犬を2匹飼っています🐶🐶
ミツエーテックラジオでもスピーカーをしています。ぜひ聞いてください!

#tRPC#モダンアプリケーション#マイクロサービスアーキテクチャ

この記事をシェアする

この記事の目次