tRPC 소개
이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →
tRPC는 타입을 선언하지 않고도 (Node) 서버부터 클라이언트까지 종단간 타입 안전성을 제공합니다. 백엔드에서는 단순히 함수에서 데이터를 반환하기만 하면, 프론트엔드에서는 엔드포인트 이름을 기반으로 해당 데이터를 사용할 수 있습니다.
👋 저는 GitHub에서 "KATT"로 알려진 Alex입니다. tRPC라는 라이브러리를 소개하려 합니다. 아직 관련 글을 발행한 적은 없지만(이미 GitHub에서 >530 🌟를 달성했습니다), 시작을 알리는 간단한 소개를 작성합니다. 향후 문서와 동영상 소개가 예정되어 있으니 기대해 주세요! 최신 소식을 받거나 질문이 있다면 트위터 @alexdotjs를 팔로우해 주세요.
tRPC 엔드포인트 및 클라이언트 호출 시 모습 예시:

React 전용 라이브러리(@trpc/react)를 제작했으며, 이는 훌륭한 react-query 위에서 동작합니다. 클라이언트 라이브러리(@trpc/client)는 React 없이도 작동합니다(Svelte/Vue/Angular/[..] 전용 라이브러리를 구축하고 싶다면 문의 주세요!).
코드 생성이 전혀 필요하지 않으며, 기존 Next.js/CRA/Express 프로젝트에 쉽게 통합할 수 있습니다.
예시
다음은 string 인수를 받는 hello라는 tRPC 프로시저(엔드포인트) 예시입니다.
tsxconst appRouter = trpc.router().query('hello', {input: z.string().optional(),resolve: ({ input }) => {return {text: `hello ${input ?? 'world'}`,};},});export type AppRouter = typeof appRouter;
tsxconst appRouter = trpc.router().query('hello', {input: z.string().optional(),resolve: ({ input }) => {return {text: `hello ${input ?? 'world'}`,};},});export type AppRouter = typeof appRouter;
다음은 해당 데이터를 사용하는 타입 안전 클라이언트 예시입니다:
tsximport type { AppRouter } from './server';async function main() {const client = createTRPCClient<AppRouter>({url: `http://localhost:2022`,});const result = await client.query('hello', '@alexdotjs');console.log(result); // --> { text: "hello @alexdotjs" }}main();
tsximport type { AppRouter } from './server';async function main() {const client = createTRPCClient<AppRouter>({url: `http://localhost:2022`,});const result = await client.query('hello', '@alexdotjs');console.log(result); // --> { text: "hello @alexdotjs" }}main();
타입 안전성을 확보하는 데 필요한 전부입니다! result 타입은 백엔드 함수 반환 값에서 추론됩니다. 입력 데이터 또한 검증기 반환 값에서 추론되므로 데이터를 바로 안전하게 사용할 수 있습니다. 실제로 입력 데이터는 검증기를 통과해야 합니다(tRPC는 zod/yup/커스텀 검증기와 즉시 호환됩니다).
위 예시를 직접 확인할 수 있는 CodeSandbox 링크: https://githubbox.com/trpc/trpc/tree/main/examples/standalone-server (미리보기보다 터미널 출력을 확인해 주세요!)
잠깐? 백엔드 코드를 클라이언트로 임포트한다고? - 사실 아닙니다
겉보기에는 그렇게 보일 수 있지만, 서버에서 클라이언트로 실제 코드가 공유되지는 않습니다. TypeScript의 import type은 "[...] 타입 주석 및 선언에 사용할 선언만 임포트합니다. 항상 완전히 삭제되어 런타임에 흔적이 남지 않습니다." - TypeScript 3.8에 추가된 기능 - TypeScript 문서 참조.
코드 생성이 필요 없으며, 서버에서 클라이언트로 타입을 공유할 수 있는 환경만 있다면(모노레포 사용을 권장합니다) 바로 적용 가능합니다.
시작에 불과합니다!
앞서 React 라이브러리가 있다고 언급했는데, React에서 위 데이터를 사용하는 방법은 다음과 같습니다:
tsxconst { data } = trpc.useQuery(['hello', '@alexdotjs']);
tsxconst { data } = trpc.useQuery(['hello', '@alexdotjs']);
.. 이제 클라이언트에서 타입 안전 데이터를 얻을 수 있습니다.
기존 브라운필드 프로젝트(Express/Next.js용 어댑터 제공)에 바로 tRPC를 추가할 수 있으며, CRA와 호환되고 React Native에서도 작동해야 합니다. React에 종속되지 않으므로 Svelte 또는 Vue 라이브러리를 개발하려면 연락주세요.
데이터 변경은 어떻게 하나요?
변경(mutation)은 쿼리만큼 간단합니다. 내부적으로는 동일하지만 문법적 편의를 위해 다르게 노출되며, GET 요청 대신 HTTP POST 요청을 생성합니다.
다음은 데이터베이스를 사용한 조금 더 복잡한 예시로, todomvc.trpc.io / https://github.com/trpc/trpc/tree/main/examples/next-prisma-todomvc 에 있는 TodoMVC 예제에서 가져온 것입니다.
tsxconst todoRouter = createRouter().mutation('add', {input: z.object({id: z.string().uuid(),data: z.object({completed: z.boolean().optional(),text: z.string().min(1).optional(),}),}),async resolve({ ctx, input }) {const { id, data } = input;const todo = await ctx.task.update({where: { id },data,});return todo;},});
tsxconst todoRouter = createRouter().mutation('add', {input: z.object({id: z.string().uuid(),data: z.object({completed: z.boolean().optional(),text: z.string().min(1).optional(),}),}),async resolve({ ctx, input }) {const { id, data } = input;const todo = await ctx.task.update({where: { id },data,});return todo;},});
React 사용 예시는 다음과 같습니다:
tsxconst addTask = trpc.useMutation('todos.add');return (<><inputplaceholder="What needs to be done?"onKeyDown={(e) => {const text = e.currentTarget.value.trim();if (e.key === 'Enter' && text) {addTask.mutate({ text });e.currentTarget.value = '';}}}/></>)
tsxconst addTask = trpc.useMutation('todos.add');return (<><inputplaceholder="What needs to be done?"onKeyDown={(e) => {const text = e.currentTarget.value.trim();if (e.key === 'Enter' && text) {addTask.mutate({ text });e.currentTarget.value = '';}}}/></>)
지금은 여기까지.
말씀드렸듯이, 시작에 불과합니다. 더 많은 기능들이 있습니다:
-
사용자별 데이터를 위한 요청 컨텍스트 생성(의존성 주입 방식으로 리졸버에 전달) - 링크
-
라우터용 미들웨어 지원 - 링크
-
라우터 병합(모든 백엔드 로직을 단일 파일에 두지 않으려는 경우) - 링크
-
@trpc/next어댑터를 이용한 React 생태계 최간단 서버 사이드 렌더링 - 링크 -
타입 안전 오류 포매팅 - 링크
-
데이터 변환기(Date/Map/Set 객체 직렬화 지원) - 링크
-
React Query 헬퍼 함수
시작하려면 Next.js 시작 가이드에 예제들이 준비되어 있습니다.
