tRPC の魅力を紹介！型安全な API 開発でストレスフリーに

## 概要

近年、API の開発において **型安全性** や **開発効率の向上** が求められる中で、tRPC は非常に魅力的な選択肢となっています。しかし、tRPC を導入しているプロジェクトはまだ少なく、その利便性が十分に伝わっていないのが現状です。  

この記事では、**tRPC の魅力と活用方法** を詳しく解説し、導入を検討している方に向けてメリットをお伝えします。  

### この記事でわかること
- **RPC とは何か**
- **tRPC の特徴とメリット**
  - 型安全性による開発効率の向上
  - API の状態管理の簡素化
  - バリデーションチェックの容易さ
- **T3 Stack の紹介**

tRPC を活用することで、フロントエンドとバックエンドの型を統一し、よりスムーズな開発を実現できます。ぜひこの記事を参考に、tRPC の魅力を体感してください！

## そもそも RPC とは

RPC（Remote Procedure Call）は、遠隔にあるコンピュータの関数を呼び出す技術 です。簡単に言うと、ネットワークを介して別のコンピュータ上にある関数を、あたかもローカルにある関数のように呼び出すことができます。

### RPC の特徴
- **ローカル関数呼び出しと同じ感覚**: 開発者はネットワーク通信の複雑さを意識せず、関数を呼び出すだけでリモートの処理を実行できます

- **分散システムの構築に適している**: 複数のサーバー間で関数を呼び出し合うことで、大規模なシステムを構築しやすくなります

### 通常の関数呼び出し

```mermaid
sequenceDiagram
    participant Client
    Client->>Client: 関数実行
```
通常の関数呼び出しは、自身のプログラム内で関数を実行し、結果を受け取ります。

### RPC の関数呼び出し

```mermaid
sequenceDiagram
    participant Client
    participant Server
    Client->>Server: 関数呼び出し
    Server->>Server: 関数実行
    Server-->>Client: 結果を返す
```

通常の関数と異なり**ネットワークを介して**別のコンピュータで関数を実行。
  
## tRPC とは

tRPC は、TypeScript を使った RPC フレームワーク です。クライアントとサーバー間の通信を型安全かつ簡単に行えるよう設計されています。特に、フロントエンドとバックエンド間で型安全な API 呼び出しを実現するために作られました。

tRPC は、従来の REST API とは異なり、型定義を自動的に共有することで、クライアントとサーバ間の型不一致を防ぎます。これにより、API の変更に伴うエラーを未然に防ぎ、開発者がより安全にコードを書くことができます。


### サーバー側
以下はtRPCでサーバー側にプロシージャを定義する例です。このコードではZodを使って入力と出力の型を定義しています。

```ts:Server
export const postRouter = createTRPCRouter({
  hello: publicProcedure
    .input(z.object({ text: z.string() }))
    .query(({ input }) => {
      return {
        greeting: `Hello ${input.text}`,
      };
    }),
});
```

### クライアント側
クライアントでは、サーバー側で定義したプロシージャをTanStack Query 経由で呼び出します。


```ts:Client
  const { data } = api.post.hello.useQuery({ text: "world" });
```

![スクリーンショット 2025-02-12 21.23.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3231246/0cd0b0d3-cad3-4890-bf27-0261c76e35aa.png)

このように、クライアントとサーバー間で型が共有されているため、API呼び出し時のエラーが未然に防止されます。

## tRPC の実際に使ってみて良かった点

tRPC を実際に使ってみて、めちゃくちゃ良かったなと思った点を挙げてみました！これから tRPC を検討する方の参考になれば嬉しいです 🙌

---

### 1. 型安全に API の実装ができる🛡️

tRPC の最大の魅力は、**型安全性**です。TypeScript の型システムをフル活用できるので、クライアントとサーバー間の通信で型の不一致によるエラーがほぼなくなります。

**Zodとの連携が非常に効果的**: tRPC は Zod をサポートしており、API の入力（input）と出力（output）に対してバリデーションを簡単に定義できます。

```ts
  hello: publicProcedure
    .input(z.object({ text: z.string() }))
    .output(z.object({ greeting: z.string() }))
    .query(({ input }) => {
      return {
        greeting: `Hello ${input.text}`,
      };
    }),
```

- **入力バリデーション**: `input` でリクエストの型を定義し、不正なデータを防ぐ
- **出力バリデーション**: output でレスポンスの型を定義し、クライアントに返すデータの整合性を保証

### 2. API の状態管理が簡単 🚀

tRPC を使えば、API の状態管理が非常にシンプルになります。特に **TanStack Query** が組み込まれているため、データフェッチングやキャッシュ管理がスムーズに行えます。

- 従来は Server Component / Client Component それぞれで API クライアントを考える必要がありましたが、tRPC は TanStack Query と統合されているため、特に意識せずに実装可能です

#### Server Component でのデータ取得
```ts:Server Component
  // prefetch など
  const data = await api.post.hello({ text: "world" });
```

#### Client Component でのデータ取得
```ts:Client Component
  // usePrefetchQuery, useSuspenseQuery など
  const { data } = api.post.hello.useQuery({ text: "world" });
```


### 3. 柔軟なプロシージャ定義（Middleware の導入）🏗️

tRPC では、**関数ごとに呼び出しルールを定義**することが可能です。  
API ごとに middleware を設定できるイメージで、これを活用すると**認証済みユーザーのみが実行可能な API** などを簡単に実装できます。

#### 公開 API（認証不要）
```ts
export const publicProcedure = t.procedure;
```

#### 認証が必要な API
```ts
export const protectedProcedure = t.procedure
  .use(({ ctx, next }) => {
    if (!ctx.session || !ctx.session.user) {
      throw new TRPCError({ code: "UNAUTHORIZED" });
    }
    return next({
      ctx: {
        session: { ...ctx.session, user: ctx.session.user },
      },
    });
  });
```


### 4. デバッグがしやすい 🛠️

tRPC には、開発をスムーズにするためのデバッグ機能が備わっています。

以下のように**関数の引数・返り値・処理時間**を可視化できるため、API の動作を直感的に把握できます。

![スクリーンショット 2025-02-12 21.18.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3231246/a209833a-757b-4165-bb57-13f5641bbce8.png)

これにより、API の呼び出しがどのように行われたのかを簡単に確認でき、デバッグの効率が向上します。


## まとめ

tRPC を活用することで、以下のようなメリットを実感できます。

✅ 型安全な API 実装が可能（型の不一致によるバグを未然に防ぐ）
✅ API の状態管理が簡単（TanStack Query との統合）
✅ バリデーションチェックが容易（Zod を活用）
✅ デバッグがしやすい（API の処理を可視化）

フロントエンドとバックエンドの両方が TypeScript なら、tRPC を使わない理由は、ほとんどないのではないかと思います。あとは、Next.js の API Routes を BFF（Backend for Frontend）として活用する場合なども、tRPC は非常に有効です。

ぜひ一度触ってみてください！ 🎉

tRPC を触ってみたい方には、**T3 Stack** がおすすめです。

https://create.t3.gg/