본문 바로가기

갈아먹는 파이썬[2] @ decorator란?

지난 글

갈아먹는 파이썬[1] generator와 yield

들어가며

플라스크, 셀러리와 같은 파이썬 오픈 소스 라이브러리들을 보면 @route, @task 등의 구문을 사용합니다.  
대체 이 골뱅이 표기들은 무엇이고, 어떤 역할을 하길래 많이 사용되는 것일까요? 

이 골뱅이의 이름은 데코레이터입니다.

데코레이터 이름을 보면 장식해주는 것? 이름만 들어서는 감이 잘 오지 않습니다.  
지금부터 예시와 함께 데코레이터의 개념과 사용처에 대해서 알아보겠습니다.

 

이 포스팅은 직접 작성한 주피터 노트북에 기반합니다. 스타 한번씩 부탁드려요 ㅎㅎ

https://github.com/yeomko22/python_study

 

yeomko22/python_study

Python study in part of HR-bigdata course of Yonsei Univ Fall 2019. - yeomko22/python_study

github.com

Decorator란?

예시 코드를 먼저 보겠습니다.

데코레이터 함수는 우선 장식을 해줄 func을 파라미터로 전달받습니다.
그리고 decorated라는 함수를 내부에 만들어주고 이를 리턴해줍니다.
decorated 함수 안에서는 전달받은 함수의 앞 뒤에 실행할 코드를 작성해줍니다.

보셨나요? I'm Jeff 만 출력하는 함수가 데코레이터의 장식을 받아 앞 뒤로 문장을 출력합니다.  

즉, 데코레이터는 장식시킬 함수의 

앞과 뒤에서 코드를 실행합니다.

 

렇다면 이런 데코레이터는 언제 사용하나요?  
바로 여러 함수들이 부분적으로 중복되는 작업을 수행하는 경우, 코드의 재사용성을 높이기 위해 사용합니다.  
예시를 통해서 알아보겠습니다.

위 사례처럼 각기 다른 동작을 수행하며, 소요 시간이 다른 세 임의의 함수가 있다고 가정합니다.
이 때 개발자는 각각의 함수가 소요 시간이 얼마나 걸리는지 확인하고자 합니다.
그냥 단순히 코딩을 한다면 다음과 같이 짤 수 있습니다.

수행하고자 하는 동작 앞, 뒤에 현재 시간을 재는 코드가 추가되었습니다.
그리고 수행을 완료한 이후 소요 시간을 출력해줍니다.
그 결과로 서로 다른 세 함수에 동일한 코드가 삽입되었습니다.

 

코드의 가독성 측면에서 이는 그다지 바람직하지 못합니다.
데코레이터를 사용하여서 이를 해결해보겠습니다.

어떤가요? 데코레이터를 사용하면 이처럼 훨씬 깔끔하게 코딩할 수 있습니다.

또한 코드를 재사용할 수 있어서 테스크가 1000개 2000개 늘어나도 동일하게 적용 가능합니다.

class 형 decorator

그런데 앞서 만든 데코레이터는 함수 안에 함수를 정의하여 그렇게 보기 좋진 않습니다.
이제 데코레이터를 함수가 아니라 클래스로 만들어보겠습니다.

이제 데코레이터가 무엇인지 감이 좀 오시나요?  
조금 더 나아가서 실제 프레임워크들에서는 데코레이터를 어떻게 사용하는지 알아보겠습니다.

 

Framework에서의 decorator

먼저 대표적인 파이썬 웹 어플리케이션 프레임워크 flask에서 데코레이터를 어떻게 사용하는 지를 보겠습니다.

이는  / 라는 url로 http 요청이 들어오면 'Hello World'를 리턴하는 API 코드입니다.
사용자는 자신이 수행하고자하는 동작 (Hello World 리턴)을 입력한 뒤에 데코레이터를 달아줍니다.
그러면 플라스크는 해당 url로 http 리퀘스트를 받고, 사용자가 정의한 함수를 실행시키며, http response를 만들어 전해주는

http API에 필요한 여러 동작들을 수행해주는 강력한 함수로 탈바꿈 시켜줍니다.

 

다음으로 파이썬 비동기 분산처리 프레임워크 celery에서 데코레이터를 어떻게 사용하는지 보겠습니다.

단순히 x와 y를 더해주는 함수에 app.task 함수를 데코레이터로 붙여줍니다.
그러면 브로커에 연결된 샐러리 앱이 브로커 내부의 큐에 테스크가 쌓이는 지를 확인하고
테스트가 있으면 가져와서 계산하고 다시 반환을 어쩌고 저쩌고 하는
듣기만해도 현기증 나는 작업들을 해주는 멋진 비동기 함수로 재탄생합니다!

 

즉, 프레임워크의 강력한 기능들을

데코레이터를 통해 쉽게 가져다 쓸 수 있습니다.

 

 

마치며

이제 데코레이터가 무엇이고 실제 개발에선 어떻게 사용되는지 아시겠나요?
끝으로 3줄 요약하면서 마치겠습니다. 감사합니다!

  1. 데코레이터는 함수를 파라미터로 전달 받으며, 그 함수 앞 뒤에 다른 동작들을 수행해준다.
  2. 코드의 재사용성, 가독성을 높이기 위해 사용한다.
  3. 프레임워크를 사용할 때 많이 볼 수 있다.

참고자료

[1] http://book.pythontips.com/en/latest/decorators.html

[2] https://bluese05.tistory.com/30

[3] https://flask.palletsprojects.com/en/1.1.x/quickstart/

[4] https://docs.celeryproject.org/en/latest/userguide/workers.html