Swagger문서로 API 타입 정의 자동화하기 (swagger-typescript-api)

Ina·2022년 11월 2일
2
post-thumbnail

회사에서 하반기에 어드민용 신규 레포를 생성하게 되면서 그동안 도입해보고팠으나 레거시 코드베이스의 압박으로 시도해보지 못 했던 🥲 이런저런 기술들을 신규 레포에서 선 적용해보기로 했습니다. 그리고 그 중 하나가 Swagger 문서로 API 타입 정의 자동화 하는 태스크였습니다.

도입 배경

  • 일일이 api 엔드포인트와 parameter 타입, 응답값 인터페이스를 수동으로 작성하는 것에 시간이 많이 쓰이고 있었음. 수고를 줄이고자!

why swagger-typescript-api ? 굳이 open api 타입 전부 지원할 필요 없기에 우리 스택(문서:swagger REST api & 스키마 : typescript 조합)에 딱 맞아서 커스터마이징의 수고가 적은 라이브러리로 정했다. 버그 업데이트도 부지런히 하고 있는 것 같아서 라이브러리 자체에 대한 불만은 크게 없다.

예상되었던 허들

기존에 swagger 문서화 자체가 많이 되어있지 않았음.
문서화가 덜(ㅠㅠ)된 채로 타입을 생성해내다보니 결과물도 구멍이 많아서 예상한 것 만큼

아무튼 도입!

  • data-contracts.ts
    apidoc.json -> typescript interface
  • http-client
    axios config를 포함한 api client axios class.
    -> 커스텀 훅에서 인스턴스화하면서 header를 커스터마이징해서 사용중.
  • [API].tsx
    api class. api 엔드포인트별로 호출할 수 있는 메서드가 담겨져있음.

조금 사용해보니.. 팁&주의점

  1. hook 적절히 사용
  2. http-client 최상단에 @ts-nocheck 추가
  3. swagger에서 요청 parameter에 대한 정의가 잘못되어 있을 경우 요청 자체가 정상적으로 가지 않을 수 있음
    ex. PUT/POST parameter의 dataType이 실제로는 string 타입인데 스웨거 문서에 formData으로 정의되어있을 경우 http-client에서 content type을 인식하고 key&value로 formData를 알아서 만들어서 보내주는데, 서버에서 인식하지 못하여 500에러가 날 수 있음. ㅠ.ㅠ


(코드 복붙을 원한다면 글 가장 아래에 스니펫 추가해뒀습니당. raw 코드는 가독성이 안 좋아서 캡쳐로 보여드립니다!)
node genApi.node.js 스크립트로 추가해서 사용중

장점

  • 서버 ↔ 프론트 협업시 컴케비용 낮아짐 (출력값에 대한 정의가 상세하게 되어있을 시)
  • 엔드포인트 수동으로 입력하지 않아도 됨 → URL 오타, get/post 메서드 오타 등 다양한 실수에서 자유로워진다.

단점

  • 생성된 타입이 잘못 입력되어있을 경우 사용할 수 없음 or 다큐멘테이션 수정요청 필요

Reference

const { generateApi } = require('swagger-typescript-api')
const path = require('path')
const fs = require('fs')

generateApi({
  url: 'apidoc의 url',
  httpClientType: 'axios',
  generateClient: true,
  generateRouteTypes: false,
  generateResponses: true,
  toJS: false,
  extractRequestBody: true,
  defaultResponseType: 'any',
  enumNamesAsValues: true,
  modular: true,
  hooks: {
    onParseSchema: (originalSchema, parsedSchema) => {
      if (originalSchema.type === 'json') {
        parsedSchema.content = 'JSON'
      }
      return parsedSchema
    },
  },
})
  .then(({ files, configuration }) => {
    files.forEach(({ content, name }) => {
      const fileContent = name === 'http-client.ts' ? `// @ts-nocheck \n${content}` : content

      fs.writeFile(`${path.resolve()}/src/apis/generated/${name}`, fileContent, (err, result) => {
        if (err) console.log('error', err)
        else {
          console.log(`✅ ${name} generated!`)
        }
      })
    })
  })
  .catch((e) => console.error(e))
profile
프론트엔드 개발자. 기록하기, 요가, 등산

2개의 댓글

comment-user-thumbnail
2023년 1월 20일

저는 OpenAPI Generator 와 swagger-typescript-api 사이에서 어떠한 도구를 선택할지 고민중인데요!
swagger-typescript-api 잘 쓰고계신지 근황이 궁금하네용.. ㅎㅎ 🤤

1개의 답글