Swagger는 OpenAPI 정의를 사용하여 API를 코드로 작성하고, Swagger UI를 사용하여 프로젝트에서 지정한 URL에 문서를 보여줄 수 있게 해주는 도구이다. Swagger UI가 제공해준 페이지를 통해 서버로 요청을 보낼 수도 있고 응답을 확인할 수도 있다.
1. 서버 프로그래밍 언어를 거치지 않고 Swagger API를 독립적인 별도의 문서로 만드는 방식.
ex) yaml 파일을 생성하여 API를 명세.
2. 서버 프로그래밍 언어를 이용해서 Swagger API를 종속적인 형태로 만드는 방식.
ex) 스프링, express 프레임워크에서 어노테이션을 활용하여 API를 명세
이번 포스팅에서는 1번 독립적인 별도의 yaml 문서로 만드는 방식으로 진행해보려 합니다.
API 명세를 쉽게 만들 수 있도록 해주는 SwaggerHub에서 샘플 데이터로 yaml 파일을 만들어본 뒤, 템플릿 없이도 만들어보도록 하겠습니다.
보통 openapi와 swagger 2.0 두 가지를 사용하실 수 있습니다. 저는 openapi를 활용해서 작성했습니다.
servers:
- description: Google api
url: http://localhost:19000
paths는 실제 API의 기능을 정의하는데 사용됩니다.
해당 API가 http method 중 어떤 것을 사용하며, 파라미터는 어떤 것을 사용하며, 응답은 어떤 형태로 처리할 것인지를 명시하는 것이 핵심이다.
paths:
/search/news:
get:
summary: 검색된 뉴스 데이터를 반환.
parameters:
- name: keyword
in: query
schema:
type: string
- name: client
in: query
schema:
type: string
responses:
'200':
description: A Text File
content:
text/plain:
schema:
type: string
간단히 설명하자면, /search/news
란 경로에 접속했을 때에 대한 API를 명세하는데, get 방식으로 들어간 경우, 파라미터로 전달된 두 개의 string 값을 받아서 사용하도록 하였다.
여기서 in: query
방식은 쿼리스트링으로 넘어온 파라미터를 받을 때 사용하며, url path에 속하는 파라미터를 받을 때는 in: path
를 사용한다.
필자는 $ref
로 참조를 걸어 get, post 경로를 search.yaml로 빼주었다.
Before:
paths:
/search/news:
get:
summary: 검색된 뉴스 데이터를 반환
responses:
'400':
$ref: '#/components/responses/BadRequest'
After;
paths:
$ref: "../swagger/search.yaml#/~1search~1news"
이제 /swagger/search.yaml 파일을 생성해주고 코드를 옮기자
/search/news:
get:
tags:
- Search
summary: 서울경제 뉴스
parameters:
- in: query
name: keyword
type: string
required: true
description: 검색 키워드
responses:
"200":
description: 성공
content:
application/json:
schema:
type: object
example:
{
"code": 200,
"data":
...
}
"400":
$ref: "./openapi.yaml#/components/responses/BadRequest"
"500":
$ref: "./openapi.yaml#/components/responses/InternalServerError"
swagger-jsdoc
라이브러리를 사용하여 각각의 API코드 상단에 직접 명세를 작성할 수도 있고, 하나의 yaml
또는 json
파일에 모든 API 명세를 다 넣을수도 있다. 문제는 두 가지 방법 모두 단점이 보였다.
swagger-jsdoc
위 코드는 단 하나의 API에 대한 명세이다. 심지어 전부가 아닌 1/2정도 이다. Swagger는 재사용가능한 파라미터, 응답, 스키마를 분리하여 참조하는 형식으로 코드의 길이를 줄일 수 있는데 swagger-jsdoc
는 다른 파일을 참조할 수 없었다고 한다. 따라서 보통 하나의 컨트롤러 파일에 CRUD 네 가지의 미들웨어가 존재한다고 치면, 위 사진에서 보이는 명세의 최소 5배는 추가될 것이다. 당연히 파일이 더러워질 것이다.
yaml
or json
파일 사용 하나의 파일에 모든 API 명세, 파라미터, 스키마, 응답을 모두 적는 방법이다. yaml
or json
파일 모두 들여쓰기가 중요한데, 하나의 파일에 수많은 명세를 작성하다보면 들여쓰기로 인한 오류는 물론, 내가 보고자하는 API 명세를 찾기는 굉장히 어려울 것이다.
그래서
yaml
을 여러 개로 분리하여 명세와 개발을 진행하고, API 명세를 UI로 확인하고자 할 때는 이를 하나의 yaml
파일로 합치는 방식을 채택했다. 이 방법도 물론 단점이 있다. 개발 시에는 nodemon
을 사용하는데, yaml
파일이 변경되면 새로운 하나의 yaml
을 생성해야 하는 것을 nodemon
이 알 수가 없다. 따라서 API 명세에 대한 코드가 변경되면 직접 파일을 생성해줘야 한다.
yamljs
, swagger-cli
, swagger-ui-express
를 install 한다.
이렇게 파일 구조를 잡고 모듈을 install 한 후, package.json
파일에서 scripts 설정
"scripts": {
"api-docs": "swagger-cli bundle ./swagger/openapi.yaml --outfile ./swagger/swagger.yaml --type yaml",
"prestart": "npm run api-docs",
"start": "nodemon ./bin/www.mjs",
"predev": "npm run api-docs",
"dev": "NODE_ENV=development nodemon ./bin/www.mjs"
},
npm run dev
로 서버 기동 후
swagger.yaml 파일이 생성된것을 확인할 수 있다.