tRPC vs REST
tRPC(型安全なRPC、TypeScriptフルスタック)とREST API(言語非依存の標準)のAPI設計比較。型安全性、エコシステム、スケーラビリティを検証。
ゼロcodegen、エンドツーエンドのTypeScript型安全性
スキーマファースト、マルチクライアント向けのユニバーサルクエリ言語
状況に応じて判断すべきであり、「型安全性」という言葉単体はGraphQLを選ぶ理由にはならない。単一のTypeScriptモノレポ+単一のWebクライアントで運用しているなら、tRPCはほぼ常により少ない作業で済む——ゼロcodegenで、サーバー側の変更は即座にクライアント側のTSエラーとして現れる。モバイルアプリがある場合、外部開発者向けに公開するpublic APIがある場合、あるいは複数チームにまたがるフェデレーションが必要な場合は、GraphQLの言語非依存なスキーマ契約とApollo Federationエコシステムが構造的な優位性をもたらす。
| カテゴリー | tRPC | GraphQL |
|---|---|---|
| パフォーマンス | 7/10 | 6/10 |
| 学習のしやすさ | 8/10 | 5/10 |
| エコシステム | 6/10 | 9/10 |
| コミュニティ | 7/10 | 8/10 |
| 求人市場 | 5/10 | 8/10 |
| 将来性 | 7/10 | 8/10 |
// tRPC — ルーター定義(サーバー)
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
// db = Prisma/ORM クライアント(別ファイルからインポート)
const t = initTRPC.create();
export const appRouter = t.router({
getUser: t.procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return db.user.findUnique({ where: { id: input.id } });
}),
});
export type AppRouter = typeof appRouter;
// クライアント — サーバーの型が自動的に推論される、codegenなし
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './server';
const client = createTRPCClient<AppRouter>({
links: [httpBatchLink({ url: 'http://localhost:3000/trpc' })],
});
const user = await client.getUser.query({ id: '1' });
// user: { id: string; name: string; ... } — コンパイル時に完全な型安全性// graphql-js + @apollo/server — スキーマ、リゾルバー、サーバーを1ファイルに
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// db = Prisma/ORM クライアント(別ファイルからインポート)
const typeDefs = `#graphql
type Post {
id: ID!
title: String!
}
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Query {
user(id: ID!): User
}
`;
const resolvers = {
Query: {
user: (_parent, { id }, { db }) => db.user.findUnique({ where: { id } }),
},
User: {
posts: (user, _args, { db }) =>
db.post.findMany({ where: { authorId: user.id } }),
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, {
context: async () => ({ db }),
listen: { port: 4000 },
});
console.log(`サーバー起動完了: ${url}`);
// クライアントクエリ — 必要なフィールドのみが選択される:
// query { user(id: "1") { name posts { title } } }状況に応じて判断すべきであり、「型安全性」という言葉単体はGraphQLを選ぶ理由にはならない。単一のTypeScriptモノレポ+単一のWebクライアントで運用しているなら、tRPCはほぼ常により少ない作業で済む——ゼロcodegenで、サーバー側の変更は即座にクライアント側のTSエラーとして現れる。モバイルアプリがある場合、外部開発者向けに公開するpublic APIがある場合、あるいは複数チームにまたがるフェデレーションが必要な場合は、GraphQLの言語非依存なスキーマ契約とApollo Federationエコシステムが構造的な優位性をもたらす。
無料相談を受ける単一のTypeScriptモノレポで単一のWebクライアントのみを運用しているなら、tRPCの方が少ないコードと設定で済む(ゼロcodegen、エンドツーエンドのTS推論 — trpc.io)。モバイルアプリ、外部開発者向けのpublic API、あるいは複数の独立したサービスがある場合は、GraphQLのスキーマ契約とフェデレーションエコシステム(Apollo Federation)の方が適切な抽象化を提供する。