[BE] Restful API, GraphQL, tRPC
05.08.2024
본 글은 유튜버 노마드 코더의 API를 구축하는 가장 좋은 방법은? 영상을 기반으로 작성되었습니다.
https://www.youtube.com/watch?v=abcnU7O5TVY&vl=ko
1. GraphQL의 탄생 배경 (RESTful API의 단점)
1-1. 하나의 기능에서 너무 많은 횟수의 API 호출
movie 리스트를 가져올 때 인기 영화와 전체 영화를 한 페이지에 호출한다고 생각해보자.
한 페이지에서 두 번의 API가 호출되는 것이다.
1-2. 서비스가 커질 수록 endpoint의 갯수가 증가로 인한 관리의 어려움
위에서 언급한 것과 같은 결이다. 전체 영화, 인기 영화, 특정 장르의 영화 등등을 모두 하나의 엔드포인트로 만든다면
서비스가 커질수록 endpoint는 계속 증가하고 그에 따라 유지보수(버전관리 등)의 복잡성도 증가하게 된다.
2. GraphQL은 어떻게 해결하였는가
GraphQL은 RESTful API와 달리 endpoint를 단 하나만 가지며 단 한 번의 요청으로 모든 데이터를 호출한다.
이 과정에서 overfetching 또는 underfetching 문제도 해결된다.
3. tRPC의 탄생 배경
3-1. 타입 안전성
기존 RESTful API와 GraphQL의 경우 타입 안정성을 위해 따로 설정을 해줘야 했다.
기존 RESTful API의 경우 작성된 코드는 이러한 형식을 띄었다.
const res = await fetch('/api/users/1');
const user = await res.json();
alert(`Hello ${user.name}`);
이러한 코드는 타입 안전성이 떨어진다고 할 수 있다.
만약 user에 name 프로퍼티가 없다면? 또는 user에서 name 프로퍼티가 fullName으로 바뀌었다면?
프로그램은 실행 오류를 내뿜을 것이고 예외처리가 되어있지 않은 경우 크래쉬로까지 이어질 수 있다.
tRPC는 이러한 문제점을 해결해준다.
백엔드가 바뀌면 tRPC는 변경을 감지하여 구문 오류로 백엔드 측에서 네임이 바뀌었다는 것을 사용자에게 알려준다.
3-2. 빠르고 쉽게 개발 가능
tRPC는 함수 호출 방식으로 동작한다.
무슨 말이냐면 '/api/route'와 같이 url로 데이터를 호출하는게 아니라 getUser() 함수를 백엔드에서 정의하면 프론트가 가져다 쓸 수 있다는 뜻이다.
4. tRPC 코드
tRPC는 프레임워크 안에서 사용할 수 있도록 디자인되었다.
4-1. 백엔드 코드
// server.ts
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
const router = t.router({
allMovies: t.procedure.query(async () => {
const movies = await db.movies.all();
return movies;
}),
movieById: t.procedure.query(async ({ input }) => {
const movie = await db.movies.find({id: input});
return movie;
}),
});
export type Router = typeof router;
const server = createHTTPServer({ router });
server.listen(3000);
4-2. 프론트엔드 코드
// client.ts
import type { Router } from './server';
import { createTRPCClient, httpBatchLink } from '@trpc/client';
const client = creatTRPCClient<Router>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
}),
],
});
// how to use
export default function Movies() {
const movies = await client.allMovies.query();
const movie = await client.movieById.query();
return <div>{movies.data?.map( ... )}</div>
}
5. 결론: 내가 아키텍처라면?
내가 만약에 한 기업의 아키텍처이고 API 구축 방법을 결정해야한다면 tRPC는 매력적일까?
내 나름대로의 결론은 도입하지 않을 것 같다. 이다.
- 첫째, tRPC의 탄생 배경이 Type Safety 라는 말은 TypeScript 개발 환경에서만 도입할 수 있다는 뜻이다. 즉, 백엔드가 node 기반이어야 한다는 말이다. 만약 회사에서 node 기반이라면 사용해볼만 할 것 같다.
- 둘째, 작은 커뮤니티와 러닝커브의 부담감은 회사의 성장에 제한을 줄 수 있다.
- 셋째, 타입 안정성 설정은 RESTful API와 GraphQL에서도 설정할 수 있다. 다만 더 복잡할 뿐..
그렇다면 언제 사용할까?
- 토이프로젝트와 같은 개인 프로젝트에는 도입해볼만 할 것 같다.
- 풀스택 솔로 프로젝트라면 tRPC의 도입으로 프로젝트에 속도를 낼 수 있고, 러닝커브에 대한 속도도 영향이 크지 않을 것이다.
- 팀프로젝트의 경우 러닝커브가 더 가팔라질 수 있으나 백엔드/프론트엔드 미스커뮤니케이션이 줄어들 수 있다. 특히 백엔드 프론트엔드 모두 tRPC 이해도가 있어야하므로 서로의 코드를 리뷰하며 풀스택 개발자로의 성장을 지향하는 환경을 조성할 수 있을 것 같다.