데코레이터: 기능을 감싸서 더하기
문자열을 저장하는 객체에 기록 기능을 더하고 싶습니다. 원래 저장 객체를 고치거나 저장 방식마다 하위 클래스를 만들지 않고, 같은 메서드를 제공하는 객체로 감쌀 수 있습니다.
호출을 감싼 뒤 원래 객체에 전달합니다
class MemoryStore:
def __init__(self):
self.items = []
def write(self, text):
self.items.append(text)
class LoggedStore:
def __init__(self, inner):
self.inner = inner
def write(self, text):
print("write:", text)
self.inner.write(text)
store = MemoryStore()
LoggedStore(store).write("hello")
print(store.items)
write: hello를 출력한 뒤 저장된 ['hello']를 보여 줍니다. LoggedStore도 MemoryStore처럼 write(text)를 제공합니다. 호출하는 쪽은 저장 객체가 기록 계층에 감싸여 있는지 몰라도 됩니다.
압축과 암호화처럼 여러 기능을 겹쳐 감쌀 수도 있습니다. 다만 순서가 결과에 영향을 줍니다. 먼저 압축한 뒤 암호화하는 것과 반대 순서는 같은 작업이 아닙니다. 감싼 계층이 많으면 오류가 어디서 났는지 추적하기도 어려워집니다.
Python의 @ 문법과는 구분합니다
Python 데코레이터는 함수나 클래스를 받아 다른 값으로 바꾸는 문법과 기능입니다. 객체를 같은 인터페이스로 감싸는 설계패턴을 구현하는 데 활용할 수 있지만, 두 개념이 항상 같은 것은 아닙니다. 여기서는 일반 객체의 구성으로 패턴을 보여 줍니다.
확인 문제
감싸는 객체의 메서드 이름을 save_with_log로 바꾸면 기존 호출 코드를 그대로 쓸 수 있을까요?
해설 보기
기존 코드가 write를 호출한다면 그대로 교체할 수 없습니다. 데코레이터의 핵심은 사용하는 쪽이 기대하는 인터페이스와 동작의 약속을 유지하면서 기능을 추가하는 것입니다.