유튜브 강의를 듣고 정리하였습니다.
출처: 유튜브 - Decorators - Advanced Python Tutorial #2
✔ 반복되는 코드 제거
예를 들어, 로그인 체크, 권한 확인, 로깅 등을 여러 함수에 적용할 때 코드 중복을 줄일 수 있습니다.
✔ 가독성 향상
코드가 더 깔끔하고 이해하기 쉬워집니다.
✔ 분리된 유지보수
기존 함수의 코드를 직접 수정하지 않고도 새로운 기능을 추가할 수 있습니다.
데코레이터는 보통 함수를 감싸는 함수(wrapper)를 사용해 구현합니다.
def mydecorator(function):
def wrapper():
print("I am decorating your function!")
function() # 원래 함수 실행
return wrapper
def hello_world():
print("Hello World")
decorated_hello = mydecorator(hello_world) # 데코레이터 적용
decorated_hello()
📌 실행 결과
I am decorating your function!
Hello World
✔ mydecorator(hello_world)는 wrapper 함수를 반환합니다.
✔ wrapper()가 실행되면서 추가적인 동작(출력)이 먼저 실행된 후, 원래 함수(hello_world())가 호출됩니다.
Python에서는 @데코레이터명을 사용하면 더 간결하게 적용할 수 있습니다.
def mydecorator(function):
def wrapper():
print("I am decorating your function!")
function()
return wrapper
@mydecorator
def hello_world():
print("Hello World")
hello_world()
✔ @mydecorator
를 사용하면 hello_world = mydecorator(hello_world)
와 같은 효과를 가집니다.
✔ hello_world()
를 실행하면 자동으로 데코레이터가 적용된 상태로 실행됩니다.
위 예제는 인자를 받지 않는 함수에만 사용할 수 있습니다.
함수에 인자를 전달하려면 *args, **kwargs를 사용해야 합니다.
def mydecorator(function):
def wrapper(*args, **kwargs):
print("I am decorating your function!")
return function(*args, **kwargs) # 원래 함수 실행 후 결과 반환
return wrapper
@mydecorator
def hello(person):
print(f"Hello {person}")
hello("Mike")
✔ wrapper(*args, *kwargs)가 모든 인자를 받아서 function(args, **kwargs)로 전달합니다.
✔ hello("Mike") 실행 시 "Hello Mike"
가 출력됩니다.
데코레이터가 적용된 함수가 반환값을 갖는 경우, wrapper()도 원래 함수의 반환값을 반환해야 합니다.
def mydecorator(function):
def wrapper(*args, **kwargs):
return_value = function(*args, **kwargs) # 원래 함수 실행
print("I am decorating your function!")
return return_value # 원래 함수의 결과 반환
return wrapper
@mydecorator
def hello(person):
print(f"Hello {person}")
return f"Hello {person}!"
print(hello("Mike"))
✔ 원래 함수의 반환값을 return_value에 저장한 후 반환합니다.
✔ 따라서 print(hello("Mike")) 실행 시 "Hello Mike!"
가 출력됩니다.
import time
def timed(function):
def wrapper(*args, **kwargs):
start_time = time.time() # 시작 시간
result = function(*args, **kwargs) # 원래 함수 실행
end_time = time.time() # 종료 시간
print(f"{function.__name__} took {end_time - start_time:.5f} seconds")
return result
return wrapper
@timed
def compute_factorial(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
compute_factorial(10000)
✔ 실행 시간을 측정하고 출력해주는 데코레이터
✔ compute_factorial(10000) 실행 시 took X.XXXXX seconds가 출력됨
def logged(function):
def wrapper(*args, **kwargs):
value = function(*args, **kwargs) # 원래 함수 실행
with open("logfile.txt", "a+") as f:
fname = function.__name__
f.write(f"{fname} returned value {value}\n") # 결과를 파일에 기록
return value
return wrapper
@logged
def add(x, y):
return x + y
print(add(10, 20))
✔ logfile.txt에 "add returned value 30"이 저장됨
✔ print(add(10, 20)) 실행 시 결과 30이 출력됨
def requires_admin(function):
def wrapper(user_role, *args, **kwargs):
if user_role != "admin":
print("Access denied: Admins only")
return
return function(*args, **kwargs)
return wrapper
@requires_admin
def delete_database():
print("Database deleted!")
delete_database("user") # Access denied
delete_database("admin") # 실행됨
✅ 데코레이터는 기존 코드를 수정하지 않고 기능을 추가하는 강력한 도구
✅ @데코레이터 문법을 사용하면 깔끔한 코드 작성 가능
✅ 실행 시간 측정, 로깅, 권한 체크 등 다양한 실전 활용 가능