Next.js에서 tRPC를 수동으로 설정하는 것을 멈추고 — 대신 이 CLI를 사용하세요
Source: Dev.to
Introduction
새로운 Next.js 프로젝트에 tRPC를 설정할 때마다 문서를 열고, 파일을 복사하고, 패키지를 설치하고, layout.tsx를 감싸고, QueryClient 오류를 고치고, 다음 프로젝트에서도 같은 과정을 반복해야 했습니다. 이러한 반복적인 설정을 없애기 위해 CLI를 만들었습니다:
npx create-trpc-setup
What the CLI Does
기존 Next.js 프로젝트 안에서 명령을 실행하면 자동으로:
- 필요한 패키지(
@trpc/server,@trpc/client,@trpc/tanstack-react-query,@tanstack/react-query,zod등)를 설치합니다. - 사용 중인 패키지 매니저(npm, pnpm, yarn, bun)를 감지합니다.
tsconfig.json을 읽어 경로 별칭(@/*,~/, 혹은 사용자 정의 별칭)을 존중합니다.- 인증 제공자(Clerk 또는 NextAuth)를 감지하고 컨텍스트를 그에 맞게 설정합니다.
- 폴더 구조(
src/혹은 루트 레이아웃)에 맞게 조정합니다.
그 후 다음과 같은 파일들을 생성합니다:
trpc/
├── init.ts ← context, baseProcedure, protectedProcedure, Zod error formatter
├── query-client.ts ← SSR‑safe QueryClient
├── client.tsx ← TRPCReactProvider + useTRPC hook
├── server.tsx ← prefetch, HydrateClient, caller
└── routers/
└── _app.ts ← health + greet procedures with Zod
app/api/trpc/[trpc]/route.ts ← API handler with real headers
app/trpc-status/ ← test page (delete after confirming)
Updating layout.tsx
Before
{children}
After
{children}
Using the Generated Setup
Server Component – Prefetch Data
// app/page.tsx
import { HydrateClient, prefetch, trpc } from "@/trpc/server";
import { MyClient } from "./my-client";
export default function Page() {
prefetch(trpc.greet.queryOptions({ name: "World" }));
return (
);
}
Client Component – Consume Data
// my-client.tsx
"use client";
import { useSuspenseQuery } from "@tanstack/react-query";
import { useTRPC } from "@/trpc/client";
export function MyClient() {
const trpc = useTRPC();
const { data } = useSuspenseQuery(
trpc.greet.queryOptions({ name: "World" })
);
return {data.message};
}
Comparison with create-t3-app
create-t3-app은 새로운 프로젝트에 적합합니다.create-trpc-setup은 기존 프로젝트에서도 동작합니다. 이미 Clerk, Shadcn UI, 혹은 커스텀 제공자를 사용하고 있더라도 명령 하나로 필요한 파일을 모두 추가하고 기존 코드를 수정하지 않습니다.
Protected Procedure Helper
생성된 init.ts에는 protectedProcedure가 포함되어 있어 ctx.userId가 없을 경우 자동으로 UNAUTHORIZED 오류를 발생시킵니다:
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.userId) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({ ctx: { ...ctx, userId: ctx.userId } });
});
어떤 라우터에서도 다음과 같이 사용할 수 있습니다:
getProfile: protectedProcedure.query(({ ctx }) => {
return { userId: ctx.userId }; // guaranteed non‑null
}),
Installation & Links
- npm package:
- GitHub repository:
CLI가 시간을 절약해 주었다면, 저장소에 ⭐를 달고 팀과 공유해 주세요.