Fastify 어댑터
예제 앱
Fastify 어댑터를 시작하는 가장 좋은 방법은 예제 애플리케이션을 살펴보는 것입니다.
| 설명 | 링크 |
|---|---|
|
Fastify와 함께 tRPC 사용 방법
의존성 설치
bashyarn add @trpc/server fastify zod
bashyarn add @trpc/server fastify zod
⚠️ Fastify 버전 요구 사항
tRPC v11 Fastify 어댑터에는 Fastify v5 이상이 필요합니다. Fastify v4를 사용하면 오류 없이 요청이 빈 응답으로 반환될 수 있습니다.
Zod는 필수 의존성이 아니지만, 아래 샘플 라우터에서 사용됩니다.
AI 코딩 에이전트를 사용하는 경우, 더 나은 코드 생성을 위해 tRPC 스킬을 설치하세요:
bashnpx @tanstack/intent@latest install
bashnpx @tanstack/intent@latest install
라우터 생성
우선 쿼리, 뮤테이션, 구독을 처리하기 위한 라우터가 필요합니다.
아래에 샘플 라우터가 제공되며, router.ts이라는 이름의 파일로 저장하세요.
router.ts
router.tstsimport {initTRPC } from '@trpc/server';import {z } from 'zod';typeUser = {id : string;name : string;bio ?: string;};constusers :Record <string,User > = {};export constt =initTRPC .create ();export constappRouter =t .router ({getUserById :t .procedure .input (z .string ()).query ((opts ) => {returnusers [opts .input ]; // input type is string}),createUser :t .procedure .input (z .object ({name :z .string ().min (3),bio :z .string ().max (142).optional (),}),).mutation ((opts ) => {constid =Date .now ().toString ();constuser :User = {id , ...opts .input };users [user .id ] =user ;returnuser ;}),});// export type definition of APIexport typeAppRouter = typeofappRouter ;
router.tstsimport {initTRPC } from '@trpc/server';import {z } from 'zod';typeUser = {id : string;name : string;bio ?: string;};constusers :Record <string,User > = {};export constt =initTRPC .create ();export constappRouter =t .router ({getUserById :t .procedure .input (z .string ()).query ((opts ) => {returnusers [opts .input ]; // input type is string}),createUser :t .procedure .input (z .object ({name :z .string ().min (3),bio :z .string ().max (142).optional (),}),).mutation ((opts ) => {constid =Date .now ().toString ();constuser :User = {id , ...opts .input };users [user .id ] =user ;returnuser ;}),});// export type definition of APIexport typeAppRouter = typeofappRouter ;
라우터 파일이 너무 커지면, 각 서브라우터를 별도의 파일로 구현하여 여러 개의 서브라우터로 분리하세요. 그런 다음 병합하여 단일 루트 appRouter로 만드세요.
컨텍스트 생성
다음으로 각 요청마다 생성될 컨텍스트가 필요합니다.
아래에 샘플 컨텍스트가 제공되며, context.ts라는 이름의 파일로 저장하세요:
context.ts
context.tstsimport {CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';export functioncreateContext ({req ,res }:CreateFastifyContextOptions ) {constuser = {name :req .headers .username ?? 'anonymous' };return {req ,res ,user };}export typeContext =Awaited <ReturnType <typeofcreateContext >>;
context.tstsimport {CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';export functioncreateContext ({req ,res }:CreateFastifyContextOptions ) {constuser = {name :req .headers .username ?? 'anonymous' };return {req ,res ,user };}export typeContext =Awaited <ReturnType <typeofcreateContext >>;
Fastify 서버 생성
tRPC에는 Fastify용 어댑터가 기본으로 포함되어 있습니다. 이 어댑터를 사용하면 tRPC 라우터를 Fastify 플러그인으로 변환할 수 있습니다. 대규모 배치 요청 시 오류를 방지하려면, 아래에 표시된 대로 maxParamLength Fastify 옵션을 적절한 값으로 설정하세요.
Fastify의 플러그인 시스템과 타입 추론의 제한 사항으로 인해, 예를 들어 onError의 타입이 올바르게 지정되지 않는 문제가 발생할 수 있습니다. TypeScript를 돕고 올바른 타입을 얻기 위해 satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions']을 추가할 수 있습니다.
server.tstsimport {fastifyTRPCPlugin ,FastifyTRPCPluginOptions ,} from '@trpc/server/adapters/fastify';importfastify from 'fastify';import {createContext } from './context';import {appRouter , typeAppRouter } from './router';constserver =fastify ({routerOptions : {maxParamLength : 5000,},});server .register (fastifyTRPCPlugin , {prefix : '/trpc',trpcOptions : {router :appRouter ,createContext ,onError ({path ,error }) {// report to error monitoringconsole .error (`Error in tRPC handler on path '${path }':`,error );},} satisfiesFastifyTRPCPluginOptions <AppRouter >['trpcOptions'],});(async () => {try {awaitserver .listen ({port : 3000 });} catch (err ) {server .log .error (err );process .exit (1);}})();
server.tstsimport {fastifyTRPCPlugin ,FastifyTRPCPluginOptions ,} from '@trpc/server/adapters/fastify';importfastify from 'fastify';import {createContext } from './context';import {appRouter , typeAppRouter } from './router';constserver =fastify ({routerOptions : {maxParamLength : 5000,},});server .register (fastifyTRPCPlugin , {prefix : '/trpc',trpcOptions : {router :appRouter ,createContext ,onError ({path ,error }) {// report to error monitoringconsole .error (`Error in tRPC handler on path '${path }':`,error );},} satisfiesFastifyTRPCPluginOptions <AppRouter >['trpcOptions'],});(async () => {try {awaitserver .listen ({port : 3000 });} catch (err ) {server .log .error (err );process .exit (1);}})();
이제 엔드포인트가 HTTP를 통해 사용할 수 있습니다!
| 엔드포인트 | HTTP URI |
|---|---|
getUserById | GET http://localhost:3000/trpc/getUserById?input=INPUT 여기서 INPUT은 URI 인코딩된 JSON 문자열입니다. |
createUser | POST http://localhost:3000/trpc/createUser 여기서 req.body의 타입은 User입니다 |
WebSocket 활성화
Fastify 어댑터는 @fastify/websocket 플러그인을 통해 WebSockets를 지원합니다. 위의 단계 외에도 종속성을 설치하고 라우터에 구독을 추가하며 플러그인에서 useWSS 옵션을 활성화하기만 하면 됩니다. 요구되는 최소 @fastify/websocket 버전은 3.11.0입니다.
종속성 설치
bashyarn add @fastify/websocket
bashyarn add @fastify/websocket
@fastify/websocket 가져오기 및 등록
tsimportws from '@fastify/websocket';server .register (ws );
tsimportws from '@fastify/websocket';server .register (ws );
구독 추가
이전 단계에서 생성된 router.ts 파일을 편집하고 다음 코드를 추가하세요:
router.tstsimport {initTRPC } from '@trpc/server';constt =initTRPC .create ();export constappRouter =t .router ({randomNumber :t .procedure .subscription (async function* () {while (true) {yield {randomNumber :Math .random () };await newPromise ((resolve ) =>setTimeout (resolve , 1000));}}),});
router.tstsimport {initTRPC } from '@trpc/server';constt =initTRPC .create ();export constappRouter =t .router ({randomNumber :t .procedure .subscription (async function* () {while (true) {yield {randomNumber :Math .random () };await newPromise ((resolve ) =>setTimeout (resolve , 1000));}}),});
useWSS 옵션 활성화
server.tstsimport {fastifyTRPCPlugin ,FastifyTRPCPluginOptions ,} from '@trpc/server/adapters/fastify';importfastify from 'fastify';import {createContext } from './context';import {appRouter , typeAppRouter } from './router';constserver =fastify ();server .register (fastifyTRPCPlugin , {useWSS : true,trpcOptions : {router :appRouter ,createContext ,// Enable heartbeat messages to keep connection open (disabled by default)keepAlive : {enabled : true,// server ping message interval in millisecondspingMs : 30000,// connection is terminated if pong message is not received in this many millisecondspongWaitMs : 5000,},},});
server.tstsimport {fastifyTRPCPlugin ,FastifyTRPCPluginOptions ,} from '@trpc/server/adapters/fastify';importfastify from 'fastify';import {createContext } from './context';import {appRouter , typeAppRouter } from './router';constserver =fastify ();server .register (fastifyTRPCPlugin , {useWSS : true,trpcOptions : {router :appRouter ,createContext ,// Enable heartbeat messages to keep connection open (disabled by default)keepAlive : {enabled : true,// server ping message interval in millisecondspingMs : 30000,// connection is terminated if pong message is not received in this many millisecondspongWaitMs : 5000,},},});
이제 randomNumber 주제에 구독할 수 있으며, 매초 무작위 숫자를 수신하게 됩니다 🚀.
Fastify 플러그인 옵션
| 이름 | 타입 | 선택 사항 | 기본값 | 설명 |
|---|---|---|---|---|
| prefix | string | true | "/trpc" | tRPC 라우트의 URL 접두사 |
| useWSS | boolean | true | false | @fastify/websocket을 통해 WebSocket 지원 활성화 |
| trpcOptions | FastifyHandlerOptions<AppRouter, Request, Reply> | false | n/a | router, createContext 등을 포함하는 tRPC 핸들러 옵션 |