본문 바로가기
개발정리 (nodeJS)

[nodeJS] Node.js로 tRPC API 만들기

by 할리갈리0 2024. 7. 11.

tRPC는 타입 안전성과 자동 생성된 클라이언트를 제공하는 새로운 방식의 API 프레임워크입니다.

타입스크립트를 사용하지 않고 tRPC API를 설정하고 사용하는 방법을 설명하겠습니다.

 

1. tRPC란?

서버와 클라이언트 간의 타입 안전성을 보장하며, 별도의 스키마 정의 없이 API를 구축할 수 있게 해주는 프레임워크

[tRPC의 장점]

  • 타입 안전성: 서버와 클라이언트 간의 데이터 타입 일치 보장
  • 자동 생성된 클라이언트: API 호출을 위한 클라이언트 코드 자동 생성
  • 생산성 향상: 별도의 스키마 정의나 코드 생성 단계 없이 바로 API 작성 가능

 

2. 프로젝트 구조 설정

  • src/index.js: Express 서버와 tRPC를 설정하는 메인 파일.
  • src/routers/appRouter.js: tRPC 라우터를 정의하는 파일.
  • src/models/user.js: 사용자 데이터를 저장하는 모델 파일.
  • uploads: 업로드된 파일을 저장하는 디렉터리.
my-trpc-project
├── src
│   ├── index.js
│   ├── routers
│   │   └── appRouter.js
│   └── models
│       └── user.js
├── uploads
├── package.json
└── README.md

 

3. tRPC 설치 및 기본 설정

tRPC를 사용하기 위해 필요한 패키지 설치

npm install @trpc/server @trpc/client express


src/index.js 파일에서 Express 서버와 tRPC를 설정하는 기본 코드 작성

간단한 Express 서버와 tRPC 라우터를 설정하여 /trpc 경로로 요청을 처리

// src/index.js
const express = require('express');
const { initTRPC } = require('@trpc/server');
const { createExpressMiddleware } = require('@trpc/server/adapters/express');
const appRouter = require('./routers/appRouter');

const app = express();
const t = initTRPC.create();

app.use('/trpc', createExpressMiddleware({
  router: appRouter,
  createContext: () => ({}),
}));

const port = 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

 

4. 간단한 API 엔드포인트 만들기

src/routers/appRouter.js 파일에서 간단한 API 엔드포인트를 작성

hello라는 엔드포인트를 정의하여 'Hello World!' 문자열을 반환

// src/routers/appRouter.js
const { initTRPC } = require('@trpc/server');

const t = initTRPC.create();

const appRouter = t.router({
  hello: t.procedure.query(() => 'Hello World!'),
});

module.exports = appRouter;

 

5. CRUD 기능 구현하기

src/models/user.js 파일에서 사용자 데이터를 저장하는 모델을 작성하고, CRUD 기능을 구현

[사용자 데이터 모델]

// src/models/user.js
let users = {
  1: { id: 1, name: 'John Doe' },
  2: { id: 2, name: 'Jane Doe' },
};

let nextId = 3;

module.exports = { users, nextId };

 

[CRUD 엔드포인트 추가]

// src/routers/appRouter.js
const { initTRPC } = require('@trpc/server');
const { users, nextId } = require('../models/user');

const t = initTRPC.create();

const appRouter = t.router({
  hello: t.procedure.query(() => 'Hello World!'),
  getUser: t.procedure.input((val) => typeof val === 'number').query((id) => {
    return users[id] || null;
  }),
  createUser: t.procedure.input((val) => typeof val === 'string').mutation((name) => {
    const id = nextId++;
    users[id] = { id, name };
    return users[id];
  }),
  updateUser: t.procedure.input((val) => typeof val === 'object' && val.id && val.name).mutation(({ id, name }) => {
    if (users[id]) {
      users[id].name = name;
      return users[id];
    }
    return null;
  }),
  deleteUser: t.procedure.input((val) => typeof val === 'number').mutation((id) => {
    const user = users[id];
    if (user) {
      delete users[id];
      return user;
    }
    return null;
  }),
});

module.exports = appRouter;

 

6. 에러 핸들링 및 미들웨어 설정

[에러 핸들링]

tRPC에서는 간단한 방식으로 에러 처리 가능

// src/routers/appRouter.js
const appRouter = t.router({
  hello: t.procedure.query(() => 'Hello World!'),
  getUser: t.procedure.input((val) => {
    if (typeof val !== 'number') throw new Error('Invalid input');
    return val;
  }).query((id) => {
    if (!users[id]) throw new Error('User not found');
    return users[id];
  }),
  // ... 기타 엔드포인트
});

 

[미들웨어 설정]

tRPC 미들웨어를 설정하여 공통 로직 처리 가능

// src/routers/appRouter.js
const loggingMiddleware = t.middleware(async ({ path, type, next }) => {
  console.log(`Call to ${path} with type ${type}`);
  return next();
});

const appRouter = t.router({
  hello: t.procedure.use(loggingMiddleware).query(() => 'Hello World!'),
  // ... 기타 엔드포인트
});

 

7. 클라이언트에서 tRPC API 호출하기

tRPC 클라이언트를 설정하여 서버의 API 호출

// src/client.js
const { createTRPCProxyClient, httpLink } = require('@trpc/client');
const fetch = require('node-fetch');

const client = createTRPCProxyClient({
  links: [
    httpLink({
      url: 'http://localhost:3000/trpc',
      fetch,
    }),
  ],
});

// API 호출 예제
async function fetchData() {
  const hello = await client.hello.query();
  console.log(hello); // "Hello World!"

  const user = await client.getUser.query(1);
  console.log(user); // { id: 1, name: 'John Doe' }
}

fetchData();

 

 

Node.js에서 tRPC를 사용해 타입스크립트를 사용하지 않고도 강력하고 타입 안전한 API를 구축하는 방법을 살펴보았습니다. tRPC를 사용하면 타입 정의와 스키마 관리의 복잡성을 줄이고, 서버와 클라이언트 간의 데이터 일관성을 유지할 수 있습니다. 또한, 자동 생성된 클라이언트를 통해 쉽게 API를 호출할 수 있습니다.

반응형