Swagger UI와 flask_restplus

햄도·2020년 12월 3일
1

Swagger란?

  • Open Api Specification을 위한 프레임워크
  • API들이 가지고 있는 스펙을 명세, 관리할 수 있는 프로젝트
  • API 문서화를 수작업으로 하는 것은 매우 귀찮고, API가 수정될때마다 문서를 같이 수정하는 것은 더더욱 귀찮다. 이러한 불편함을 줄여주기 위해 개발된 프로젝트

Flask-RESTx / Flask-RESTPlus

  • REST API를 빠르게 빌드하고, Swagger 포함 여러 기능들이 들어있는 Flask 확장 프레임워크이므로 Flask에 익숙하다면 쉽게 접근할 수 있다.
  • flask-restplus 프로젝트 중단?
  • flask-restx로 fork되었다
  • 여기에서는 기초적인 Flask 예제에서 하는 것처럼 function을 route시킬 수 없고, Resource에서 파생된 클래스만 이용할 수 있다. 따라서 기존 function은 class로 변경해야 한다.

코드에 적용하기

  • Resource를 상속한 클래스에 get, post, put 등 rest api method에 해당하는 function들을 만들면 swagger UI에 추가되고, route 함수 안에 method 인자를 넣지 않아도 해당하는 method의 요청을 연결해준다.
    # resource1.py
    @resource1_api.route('/resource1')
    class FirstResource(Resource):
        @resource1_api.expect(parser)
        def test_func(self): # swagger UI에 method가 추가되지 않는다.
            result = {'result_msg': 'Success'}
            return result, 200

    ...(후략)
    # resource2.py
    @resource2_api.route('/resource2')
    class SecondResource(Resource):
        @resource2_api.expect(parser)
        def get(self): # get method로 설정
            result = {'result_msg': 'Success'}
            return result, 200

    ...(후략)
  • flask의 Blueprint와 같이 연관된 리소스들을 묶어 api를 계층적으로 관리하고 싶은 경우 Namespace를 사용한다.
    # resource1.py

    # Blueprint 와 Namespace 모두 사용 가능
    resource1_app = Blueprint('resource1_app', __name__, url_prefix='/routes')
    resource1_api = Namespace('resource1_api', path='/routes')

    @resource1_api.route('/resource1')
    class FirstResource(Resource):
          @resource1_api.expect(parser)
          def get(self):
            result = {'result_msg': 'Success'}
            return result, 200

    ...(후략)
    # app.py
    app = Flask(__name__,
                static_url_path='', 
                static_folder='static', 
                template_folder='templates'
    )
    # Blueprint 등록
    app.register_blueprint(resource1_app)

    # '/doc' 경로에 API 생성
    api = Api(app, title='My API', doc='/doc')

    # resource1.py에서 생성한 api를 import해 Namespace에 등록
    api.add_namespace(resource1_api))
  • @resource1_api.expect(parser) 를 이용해 api 문서에 필요한 파라미터들을 추가할 수 있다. 이 때 parser는 flask-restx의 reqparse를 사용하면 되고, python argparse와 사용법이 유사하다.
    from flask-restx import Namespace, Resource, reqparse, Api

    parser = reqparse.RequestParser()

    parser.add_argument('page', type=int, default=1, help='페이지 번호')
    parser.add_argument('page_count', type=int, default=50, help='페이지 당 item 수')

    # api 구현
    @resource1_api.route('/resource1')
    class FirstResource(Resource):
        @resource1_api.expect(parser)
        def get(self):
            result = {'result_msg': 'Success'}
            return result, 200

    ...(후략)
  • @resource1_api.response() 를 이용해 documentation에 response에 대한 설명을 추가할 수 있다. 상태값은 result dict와 함께 반환하면 된다.
    # resource1.py

    @resource1_api.route('/resource1')
    class FirstResource(Resource):
        @resource1_api.expect(parser)
        @resource1_api.response(200, 'Success')
        @resource1_api.response(400, 'Bad Request')
        def get(self):
                
            try:
            
                (중략)

    			result = {
                    'result_msg' : '성공',
                    'result_count' : len(result_list),
                    'result_list' : result_list
    	            }, 200 # 상태값을 같이 반환

            except Exception as e :
                LOG.error(e)
                result = {
                    'result_msg' : f'오류발생 ::: {e}'
                }, 400 # 예외 시 상태값 반환

            return result

참고

profile
developer hamdoe

0개의 댓글