본문 바로가기
Python/Flask

Flask 시작하기 - flask-restx (Namespace, Model)

by 쿠리의일상 2024. 2. 24.

현재 프로젝트에서 Flask를 사용하기로 하였다. 지금껏 플라스크로 셀레니움과 같이 크롤링 자동화만 다뤄봤는데 이번엔 flask 를 주축으로 API Server 를 만들게 되었다. 프론트딴에는 Next.js 를 사용하고 서버딴에는 Flask 를 사용하게 될 예정이다. 기본적으로 프론트 프레임워크가 있으므로 Flask에선 진자2를 굳이 사용할 필욘 없어보인다. 대신 API 문서화를 위한 Swagger UI 를 구성할 수 있는 flask-restx 라이브러리를 정리해본다.

 

Flask 와 Flask-restx 설치 및 import

conda install flask
conda install flask-restx

 

from flask import Flask
from flask_restx import Api, Resource

app = Flask(__name__) 
api = Api(app)

기존 플라스크는 아래처럼 app 을 직접 route 처리해서 페이지 라우팅을 해주었다.

@app.route('/')
def main():
    return 'Hello world'

@app.route('/login')
def login():
    return 'Login'

이 과정에서 template 와 진저2 를 활용하여 웹페이지를 꾸며줬어야 했지만 API 전용 서버이므로 flask_restx를 사용하여 아래처럼 api 로 라우팅을 해준다.

@api.route('/admin')
class AdminAPI(Resource):
    def get(self):
        return {'hello': 'admin!'}
    
@api.route('/user/<string:user_id>/<string:user_name>')
class User(Resource):
    def get(self, user_id, user_name):
        return {"Message": f"Hello, {user_name} ({user_id})"}

해당 주소에 해당하는 페이지로 접근하면 위에 지정해준 json 형태의 정보가 보일 것이다. 큰 차이점은 return 시 정보를 보내냐 html 을 보내냐의 차이와 api 로 라우팅처리를 할 경우 class 안에 get, post 등의 요청 메서드로 함수를 만들어줘야(오버라이딩) 한다는 점이다.

주소창에 동적 주소를 받아주고 싶다면 < >를 사용하여 <타입:변수명> 형태로 작성하고, 요청 메서드의 매개변수로 변수를 받아올 수 있다.

 

Namespace 를 사용한 파일 분리

app.py 파일에 모든 라우팅을 처리할 순 없다. 각 기능마다 패키지-모듈화 하여 분리해줄 수 있는 함수가 존재한다. 기존에 app 및 api 를 정의했던 파일에 아래와 같이 추가해주면 라우팅 처리가 가능하다.

api.add_namespace(네임스페이스명, '/적용될주소')

 

물론 네임스페이스를 지정한 파일을 별도로 아래처럼 준비해둬야 한다.

from flask_restx import Resource, Namespace

네임스페이스명 = Namespace('Swagger에 들어갈 제목', description='Swagger에 들어갈 설명')

@네임스페이스명.route('/')
class 관련클래스(Resource):
    def get(self):
        return {'response': 'test'}

 

Swagger UI 활용

지금껏 작성한 api 들은 기본 주소인 localhost:5000 으로 접속하면 Swagger UI가 적용된 화면을 확인할 수 있다. Swagger UI의 내용들을 변경하기 위해선 아래처럼 작성해준다.

api = Api(
    app,
    version='버전',
    title='가장 최상단 제목',
    description='설명')

그외의 속성들은 아래의 공식문서를 확인해서 채워주자.

https://flask-restx.readthedocs.io/en/latest/api.html

 

API — Flask-RESTX 1.1.1.dev documentation

a 3-tuple (data, code, headers)

flask-restx.readthedocs.io

입력해준 내용으로 바뀌었음을 볼 수 있다.

 

그밖에도 네임스페이스를 활용하여 response 메서드를 아래처럼 수정하면 Swagger UI 내 내용이 추가된다.

@네임스페이스명.response(400, '에러')

이런 기능들이 사용하기 편하게 정리된 공식 문서를 확인하자. https://flask-restx.readthedocs.io/en/latest/swagger.html

 

Swagger documentation — Flask-RESTX 1.1.1.dev documentation

Swagger documentation Swagger API documentation is automatically generated and available from your API’s root URL. You can configure the documentation using the @api.doc() decorator. Documenting with the @api.doc() decorator The api.doc() decorator allow

flask-restx.readthedocs.io

 

 

Resource

flask-restx 에서 class 를 지정할 때 상속받아주는 Response 는 HTTP 메서드를 오버라이딩 할 수 있게끔 처리해준다고 하였다. 지원하지 않는 메서드를 사용할 시 405코드를 반환하게 된다.

@api.route('/user/<string:user_id>/<string:user_name>')
class User(Resource):
    def get(self, user_id, user_name):
        return {"Message": f"Hello, {user_name} ({user_id})"}

 

Model

네임스페이스의 모델은 입출력에 대한 스키마를 나타내는 객체이며, 아래처럼 모델을 설정해줄 수 있다. fields 클래스를 사용하여 타입, 설명, 필수 여부, 예시 등을 넣어줄 수 있다.

from flask_restx import Resource, Namespace, fields
//...
네임스페이스명 = Namespace('네임스페이스 제목', description='설명')

모델변수 = 네임스페이스명.model('모델명', {
    'id': fields.String(required=True, description='Identifier'),
    'name' : fields.String,
})

inherit 을 사용하면 모델을 상속 받을 수도 있다.

@DatabaseNS.route('/')
@DatabaseNS.response(200, '성공', 모델변수)
@DatabaseNS.response(400, '에러')

네임스페이스의 response 에 모델을 등록해주면 위처럼 Swagger에서 확인이 가능하다.

 

.doc( )

해당 메서드는 네임스페이스의 상태코드마다 설명을 추가해주거나 쿼리 파라미터에 대한 설명을 추가해주는 메서드이다.

@DatabaseNS.route('/maindb')
class MainDatabase(Resource):
    @DatabaseNS.doc(responses={200: '성공!'})
    @DatabaseNS.doc(responses={400: '에러!'})
    def get(self):
        """메인 데이터베이스 페이지"""
        return {'Database': 'Main'}

만약 위와 같은 코드를 작성했다면, 아래와 같은 결과 확인이 가능하다.

 

간단하게 정리해보았다.