본문 바로가기
버전: 11.x

Next.js Pages 라우터로 설정하기

비공식 베타 번역

이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →

주의

이 가이드는 Next.js Pages 라우터를 위한 것입니다. React 서버 컴포넌트와 함께 Next.js App 라우터를 사용 중이라면 RSC 문서를 확인하세요.

추천 파일 구조

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 install @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@latest zod

Next.js 통합은 실제로 React Query 통합과 Next.js 전용 통합의 조합입니다.

2. 엄격 모드 활성화

Zod를 입력 유효성 검사에 사용하려면 tsconfig.json에서 엄격 모드를 활성화해야 합니다:

tsconfig.json
diff
"compilerOptions": {
+ "strict": true
}
tsconfig.json
diff
"compilerOptions": {
+ "strict": true
}

엄격 모드가 부담스럽다면 최소한 strictNullChecks는 활성화하세요:

tsconfig.json
diff
"compilerOptions": {
+ "strictNullChecks": true
}
tsconfig.json
diff
"compilerOptions": {
+ "strictNullChecks": true
}

3. tRPC 라우터 생성

src/server/trpc.ts에서 initTRPC 함수를 사용해 tRPC 백엔드를 초기화하고 첫 번째 라우터를 만듭니다. 여기서는 간단한 "hello world" 라우터와 프로시저를 만들겠습니다. tRPC API 생성에 대한 자세한 내용은 다음을 참조하세요:

View sample backend
server/trpc.ts
ts
import { 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 helpers
export const router = t.router;
export const procedure = t.procedure;
server/trpc.ts
ts
import { 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 helpers
export const router = t.router;
export const procedure = t.procedure;

server/routers/_app.ts
ts
import { 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 API
export type AppRouter = typeof appRouter;
server/routers/_app.ts
ts
import { 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 API
export type AppRouter = typeof appRouter;

pages/api/trpc/[trpc].ts
ts
import * as trpcNext from '@trpc/server/adapters/next';
import { appRouter } from '../../../server/routers/_app';
// export API handler
// @link https://trpc.io/docs/v11/server/adapters
export default trpcNext.createNextApiHandler({
router: appRouter,
createContext: () => ({}),
});
pages/api/trpc/[trpc].ts
ts
import * as trpcNext from '@trpc/server/adapters/next';
import { appRouter } from '../../../server/routers/_app';
// export API handler
// @link https://trpc.io/docs/v11/server/adapters
export default trpcNext.createNextApiHandler({
router: appRouter,
createContext: () => ({}),
});
참고

위 백엔드는 추천 파일 구조를 사용하지만, 선호한다면 API 핸들러에 직접 모든 내용을 넣을 수도 있습니다.

4. tRPC 훅 생성

API의 타입 시그니처에서 강력한 타입의 훅 세트를 생성하려면 createTRPCNext 함수를 사용하세요.

utils/trpc.ts
tsx
import { 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 path
return '';
if (process.env.VERCEL_URL)
// reference for vercel.com
return `https://${process.env.VERCEL_URL}`;
if (process.env.RENDER_INTERNAL_HOSTNAME)
// reference for render.com
return `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;
// assume localhost
return `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/v11/ssr
**/
url: `${getBaseUrl()}/api/trpc`,
// You can pass any HTTP headers you wish here
async headers() {
return {
// authorization: getAuthCookie(),
};
},
}),
],
};
},
/**
* @see https://trpc.io/docs/v11/ssr
**/
ssr: false,
});
utils/trpc.ts
tsx
import { 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 path
return '';
if (process.env.VERCEL_URL)
// reference for vercel.com
return `https://${process.env.VERCEL_URL}`;
if (process.env.RENDER_INTERNAL_HOSTNAME)
// reference for render.com
return `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;
// assume localhost
return `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/v11/ssr
**/
url: `${getBaseUrl()}/api/trpc`,
// You can pass any HTTP headers you wish here
async headers() {
return {
// authorization: getAuthCookie(),
};
},
}),
],
};
},
/**
* @see https://trpc.io/docs/v11/ssr
**/
ssr: false,
});
참고

createTRPCNext는 tRPC-v9 호환 모드와 함께 작동하지 않습니다. v9에서 호환 모드를 사용해 마이그레이션 중이라면 기존 tRPC 초기화 방식을 계속 사용해야 합니다.

5. _app.tsx 설정

루트 앱 페이지를 다음과 같이 trpc.withTRPC HOC로 감싸세요:

pages/_app.tsx
tsx
import 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.tsx
tsx
import 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.tsx
tsx
import { 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.tsx
tsx
import { 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 자세히 보기

  • 선택 사항:

  • tRPC React 훅 내부에서 사용되는 React Query QueryClient의 구성 객체 queryClientConfig: QueryClient 문서

  • queryClient: React Query의 QueryClient 인스턴스

    • 참고: queryClientqueryClientConfig 중 하나만 제공할 수 있습니다.
  • transformer: 아웃바운드 페이로드에 적용되는 변환기. 데이터 변환기 문서 참조

  • abortOnUnmount: 컴포넌트 언마운트 시 진행 중인 요청을 취소할지 여부. 기본값은 false입니다.

overrides: (기본값: undefined)

React Query 훅에 대한 오버라이드 설정

ssr-부울값 (기본값: false)

서버 사이드 렌더링 시 tRPC가 쿼리를 대기할지 여부. 기본값은 false입니다.

responseMeta-콜백

서버 사이드 렌더링 시 응답 헤더와 HTTP 상태 코드 설정 기능

예시

utils/trpc.ts
tsx
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../pages/api/trpc/[trpc]';
export const trpc = createTRPCNext<AppRouter>({
config(config) {
/* [...] */
},
});
utils/trpc.ts
tsx
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../pages/api/trpc/[trpc]';
export const trpc = createTRPCNext<AppRouter>({
config(config) {
/* [...] */
},
});

다음 단계

인증, 미들웨어, 오류 처리 등에 대해 알아보려면 문서를 계속 탐색하세요.

@trpc/react-query를 사용 중이므로 쿼리뮤테이션에 대한 정보도 확인할 수 있습니다.