Flask REST API 문서 자동화 하기, Flasgger
업데이트:
결론
Flasgger를 적용하여 API 문서 작성.
- 현재 Flask와 Flask-restful, Flask-sqlalchemy를 이용해서 REST API를 개발
- Swagger UI version 3과 OAS 3.0을 지원하는 Flasgger라는 라이브러리를 통해 API 문서를 작성
- 실제 프로젝트 소스에 적용하기 전에는 Swagger UI Editor라는 웹 OAS 에디터를 통해 작성
- Spring에 Swagger를 적용하는 것처럼 ‘문서 자동화는 이루지 못함’(메소드별 자동 yml 매핑 정도..)’
- 하지만 프로젝트 내부에 API 문서도 함께 관리할 수 있음에 감사
Flasgger의 소개 및 사용방법은 뒤에 …
문서화의 필요성을 여실히 느끼다
- 지금까지 Flask로 REST API를 개발함
- Swagger UI Editor로 OAS 3.0으로 설계 문서 작성함
- Swagger가 Spring 진영에서 사용한다고 하여 Swagger JSON, UI 도전 안함.
- Postman으로 API 테스트를 수행하였고, Publish Docs 기능을 이용해서 문서화 진행
- 하지만, 특정 메소드의 변화가 반영되지 않는 문제점이 있었음.
- 또한 명확한 문서 유지 보수 필요성을 느낌
- 클라이언트 개발 팀원에게 API 문서를 전달해야함
- 설계 수정을 해야하는데 문서가 없으면 한눈에 보기가 어려움
- 그래서 결국 Auto Documentation을 할 방법을 다시 찾아봄.
느낀점 : 처음에 문서 유지 보수 방안을 잘 정해놓자. 안그래도 할게 많은데 문서를 다시 작성하는 것은 너무 귀찮았고, 또, 초기 설계대로 되는 법이 없어서 무조건 고치게 된다.
Flask auto documentation
‘Flask 문서 자동화’, ‘Flask auto documentation’ 그리고 ‘Flask Swagger’등의 키워드로 검색하면, 마땅한 라이브러리나 참고할 글들이 나오지 않는다.
내가 찾았던 방법들은 다음과 같다.
- Flask-restplus
- Flask-restful-swagger
- Flask-apispec
이외의 라이브러리도 다 400~600 대의 Star였다.
Flask-restplus
Flask REST API 개발을 시작하지 않았다면 Flask-restplus도 고려해보길 바란다.
Flask의 REST 개발 라이브러리는 크게 2가지가 있다. Flask-restful과 Flask-restplus이다.
나는 restful이 코드가 간결해보여서 택했는데, restful은 swagger를 기본적으로 지원해주지 않았다.
하지만 restplus는, 별다른 세팅없이 개발한대로 자동으로 문서화 되도록 지원이 잘 되어있었다. 더불어서, 참고할 한글 블로그 글도 있었다.
Flask-restful-swagger
현재 Flask-restful을 사용하고 있어서, 이 라이브러리를 위한 Swagger 라이브러리를 또 찾아보았다.
flask-restful-swagger is a wrapper for flask-restful which enables swagger support. In essence, you just need to wrap the Api instance and add a few python decorators to get full swagger support.
Star는 600개 정도, 가장 최근 커밋이 3 months ago 였다. Issue를 먼저 확인했다.
Python 3.8에 대한 2018년에 작성된 Issue가 있었는데, 아직까지 답변이 없었다. 내가 3.8로 개발하고 있어서 약간 쎄했다.
예제 코드를 보니, @swagger.operation으로 메소드에 데코레이터를 달고, 추가적인 정보를 넣을 수 있었다. Model에는 @swagger.model 데코레이터만 달면 되었다. 간단해 보였다.
flask-restful-swagger 실패
예상되는 원인은, 해당 라이브러리의 Factory pattern에 대한 지원이 없기 때문인 것 같다. init_app()는 오류가 발생했고, 구글링해도 검색 결과가 없었다(나만 못했을 확률도 높다).
1
2
3
4
5
6
7
8
api.init_app(app)
# Set up flask-restful-swagger
api = swagger.docs(api,
apiVersion='0.1',
basePath="http://localhost:5000",
resourcePath="/",
description="A Basic API"
)
위와 같이 다른 방법으로도 시도해 보았지만, 웹 상에 Swagger UI 자체가 렌더링되지 않았다.
/api/spec, /api/spec.json, /api/spec.html 다 404 Error…
Flask-apispec 보류
다음으로 찾은, Flask auto documentation이라고 검색하면 가장 먼저 나오는 library였다. 가장 최근 커밋이 9 days ago 였지만, 역시나 Star는 400개 정도 였다.
flask-apispec is a lightweight tool for building REST APIs in Flask. flask-apispec uses webargs for request parsing, marshmallow for response formatting, and apispec to automatically generate Swagger markup. You can use flask-apispec with vanilla Flask or a fuller-featured framework like Flask-RESTful.
예시 Quickstart 코드는 다음과 같았다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from flask import Flask
from flask_apispec import use_kwargs, marshal_with
from marshmallow import Schema
from webargs import fields
from .models import Pet
app = Flask(__name__)
class PetSchema(Schema):
class Meta:
fields = ('name', 'category', 'size')
@app.route('/pets')
@use_kwargs({'category': fields.Str(), 'size': fields.Str()})
@marshal_with(PetSchema(many=True))
def get_pets(**kwargs):
return Pet.query.filter_by(**kwargs)
하지만, 다음과 같은 이유로 이 라이브러리는 사용을 보류했다.
- Flask-restful을 지원한다고 하지만 설명이 부족하다(예시 코드를 찾을 수 없다)
- 사용하지 않고 있는 webargs 라는 라이브러리를 사용한다
- 사용하지 않고 있는 use_kwargs, marshal_with 데코레이터를 사용한다.
Flasgger
그리고..마지막으로 Flasgger를 찾았다. Star가 2.3k였다. README.md 마저 깔끔했다(눈물). Flasgger repo
Easy OpenAPI specs and Swagger UI for your Flask API
README.md와 examples 코드들이 빠방했고, issue와 stack-overflow도 검색 결과가 있었다. 그 결과로, Flasgger를 사용하기로 결정했다.
나름대로 정리한 소개 및 사용법은 다음과 같다.
소개
- Swagger UI 2와 3 모두 지원
- OpenAPI version 2와 3 모두 지원
- 하지만 OAS 3.0은 Stable하지 않은 것 같다(Still experimental)
로 다운로드 할 수 있다1
pip install flasgger
- Flask-restful 라이브러리를 지원하고 예제 코드도 있다.
- Factory pattern(init_app())을 지원한다.
- Validation도 지원한다.
사용법
README.md 에서는 크게 다음과 같이 나누고 있다.
- Using docstrings as specification
- Using external YAML files
- Using dictionaries as raw specs
- Using Marshmallow schemas
나는 docstring이나 dictionary가 아닌 yml 파일로 spec을 작성했다. Marshmallow는 내가 flask-marshmallow를 사용하고 있어서 도전하지 않았다.
OAS 3.0 설정
기본 설정이 OAS 2.0 spec이므로 따로 설정해줘야한다.
나는 config.py를 별도로 작성하여 app 생성시에 적용해주고 있다.
1
2
3
4
5
6
# project/swagger.py
swagger_config = {
'openapi': '3.0.0',
...
}
1
2
3
4
5
6
# project/config.py
class Config:
# flasgger config
from swagger import swagger_config
SWAGGER = swagger_config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# project/app/__init__.py
...
from config import config as Config
db = SQLAlchemy()
ma = Marshmallow()
api = Api()
swagger = Swagger(template=swagger_template, parse=True)
def create_app(config):
app = Flask(__name__)
config_name = config
if not isinstance(config, str):
config_name = os.getenv('FLASK_CONFIG', 'default')
app.config.from_object(Config[config_name])
# Set up extensions
db.init_app(app)
ma.init_app(app)
api.init_app(app)
swagger.init_app(app)
return app
doc_dir 설정
doc_dir를 설정하면 Resource의 get, post 등의 메소드와 yml 파일을 자동으로 매핑해준다. 이를 통해 yml 파일만 별도의 폴더로 관리할 수 있다.
- 예시 Resource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# project/app/resources/user.py
...
from flask_restful import Resource
class LoginApi(Resource):
def post(self):
...
return '', 200
class LogoutApi(Resource):
@confirm_account
def post(self):
...
return '', 200
- config에 다음과 같이 디렉토리를 지정해준다.
1
2
3
4
5
6
# project/swagger.py
swagger_config = {
'doc_dir': './app/docs/'
...
}
- project/app/docs/ 디렉토리와 파일을 다음과 같이 만들어 준다.
- yml파일은 post, get, put, delete등 이름에 맞게 적어준다.
- post.yml을 OAS 3.0에 맞게 작성해준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# project/app/docs/LoginApi/post.yml
tags:
- user
summary: Logs user into the system
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: "#/components/schemas/user_auth_token"
"401":
description: Invalid useremail/password supplied
content:
application/json:
schema:
$ref: "#/components/schemas/api_fail_response"
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/login_user"
description: Login user object
required: true
- localhost:5000/apidocs에서 확인할 수 있다.
덧붙여서 …
또한 OAS 3.0 Spec의 Components, info, tags 등의 정보도 물론 지정해줄 수 있다. template dict를 만들어 Swagger 객체 생성시 지정해주면 된다.
공식 문서를 참고하더라도 헷갈리는 분이 있으시다면, 댓글 달아주시면 해당 부분에 대한 설명도 향후에 추가하도록 하겠다 :)
댓글남기기