다들 사이드 프로젝트 혹은 회사에서 근무할때 api를 어떤식으로 처리하나요?
저는 새로운 프로젝트에 들어갈 때마다 늘 같은 고민을 하곤 했습니다.
“왜 똑같은 작업을 반복하고 있을까?”
API 문서를 열고 → 타입스크립트 인터페이스 작성하고 → Axios 요청 함수 만들고 → 응답 타입 정의하고…
이 일련의 과정은 프로젝트를 시작할 때마다 반복적으로 등장하는 작업이었죠.
그래서 이번에는 이 반복을 줄여보고자 API/타입 자동화 도입을 직접 프로젝트에 적용해봤습니다.
특히 swagger-typescript-api라는 라이브러리를 사용해서, 어떻게 반복적인 작업을 줄이고 개발 효율을 높일 수 있었는지 경험을 공유해보려고 합니다.
npm i -D swagger-typescript-api
설치를 진행 한 후 Swagger 문서 URL을 알아야 합니다.
예를 들어 Swagger 문서가 https://example.com/api-docs.json 에 있다고 해봅시다.
package.json에 스크립트를 하나 추가하면 됩니다.
{
"scripts": {
"gen:api": "swagger-typescript-api -p https://example.com/api-docs.json -o src/api --axios --modular"
}
}
위에 보면 swagger 문서를 이런 API가 있다고 가정 해봅시다.
실행 후에는 아래와 같은 코드가 나옵니다.
// src/api/data-contracts.ts
export interface User {
id: number;
name: string;
email: string;
}
// src/api/Users.ts
import { HttpClient } from "./http-client";
export class UsersApi {
constructor(public http: HttpClient) {}
getUsers() {
return this.http.request<User[]>({
method: "GET",
url: "/users",
});
}
createUser(data: Omit<User, "id">) {
return this.http.request<User>({
method: "POST",
url: "/users",
body: data,
});
}
}
타입과 API 함수가 다 자동으로 만들어졌죠.
우리는 가져다 쓰기만 하면 됩니다.
이제 간단한 예시로 React 프로젝트에서 어떤식으로 사용할지 같이 보겠습니다.
import { UsersApi, HttpClient } from "@/api";
const api = new UsersApi(new HttpClient({ baseURL: "/api" }));
async function load() {
const users = await api.getUsers();
console.log(users[0].name); // 자동완성 + 타입체크 OK
}
users.까지 치면 바로 id, name, email 자동완성을 지원하죠~생성된 함수는 단순 HTTP 요청자이죠.
그래서 저는 실무에서는 React Query 같은 상태 관리/캐싱 라이브러리와 같이 쓰고있습니다.
const http = new HttpClient({ baseURL: "/api" });
export const usersApi = new UsersApi(http);
function useUsers() {
return useQuery({
queryKey: ["users"],
queryFn: () => usersApi.getUsers(),
select: (data) => data.map((u) => ({ ...u, display: `${u.name} (${u.email})` })),
});
}
역할이 분리되어 코드가 훨씬 깔끔해 지는것을 알수있습니다.
swagger-typescript-api는 기본적으로 GET /api/v1/userData → v1UserData 같은 식으로 메서드를 만들어 줍니다.
즉, 가독성이 조금 떨어질 수 있습니다. 이 점을 참고하셔서 커스텀을 진행하시거나 혹은 컨벤션에 맞게 변경하는 작업이 필요합니다.