[express] Swagger AutoGen 으로 가볍게 스웨거 문서를 만들자!

이원찬·2024년 8월 6일

express

목록 보기
3/3

직접 스웨거 문서를 작성하던 도중 너무 화가나 node express 에서 자동으로 스웨거 문서를 생성해 주는 툴이 없을까 하다가 찾게된 swagger-autogen 라이브러리 사용 경험을 포스팅 하려한다.

먼저 swagger 문서를 표시할

swagger-ui-express 라이브러리와 스웨거 문서를 자동 생성 해줄 swagger-autogen 라이브러리를 설치하자

npm install swagger-ui-express swagger-autogen

swagger.js 파일을 만들고 아래와 같이 간단한 정보를 입력한다.

// swagger.js

import swaggerAutogen from "swagger-autogen";

const doc = {
  info: {
    title: "My API",
    description: "Description",
  },
  host: "localhost:4000"
};

// 자동으로 생성될 파일의 경로를 적어준다.
const outputFile = './swagger-output.json';

// controller 들이 박힌 라우터들이 위치한다.
const routes = ['./src/router/movieRouter', 또다른 router들];

// 아래와 같이 swaggerAutogen 함수를 실행한다!
swaggerAutogen()(outputFile, routes, doc);

node swagger.js 로 swagger.js 파일을 실행하면 위와같은 우리가 작성한 경로에 swagger 작성 파일이 생성된다.

{
  "swagger": "2.0",
  "info": {
    "title": "My API",
    "description": "Description",
    "version": "1.0.0"
  },
  "host": "localhost:4000",
  "basePath": "/",
  "schemes": [
    "http"
  ],
  "paths": {
    "/movie": {
      "get": {
        "description": "",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "type": "string"
          },
          {
            "name": "pageSize",
            "in": "query",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      ...

길어서 중간에 좀 잘랐다…

이제 이 문서를 swagger-ui-express 라이브러리를 이용해서 띄워주기만 하면된다.

index.js (혹은 app.js 에서)

import swaggerUi from "swagger-ui-express";
import swaggerFile from "./swagger-output.json" with { type: "json" };

...

// 아래처럼 /doc 경로로 swagger를 제공하면 된다.
app.use("/doc", swaggerUi.serve, swaggerUi.setup(swaggerFile));

그리고 서버를 실행하면…?

잘 나온다!!

문제 발생

query string 이나 path params, body 같은 경우는 autogen 이 잘 잡아주지만

response 같은 경우는 아무것도 띄워 주지 않는다…

또한 query string 또는 request body 같은경우 추가 타입이라던지 힌트를 커스텀 하고 싶다면…?

Response 커스텀 하기

생성된 swagger-output.json 파일을 수정하는게 아닌 라우터에 주석을 달아 해결해보자!

본인은 라우터마다 controller 의 메서드를 달아서 라우팅을 처리하고 있었다.

// movieRouter.js
movieRouter.get("/movie/:movieId", movieController.getMovieDetail);

// movieController.js
getMovieDetail: async (req, res, next) => {
  const { movieId } = req.params;

  if (isNaN(movieId)) {
    throw CustomError.BAD_REQUEST;
  }

  const findMovie = await movieService.getMovieDetail({ movieId });
  res.json(movieConverter.toMovieDetail(findMovie));
},

이제 저 getMovieDetail 메서드 안에 아래와 같은 주석을 넣는다.

/*
#swagger.responses[200] = {
  schema: {$ref: "#/definitions/MovieDetail"}
}
*/

200 응답의 결과로 MovieDetail 이라는 스키마를 응답하겠다는 뜻이다

그렇다면 스키마는 어디에 정의?

우리가 만든 swagger.js 에 만들어 놓으면 된다!!

const doc = {
  info: {
    title: "My API",
    description: "Description",
  },
  host: "localhost:4000",
  
  // 아래부터 추가된 부분!
  definitions: {
    MovieDetail: {
      movieId: 0,
      title: "string",
      genre: "ACTION",
      createdAt: "string",
      updatedAt: "string",
    },
  },
};

아까 만들었던 doc 변수에 MovieDetail 변수를 넣는다!!

그리고 다시 node swagger.js 를 하고 서버를 시작하면?

응답이 잘 생성된다!!

고도화

현재 본인은 MovieConverter를 이용해 응답값 < = > 조회값 사이를 변환하고 있었다.

// movieConverter
export default {
  toMovieDetail: (movie) => ({
    movieId: movie.movieId,
    title: movie.title,
    genre : movie.genre,
    createdAt : movie.createdAt,
    updatedAt : movie.updatedAt,
    isDeleted: !!movie.isDeleted,
  }),
};

위 컨버터를 이용해 스키마를 만들어보았다.

export default {
  toMovieDetail: (movie) => ({
    movieId: movie ? movie.movieId : 0,
    title: movie ? movie.title : "string",
    genre: movie ? movie.genre : 'string',
    createdAt: movie ? movie.createdAt : (new Date()).toISOString(),
    updatedAt: movie ? movie.updatedAt : (new Date()).toISOString(),
    isDeleted: movie ? !!movie.isDeleted : false,
  }),
};

위와 같이 만들어 movie 인자를 주지 않으면 기본값이 되게끔!!

그리고 스키마로 가서

definitions: {
  MovieDetail: movieConverter.toMovieDetail(),
},

위와같이 하고 node swagger로 생성해보면?

개 같이 잘나온다.

더 많은 정보는 아래 공식문서 에서 확인하자
https://swagger-autogen.github.io/docs/getting-started/advanced-usage

profile
소통과 기록이 무기(Weapon)인 개발자

0개의 댓글