Next.js로 설정하기
이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →
추천 파일 구조
tRPC에서 강제하지는 않지만 다음과 같은 파일 구조를 권장합니다. 예시 앱에서도 이 구조를 확인할 수 있습니다. 이어지는 내용에서는 이 구조에 tRPC를 추가하는 과정을 설명합니다.
graphql.├── prisma # <-- if prisma is added│ └── [..]├── src│ ├── pages│ │ ├── _app.tsx # <-- add `withTRPC()`-HOC here│ │ ├── api│ │ │ └── trpc│ │ │ └── [trpc].ts # <-- tRPC HTTP handler│ │ └── [..]│ ├── server│ │ ├── routers│ │ │ ├── _app.ts # <-- main app router│ │ │ ├── post.ts # <-- sub routers│ │ │ └── [..]│ │ ├── context.ts # <-- create app context│ │ └── trpc.ts # <-- procedure helpers│ └── utils│ └── trpc.ts # <-- your typesafe tRPC hooks└── [..]
graphql.├── prisma # <-- if prisma is added│ └── [..]├── src│ ├── pages│ │ ├── _app.tsx # <-- add `withTRPC()`-HOC here│ │ ├── api│ │ │ └── trpc│ │ │ └── [trpc].ts # <-- tRPC HTTP handler│ │ └── [..]│ ├── server│ │ ├── routers│ │ │ ├── _app.ts # <-- main app router│ │ │ ├── post.ts # <-- sub routers│ │ │ └── [..]│ │ ├── context.ts # <-- create app context│ │ └── trpc.ts # <-- procedure helpers│ └── utils│ └── trpc.ts # <-- your typesafe tRPC hooks└── [..]
기존 Next.js 프로젝트에 tRPC 추가하기
1. 의존성 설치
- npm
- yarn
- pnpm
- bun
shnpm install @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
shnpm install @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
shyarn add @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
shyarn add @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
shpnpm add @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
shpnpm add @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
shbun add @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
shbun add @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@4 zod
Next.js 통합은 실제로 React Query 통합과 Next.js 전용 통합의 조합입니다.
2. 엄격 모드 활성화
Zod를 입력 유효성 검사에 사용하려면 tsconfig.json에서 엄격 모드를 활성화해야 합니다:
tsconfig.jsondiff"compilerOptions": {+ "strict": true}
tsconfig.jsondiff"compilerOptions": {+ "strict": true}
엄격 모드가 부담스럽다면 최소한 strictNullChecks는 활성화하세요:
tsconfig.jsondiff"compilerOptions": {+ "strictNullChecks": true}
tsconfig.jsondiff"compilerOptions": {+ "strictNullChecks": true}
3. tRPC 라우터 생성
src/server/trpc.ts에서 initTRPC 함수를 사용해 tRPC 백엔드를 초기화하고 첫 번째 라우터를 만듭니다. 여기서는 간단한 "hello world" 라우터와 프로시저를 만들겠습니다. tRPC API 생성에 대한 자세한 내용은 다음을 참조하세요:
-
Next.js 서버 내 tRPC 마운팅: Next.js 어댑터 문서
View sample backend
server/trpc.tstsimport { initTRPC } from '@trpc/server';// Avoid exporting the entire t-object// since it's not very descriptive.// For instance, the use of a t variable// is common in i18n libraries.const t = initTRPC.create();// Base router and procedure helpersexport const router = t.router;export const procedure = t.procedure;
server/trpc.tstsimport { initTRPC } from '@trpc/server';// Avoid exporting the entire t-object// since it's not very descriptive.// For instance, the use of a t variable// is common in i18n libraries.const t = initTRPC.create();// Base router and procedure helpersexport const router = t.router;export const procedure = t.procedure;
server/routers/_app.tstsimport { z } from 'zod';import { procedure, router } from '../trpc';export const appRouter = router({hello: procedure.input(z.object({text: z.string(),}),).query((opts) => {return {greeting: `hello ${opts.input.text}`,};}),});// export type definition of APIexport type AppRouter = typeof appRouter;
server/routers/_app.tstsimport { z } from 'zod';import { procedure, router } from '../trpc';export const appRouter = router({hello: procedure.input(z.object({text: z.string(),}),).query((opts) => {return {greeting: `hello ${opts.input.text}`,};}),});// export type definition of APIexport type AppRouter = typeof appRouter;
pages/api/trpc/[trpc].tstsimport * as trpcNext from '@trpc/server/adapters/next';import { appRouter } from '../../../server/routers/_app';// export API handler// @link https://trpc.io/docs/server/adaptersexport default trpcNext.createNextApiHandler({router: appRouter,createContext: () => ({}),});
pages/api/trpc/[trpc].tstsimport * as trpcNext from '@trpc/server/adapters/next';import { appRouter } from '../../../server/routers/_app';// export API handler// @link https://trpc.io/docs/server/adaptersexport default trpcNext.createNextApiHandler({router: appRouter,createContext: () => ({}),});
위 백엔드는 추천 파일 구조를 사용하지만, 선호한다면 API 핸들러에 직접 모든 내용을 넣을 수도 있습니다.
4. tRPC 훅 생성
API의 타입 시그니처에서 강력한 타입의 훅 세트를 생성하려면 createTRPCNext 함수를 사용하세요.
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import type { AppRouter } from '../server/routers/_app';function getBaseUrl() {if (typeof window !== 'undefined')// browser should use relative pathreturn '';if (process.env.VERCEL_URL)// reference for vercel.comreturn `https://${process.env.VERCEL_URL}`;if (process.env.RENDER_INTERNAL_HOSTNAME)// reference for render.comreturn `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;// assume localhostreturn `http://localhost:${process.env.PORT ?? 3000}`;}export const trpc = createTRPCNext<AppRouter>({config(config) {return {links: [httpBatchLink({/*** If you want to use SSR, you need to use the server's full URL* @see https://trpc.io/docs/ssr**/url: `${getBaseUrl()}/api/trpc`,// You can pass any HTTP headers you wish hereasync headers() {return {// authorization: getAuthCookie(),};},}),],};},/*** @see https://trpc.io/docs/ssr**/ssr: false,});
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import type { AppRouter } from '../server/routers/_app';function getBaseUrl() {if (typeof window !== 'undefined')// browser should use relative pathreturn '';if (process.env.VERCEL_URL)// reference for vercel.comreturn `https://${process.env.VERCEL_URL}`;if (process.env.RENDER_INTERNAL_HOSTNAME)// reference for render.comreturn `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;// assume localhostreturn `http://localhost:${process.env.PORT ?? 3000}`;}export const trpc = createTRPCNext<AppRouter>({config(config) {return {links: [httpBatchLink({/*** If you want to use SSR, you need to use the server's full URL* @see https://trpc.io/docs/ssr**/url: `${getBaseUrl()}/api/trpc`,// You can pass any HTTP headers you wish hereasync headers() {return {// authorization: getAuthCookie(),};},}),],};},/*** @see https://trpc.io/docs/ssr**/ssr: false,});
createTRPCNext는 tRPC v9 호환 모드와 함께 작동하지 않습니다. v9에서 호환 모드를 사용해 마이그레이션 중이라면 이전 방식의 tRPC 초기화를 계속 사용해야 합니다.
5. _app.tsx 설정
루트 앱 페이지를 다음과 같이 trpc.withTRPC HOC로 감싸세요:
pages/_app.tsxtsximport type { AppType } from 'next/app';import { trpc } from '../utils/trpc';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
pages/_app.tsxtsximport type { AppType } from 'next/app';import { trpc } from '../utils/trpc';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
6. API 요청하기
모든 준비가 완료되었습니다!
이제 생성한 React 훅을 사용해 API를 호출할 수 있습니다. 자세한 내용은 React Query 통합을 참조하세요.
pages/index.tsxtsximport { trpc } from '../utils/trpc';export default function IndexPage() {const hello = trpc.hello.useQuery({ text: 'client' });if (!hello.data) {return <div>Loading...</div>;}return (<div><p>{hello.data.greeting}</p></div>);}
pages/index.tsxtsximport { trpc } from '../utils/trpc';export default function IndexPage() {const hello = trpc.hello.useQuery({ text: 'client' });if (!hello.data) {return <div>Loading...</div>;}return (<div><p>{hello.data.greeting}</p></div>);}
createTRPCNext() 옵션
config 콜백
config 인수는 tRPC 및 React Query 클라이언트를 구성하는 객체를 반환하는 함수입니다. 이 함수는 Next.js req 객체 등에 접근할 수 있는 ctx 입력을 받습니다. 반환된 객체는 다음 속성을 포함할 수 있습니다:
-
필수:
-
tRPC 클라이언트와 서버 간 데이터 흐름을 커스터마이즈하는
links자세히 보기 -
선택 사항:
-
queryClientConfig: tRPC React 훅 내부에서 사용되는 React QueryQueryClient를 위한 설정 객체: QueryClient 문서 -
queryClient: React Query QueryClient 인스턴스- 참고:
queryClient와queryClientConfig중 하나만 제공할 수 있습니다.
- 참고:
-
transformer: 아웃바운드 페이로드에 적용되는 변환기. 데이터 변환기 문서 참조 -
abortOnUnmount: 컴포넌트 언마운트 시 진행 중인 요청을 취소할지 여부. 기본값은false입니다.
overrides: (기본값: undefined)
ssr-부울값 (기본값: false)
서버 사이드 렌더링 시 tRPC가 쿼리를 대기할지 여부. 기본값은 false입니다.
responseMeta-콜백
서버 사이드 렌더링 시 응답 헤더와 HTTP 상태 코드 설정 기능
예시
utils/trpc.tstsximport { createTRPCNext } from '@trpc/next';import type { AppRouter } from '../pages/api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {/* [...] */},ssr: true,responseMeta(opts) {const { clientErrors } = opts;if (clientErrors.length) {// propagate first http error from API callsreturn {status: clientErrors[0].data?.httpStatus ?? 500,};}// cache full page for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {'Cache-Control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,};},});
utils/trpc.tstsximport { createTRPCNext } from '@trpc/next';import type { AppRouter } from '../pages/api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {/* [...] */},ssr: true,responseMeta(opts) {const { clientErrors } = opts;if (clientErrors.length) {// propagate first http error from API callsreturn {status: clientErrors[0].data?.httpStatus ?? 500,};}// cache full page for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {'Cache-Control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,};},});