1 분 소요


데코레이터란

데코레이터란 함수에 반복적인 기능과 역할을 할 수 있도록 만들어주는 기능이다. 함수 내부의 로직을 수정하지않고, 기능을 추가하거나 수정 하고싶을 때 사용한다.

일반적으로는 함수의 전처리/후처리 등에대해 필요가 있을 때 사용한다.

데코레이터 사용하기

물론 여러가지 미리 작성된 기능들이 있지만, 인증과 관련된 부분을 커스터마이징 해 보려고 한다.

(인증은 장고의 @login_required() 와 같은 데코레이터들이 이미 있다)

데코레이터 선언

from flask import request
from functools import wraps

def api_decorator():
    def api_auth_decorator(f):
        @wraps(f)
        def _api_auth_decorator(*args, **kwargs):
            result = f(*args, **kwargs)
            token = request.headers.get("Authorization")
            if token is None:
                return {"message": "허가되지 않은 접근입니다.", }, 401

            if datetime.datetime.now() >= time_checker(token)
                # time_checker는 현재 token의 만료기간을 체크하는 임의의 함수입니다
                return {"message": "토큰이 올바르지 않습니다.", }, 401
            return result

        return _api_auth_decorator

    return api_auth_decorator
  • 우선, wraps로 데코레이터를 만들어 줄 함수를 정의한다
  • 함수를 인자로 받아서, 해당하는 함수가 실행 되기 전에 미리 실행한다
  • 인자로 받은 *args, **kwargs 들을 가져와서 request되는 정보들을 뽑아본다.
  • (예제로는) header 안에 있는 “Authorization” 을 뽑아 token을 체크한다

데코레이터 적용

로그인이 필요한 코멘트를 작성하는 API를 간단히 예시로 들어보았다

@app.route("/post/comment", methods=["POST"])
@api_decorator()
def post_comment():
    params = json.loads(request.get_data())
    context = params.get("context",None)
    user_id = params.get("userId",None)
    post_id = params.get("postId",None)

    CommentModel.create(
        context = context,
        user_id = user_id,
        post_id = post_id,
    )
    return {"message":"코멘트 작성이 완료되었습니다"}

위에 작성했던 api_dcorator() 를 사용하지 않았다면, 해당하는 router마다 로그인이 되어있는지, 토큰을 체크 해 주어야 하는지에대해서 매번 서비스로직을 넣어 확인 해야 한다

비슷한 기능을 하는 함수들

Flask는 프레임워크이다. 그래서 우리가 만들 데코레이터들과 비슷한 기능을 이미 제공 해 주고 있다.

before_first_request

  • 플라스크 서버가 실행되고 가장 첫 요청 전에 사용되는 로직 ```python from flask import Flask, jsonify

app = Flask(name)

@app.route(“/”) def before_first_request(): log.info(“플라스크가 실행된 후, 가장 첫 request 요청에서만 사용”) return jsonify({“msg”:”before_first_request”})


### before_request

- 플라스크 서버가 실행되고 매 request전에 사용

```python
from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/")
def before_request():
    log.info("플라스크가 실행된 후, request 요청 전에 사용")
    return jsonify({"msg":"before_request"})

after_request

  • 플라스크 서버가 실행되고 매 request 이후에 사용
from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/")
def after_request():
    log.info("플라스크가 실행된 후, request 이후에 사용")
    return jsonify({"msg":"after_request"})

이외에도 teardown_request, teardown_appcontext 등이 존재한다!

댓글남기기