python에서 데코레이터(decorator)란?
Python에서 데코레이터(Decorator)는 함수나 메서드에 추가적인 기능을 부여하는 강력한 도구이다. 데코레이터는 코드의 재사용성을 높이고, 함수의 동작을 동적으로 변경할 수 있게 해준다.
1. 데코레이터란?
데코레이터는 다른 함수를 수정하지 않고, 그 함수에 새로운 기능을 추가할 수 있는 방법이다. 간단히 말해, 데코레이터는 함수를 감싸는(wrapper) 함수로, 원래의 함수에 새로운 기능을 추가하거나, 함수의 실행 결과를 수정할 수 있다. 데코레이터는 함수나 메서드를 매개변수로 받아서 새로운 함수를 반환하는 클로저 패턴을 사용한다.
2. 데코레이터의 기본 구조
데코레이터를 정의하는 기본 구조는 다음과 같습니다:
def my_decorator(func):
def wrapper(*args, **kwargs):
# 함수 실행 전
result = func(*args, **kwargs)
# 함수 실행 후
return result
return wrapper
여기서 my_decorator
는 데코레이터 함수이며, wrapper
함수는 원래의 func
함수를 감싸는 함수이다. wrapper
함수 내에서 func
를 호출하고, 그 결과를 반환한다. 데코레이터는 주로 @
문법을 사용하여 적용된다.
3. 데코레이터의 사용 예시
간단한 데코레이터 예시를 통해 데코레이터의 동작을 알아보자.
def simple_decorator(func):
def wrapper():
print("함수 실행 전")
func()
print("함수 실행 후")
return wrapper
@simple_decorator
def say_hello():
print("Hello, World!")
say_hello()
출력:
함수 실행 전
Hello, World!
함수 실행 후
위 코드에서 @simple_decorator
는 say_hello
함수에 데코레이터를 적용한다. say_hello
함수가 호출될 때, 실제로는 wrapper
함수가 실행되며, 그 안에서 say_hello
함수가 호출된다. 이를 통해 함수 실행 전후로 추가적인 동작을 삽입할 수 있다.
4. 데코레이터의 활용 사례
4.1. 로깅 데코레이터
로깅(logging)은 함수가 호출될 때마다 그 동작을 기록하는 것이다. 로깅 데코레이터는 함수를 호출할 때마다 로그를 남기게 한다.
def logging_decorator(func):
def wrapper(*args, **kwargs):
print(f"Calling function {func.__name__} with arguments {args} and {kwargs}")
result = func(*args, **kwargs)
print(f"Function {func.__name__} returned {result}")
return result
return wrapper
@logging_decorator
def add(a, b):
return a + b
result = add(5, 3)
출력:
Calling function add with arguments (5, 3) and {}
Function add returned 8
이 데코레이터는 함수의 이름, 인자, 그리고 반환값을 출력하여 함수의 동작을 추적할 수 있다.
4.2. 실행 시간 측정 데코레이터
함수의 실행 시간을 측정하여 성능을 분석할 수 있다.
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds")
return result
return wrapper
@timer_decorator
def slow_function():
time.sleep(2)
print("Finished slow function")
slow_function()
출력:
Finished slow function
Function slow_function took 2.0023 seconds
이 데코레이터는 함수가 얼마나 오래 실행되는지를 측정한다. 성능 최적화가 필요한 코드에서 매우 유용하다.
4.3. 권한 검사 데코레이터
권한 검사 데코레이터는 사용자가 특정 기능에 접근할 수 있는지를 확인하는 데 사용된다.
def requires_permission(permission):
def decorator(func):
def wrapper(user, *args, **kwargs):
if user.get("permissions", []) and permission in user["permissions"]:
return func(user, *args, **kwargs)
else:
print(f"User {user['name']} does not have permission: {permission}")
return None
return wrapper
return decorator
@requires_permission("admin")
def delete_database(user):
print("Database deleted!")
user = {"name": "Alice", "permissions": ["user"]}
delete_database(user)
admin_user = {"name": "Bob", "permissions": ["admin"]}
delete_database(admin_user)
출력:
User Alice does not have permission: admin
Database deleted!
이 데코레이터는 사용자가 특정 권한을 가지고 있는지 확인하고, 해당 권한이 없으면 함수의 실행을 차단한다.
5. 파라미터가 있는 데코레이터
지금까지 살펴본 데코레이터는 함수에 추가적인 기능을 제공했다. 하지만, 때로는 데코레이터 자체에 파라미터를 전달해야 할 때가 있다. 이를 위해 데코레이터 함수를 또 다른 함수로 감싸는 방식으로 구현할 수 있다.
파라미터를 받는 데코레이터 예시
def repeat(num_times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
출력:
코드 복사
Hello, Alice!
Hello, Alice!
Hello, Alice!
이 예제에서 @repeat(3)
데코레이터는 greet
함수를 3번 반복 실행하도록 한다.