Django 프로젝트에서 비지니스 로직에 영향을 주지 않고 최대한 깔끔하게 로깅 하는 방법을 찾다보니 데코레이터가 떠올랐다.(Spring 에서 많이 사용하는 AOP(Aspect Oriented Programming) 느낌으로 접근하면 이해가 편할 것 같다.)

 

로그를 남기는 데이터는 별것없다. 누가, 언제, 어떤 action 3개의 데이터만 해당 view 에 접근했을때 Logging DBinsert 하려한다.

view


DRF를 이용해서 view를 만들었다. @api_view 또한 데코레이터를 사용하기 때문에 순서가 중요하다.
api_view 먼저 실행 시키고 그다음에 나의 custom logging 데코레이터를 실행 하려한다.

@api_view(['GET'])
@Logging.log_decorator('고객을 가져오는 액션!')
def get_customer(request: Request) -> Response:



데코레이터


Logging Modelstatic 메소드로 데코레이터를 생성했다.
데코레이터가 무려 두개나 있는데 이는 action 이라는 매개변수를 전달 받기 위함이다.

(stackoverflow 참조: https://stackoverflow.com/questions/5929107/decorators-with-parameters)


function(*args, **kwargs)은 기존의 view 로직을 실행하는 구문이다.
필자는 기존의 view 로직을 수행하기 전에 로깅을 하기 원한다.
Logging 데이터를 추가하기 전에 argsapi_view 데코레이터를 처리한 뒤 반환된 값이라 Django에서 사용하는 user 객체를 이용할 수 있다. 해서 user 데이터를 args[0].user.username을 사용해서 추가했다.

필자가 실행한 전처리보다는 후처리를 하고 싶은 경우엔 # 후처리 부분에 로직을 넣으면 된다.

class Logging(TimeStampedModel):
    user = models.CharField(max_length=255)
    action = models.CharField(max_length=255)
    created = models.DateTimeField(auto_now_add=True)

    @staticmethod
    def log_decorator(action: str):
        def decorator(function):
            def wrapper(*args, **kwargs):
                try:  # 전처리
                    Logging.objects.create(user=args[0].user.username, action=action).save()
                except Exception as e:
                    print("###Error####", e)
                result = function(*args, **kwargs)
                # print('GoodBye~')  # 후처리
                return result

            return wrapper

        return decorator





결론 : 비지니스 로직에 Logging 로직을 넣지 말고 데코레이터를 이용해 넣자. 깔끔해진다.

+ Recent posts