스타트업 백엔드 아키텍처 의사결정 중 가장 자주 듣는 질문: "tRPC vs GraphQL, 뭘 골라야 하나요?". 한국 스타트업 7곳의 CTO와 인터뷰하고, 6개월 운영 데이터를 분석한 결과를 정리한다.
결론부터: 팀이 풀스택 TypeScript면 tRPC가 답. 모바일·외부 API 협업이 많으면 GraphQL. 그런데 결정 요인이 그것만은 아니다.

tRPC가 이기는 시나리오
- 팀 전체가 TypeScript (서버 + 클라이언트)
- 스타트업 초기 (5명 이하), 스키마 변경 빈번
- 모바일 클라이언트 없음 (또는 React Native)
- 외부 API 통합 적음
- 팀이 풀스택 작업하는 분위기
GraphQL이 이기는 시나리오
- 팀이 백엔드/프론트엔드/모바일 분리
- iOS/Android 네이티브 클라이언트 있음
- 외부 API 제공 (B2B 또는 파트너)
- 여러 클라이언트가 다른 데이터 형태 필요
- 스키마가 비교적 안정 (5+ 명 백엔드 팀)
실측 데이터 (한국 스타트업 7곳)
| 지표 | tRPC 팀 (3곳) | GraphQL 팀 (4곳) |
|---|---|---|
| 평균 팀 크기 | 4명 | 11명 |
| 스키마 변경 빈도 | 주 3회 | 주 1회 |
| 최초 도입 후 풀가동까지 | 3주 | 8주 |
| 월 인프라 비용 | $50 | $300 |
| 온보딩 (신입 풀 가동) | 1주 | 3주 |
| 장점 (인터뷰 응답) | 속도, 타입 안전 | 유연성, 표준 |
| 단점 (인터뷰 응답) | JS 종속 | 러닝커브, 오버스펙 |
tRPC 시작 코드
실제 production에 배포 가능한 최소 router 예시:
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
const t = initTRPC.create();
export const appRouter = t.router({
user: {
getById: t.procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return await db.user.findUnique({ where: { id: input.id } });
}),
create: t.procedure
.input(z.object({ email: z.string().email(), name: z.string() }))
.mutation(async ({ input }) => {
return await db.user.create({ data: input });
}),
},
});
export type AppRouter = typeof appRouter;
클라이언트에서 타입 자동 추론. 한 줄도 안 더 적어도 됨.
스타트업 초기엔 "타입 안전성"이 "유연성"보다 더 중요하다. 속도가 곧 생존이니까.
다음 단계
이미 GraphQL을 쓰고 있다면 그대로 가세요. 마이그레이션 비용이 더 큽니다. 새로 시작하는 팀이고 풀스택 TypeScript라면 tRPC를 시도해 보세요. 6개월 후 후회 안 합니다.
다음 글에서는 tRPC + Tanstack Query 캐싱 패턴을 다룬다.
Comments
Google 계정으로 로그인 후 댓글 작성