728x90
반응형
Overview
데코레이터는 Python의 강력한 기능 중 하나로, 코드를 간결하고 우아하게 만들어준다.
클래스에서 사용하는 주요 데코레이터들을 알아보자.

1. @property: Getter 만들기
`@property` 는 메서드를 속성처럼 사용할 수 있게 해준다.
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
"""반지름 getter"""
return self._radius
@property
def diameter(self):
"""지름 계산"""
return self._radius * 2
@property
def area(self):
"""넓이 계산"""
return 3.14159 * self._radius ** 2
# 사용
circle = Circle(5)
print(circle.radius) # 5 - 메서드처럼 ()가 필요 없음!
print(circle.diameter) # 10
print(circle.area) # 78.53975
장점
- 메서드를 속성처럼 깔끔하게 사용
- 계산된 값을 속성처럼 접근 가능
- 내부 로직을 숨기고 깔끔한 인터페이스 제공
2. @property.setter: Setter 만들기
속성 값을 설정할 때 유효성 검사나 추가 로직을 넣을 수 있다.
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if value < 0:
raise ValueError("나이는 0보다 작을 수 없습니다!")
if value > 150:
raise ValueError("나이가 너무 많습니다!")
self._age = value
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not value or not value.strip():
raise ValueError("이름은 비어있을 수 없습니다!")
self._name = value.strip()
# 사용
person = Person("철수", 25)
print(person.age) # 25
person.age = 30 # setter 호출
print(person.age) # 30
person.age = -5 # ValueError: 나이는 0보다 작을 수 없습니다!
왜 사용하나요?
- 데이터 유효성 검사
- 값 변경 시 추가 작업 수행
- 캡슐화: 내부 구현을 숨기면서 안전하게 값 변경
3. @property.deleter: Deleter 만들기
속성 삭제 시 동작을 정의한다.
class BankAccount:
def __init__(self, balance):
self._balance = balance
@property
def balance(self):
return self._balance
@balance.setter
def balance(self, value):
if value < 0:
raise ValueError("잔액은 음수일 수 없습니다!")
self._balance = value
@balance.deleter
def balance(self):
print("계좌를 초기화합니다.")
self._balance = 0
# 사용
account = BankAccount(10000)
print(account.balance) # 10000
del account.balance # 계좌를 초기화합니다.
print(account.balance) # 0
4. @dataclass: 자동으로 클래스 생성
Python 3.7+에서 도입된 `@dataclass` 는 보일러플레이트 코드를 줄여준다.
from dataclasses import dataclass, field
from typing import List
# 일반 클래스
class PersonOld:
def __init__(self, name, age, email):
self.name = name
self.age = age
self.email = email
def __repr__(self):
return f"Person(name={self.name}, age={self.age}, email={self.email})"
def __eq__(self, other):
return (self.name == other.name and
self.age == other.age and
self.email == other.email)
# @dataclass 사용
@dataclass
class Person:
name: str
age: int
email: str
hobbies: List[str] = field(default_factory=list) # 기본값
# 사용
person1 = Person("철수", 25, "chulsoo@email.com")
person2 = Person("철수", 25, "chulsoo@email.com")
print(person1) # Person(name='철수', age=25, email='chulsoo@email.com', hobbies=[])
print(person1 == person2) # True - __eq__ 자동 생성!
@dataclass 옵션
@dataclass(
frozen=True, # 불변 객체로 만들기
order=True, # <, >, <=, >= 비교 연산자 추가
eq=True, # == 연산자 (기본값 True)
repr=True # __repr__ 자동 생성 (기본값 True)
)
class Product:
name: str
price: int
stock: int = 0 # 기본값
5. 클래스 데코레이터: 클래스 자체를 수정
클래스 전체에 데코레이터를 적용할 수 있다.
def singleton(cls):
"""싱글톤 패턴 데코레이터"""
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self):
print("데이터베이스 연결 생성!")
self.connection = "Connected"
# 사용
db1 = Database() # 데이터베이스 연결 생성!
db2 = Database() # 출력 없음 - 같은 인스턴스 반환
print(db1 is db2) # True
6. 메서드 데코레이터: 성능 측정
import time
from functools import wraps
def timer(func):
"""함수 실행 시간을 측정하는 데코레이터"""
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 실행 시간: {end - start:.4f}초")
return result
return wrapper
class DataProcessor:
@timer
def process_large_data(self, data_size):
"""대용량 데이터 처리 시뮬레이션"""
total = 0
for i in range(data_size):
total += i
return total
# 사용
processor = DataProcessor()
result = processor.process_large_data(1000000)
# process_large_data 실행 시간: 0.0234초
7. 실전 예제: 모든 데코레이터 활용
from dataclasses import dataclass
from functools import wraps
def validate_positive(func):
"""양수 검증 데코레이터"""
@wraps(func)
def wrapper(self, value):
if value <= 0:
raise ValueError(f"{func.__name__}: 양수만 가능합니다!")
return func(self, value)
return wrapper
class Product:
def __init__(self, name, price, stock):
self._name = name
self._price = price
self._stock = stock
@property
def name(self):
return self._name
@property
def price(self):
return self._price
@price.setter
@validate_positive
def price(self, value):
self._price = value
@property
def stock(self):
return self._stock
@stock.setter
@validate_positive
def stock(self, value):
self._stock = value
@property
def total_value(self):
"""재고 총액 계산"""
return self._price * self._stock
@staticmethod
def apply_tax(price, tax_rate=0.1):
"""세금 계산"""
return price * (1 + tax_rate)
@classmethod
def create_bundle(cls, name, items):
"""묶음 상품 생성"""
total_price = sum(item.price for item in items)
total_stock = min(item.stock for item in items)
return cls(name, total_price, total_stock)
# 사용
laptop = Product("노트북", 1000000, 50)
print(laptop.total_value) # 50000000
laptop.price = 1200000 # setter로 가격 변경
print(laptop.total_value) # 60000000
print(Product.apply_tax(laptop.price)) # 1320000.0
laptop.price = -100 # ValueError: price: 양수만 가능합니다!
데코레이터 비교 정리
| 데코레이터 | 용도 | 적용 대상 |
| `@property` | Getter 만들기 | 메서드 |
| `@속성.setter` | Setter 만들기 | 메서드 |
| `@속성.deleter` | Deleter 만들기 | 메서드 |
| `@staticmethod` | 정적 메서드 | 메서드 |
| `@classmethod` | 클래스 메서드 | 메서드 |
| `@dataclass` | 자동 클래스 생성 | 클래스 |
| 커스텀 데코레이터 | 원하는 기능 추가 | 클래스/메서드 |
결론
데코레이터를 잘 활용하면
- 코드가 간결하고 읽기 쉬워진다
- 반복되는 로직을 재사용할 수 있다
- 관심사를 분리하여 유지보수가 쉬워진다
- 더 안전하고 견고한 코드를 작성할 수 있다
데코레이터는 처음엔 어렵게 느껴질 수 있지만, 익숙해지면 없어서는 안 될 강력한 도구가 된다.
Reference
- Python Official Docs - dataclasses: https://docs.python.org/3/library/dataclasses.html
- Python Official Docs - Built-in Functions (property, classmethod, staticmethod): https://docs.python.org/3/library/functions.html
튜토리얼 & 가이드
- Real Python - Properties: https://python101.pythonlibrary.org/chapter25_decorators.html
- Florimond Manca - Reconciling Dataclasses and Properties: https://florimond.dev/en/posts/2018/10/reconciling-dataclasses-and-properties-in-python/
- Machine Learning Plus - Method Decorators: https://www.machinelearningplus.com/python/python-method-decorators-classmethod-vs-staticmethod-vs-property/
- Better Programming - Magical Decorators: https://betterprogramming.pub/how-to-use-the-magical-staticmethod-classmethod-and-property-decorators-in-python-e42dd74e51e7
심화 자료
- Stack Overflow - Dataclasses and Property: https://stackoverflow.com/questions/51079503/dataclasses-and-property-decorator
- TutorialsTeacher - Static Method Decorator: https://www.tutorialsteacher.com/python/staticmethod-decorator
728x90
반응형
'Launguage' 카테고리의 다른 글
| Python 예외 처리와 컨텍스트 매니저 완벽 가이드 (0) | 2025.12.19 |
|---|---|
| Python 상속과 다형성 완벽 가이드 (0) | 2025.12.05 |
| Python 매직 메서드 완벽 가이드 (0) | 2025.11.07 |
| Python 메서드의 3가지 종류: Instance, Class, Static Method 완벽 정리 (1) | 2025.10.24 |
| Python 가상환경 설정(WSL2 Ubuntu) (0) | 2023.10.10 |