라떼군 이야기


4 / 13강

데코레이터: 기능을 감싸서 더하기

문자열을 저장하는 객체에 기록 기능을 더하고 싶습니다. 원래 저장 객체를 고치거나 저장 방식마다 하위 클래스를 만들지 않고, 같은 메서드를 제공하는 객체로 감쌀 수 있습니다.

호출을 감싼 뒤 원래 객체에 전달합니다

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를 호출한다면 그대로 교체할 수 없습니다. 데코레이터의 핵심은 사용하는 쪽이 기대하는 인터페이스와 동작의 약속을 유지하면서 기능을 추가하는 것입니다.

제품 개발 파트너나 강의를 찾으시나요? 개인, 팀, 기업 모두 환영합니다. 문제 정의부터 출시까지 함께하며, 팀과 학교에 맞춘 개발 강의도 합니다.