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

Next.js Pages Router로 설정하기

비공식 베타 번역

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

주의

이 가이드는 Next.js Pages Router를 위한 것입니다. Next.js App Router를 사용 중이라면 대신 App Router 설정 가이드를 참조하세요.

추천 파일 구조​

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
AI 에이전트

AI 코딩 에이전트를 사용하는 경우 더 나은 코드 생성을 위해 tRPC 스킬을 설치하세요:

bash
npx @tanstack/intent@latest install
bash
npx @tanstack/intent@latest install

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/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/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/client/nextjs/pages-router/ssr
**/
url: `${getBaseUrl()}/api/trpc`,
 
// You can pass any HTTP headers you wish here
async headers() {
return {
// authorization: getAuthCookie(),
};
},
}),
],
};
},
/**
* @see https://trpc.io/docs/client/nextjs/pages-router/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/client/nextjs/pages-router/ssr
**/
url: `${getBaseUrl()}/api/trpc`,
 
// You can pass any HTTP headers you wish here
async headers() {
return {
// authorization: getAuthCookie(),
};
},
}),
],
};
},
/**
* @see https://trpc.io/docs/client/nextjs/pages-router/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 클라이언트를 구성하는 객체를 반환하는 함수입니다. 이 함수는 선택적 ctx 속성(NextPageContext 타입)을 가진 객체를 인자로 받으며, 이를 통해 서버 사이드 렌더링 중 Next.js req 객체에 접근할 수 있습니다. 반환된 객체는 다음 속성을 포함할 수 있습니다:

  • 필수:

  • tRPC 클라이언트와 서버 간 데이터 흐름을 커스터마이즈하는 links 자세히 보기

  • 선택 사항:

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

  • queryClient: React Query의 QueryClient 인스턴스

    • 참고: queryClient와 queryClientConfig 중 하나만 제공할 수 있습니다.
  • 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 '../server/routers/_app';
 
export const trpc = createTRPCNext<AppRouter>({
config(config) {
return {
links: [
/* [...] */
],
};
},
});
utils/trpc.ts
tsx
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../server/routers/_app';
 
export const trpc = createTRPCNext<AppRouter>({
config(config) {
return {
links: [
/* [...] */
],
};
},
});

다음 단계​

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

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