- 데코레이터가 동작하는 방식 이해
- 함수와 클래스에 적용되는 데코레이터를 구현하는 방법
- 일반적인 실수를 피하고 효과적으로 구현하는 방법
- 중복 회피(DRY 원칙 준수)
- 관심사 분리
- 좋은 데코레이터 사례
- 좋은 선택이 될 수 있는 일반적인 상황, 관용구, 패턴
- 문법적 설탕(syntax sugar)
- 데코레이터 이후에 나오는 것을 데코레이터의 첫 번째 파라미터로 하고 데코레이터의 결과 값을 변환
def original(...): ... original = modifier(original)@modifier def original(...): ...- modifier
- 데코레이터
- original
- 데코레이팅된(decorated) 함수, 래필된(wrapped) 객체
- modifier
- 데코레이터 이후에 나오는 것을 데코레이터의 첫 번째 파라미터로 하고 데코레이터의 결과 값을 변환
- 함수, 메서드, 제너레이터, 클래스에 적용 가능
- 데코레터 함수의 파라미터로 함수가 아닌 클래스를 받음
- 클래스 데코레이터가 복잡하고 가독성을 떨어뜨릴 수 있음
- 장점
- 코드 재사용과 DRY 원칙의 모든 이점 공유
- 작고 간단한 클래스를 생성, 데코레이터로 기능 보강
- 유지보수 시 데코레이터를 사용해 기존 로직을 훨씬 쉽게 변경
- 리펙토링이 필요한 코드
- 이벤트 클래스와 직렬화 클래스가 1:1로 매핑되어 있어서 클래스가 많아짐
- password 필드를 숨기기 위한 기능이 유연하지 않음(타클래스에서 사용 불가)
- serialize() 메서드는 모든 이벤트 클래스에 있어야 함
- 리펙토링 후 코드
- 함수, 메서드, 클래스 뿐만 아니라 제너레이터, 코루틴에도 적용 가능
- 이미 데코레이트된 객체도 제코레이트 가능
@Serialization( username=show_original, password=hide_field, ip=show_original, timestamp=format_time ) @dataclass class LoginEvent: username: str password: str ip: str timestamp: datetime - 코루틴으로 사용되는 제너레이터(227p)
- 파라미터를 갖는 데코레이터를 구현하는 방법
- 간접 참조(indirection)를 통해 새로운 레벨의 중첩 함수를 만듬
- 데코레이터를 위한 클래스를 만듬
- 일반적으로 중첩함수보다 가독성이 좋음
- 함수를 파라미터로 받아서 함수를 반환하는 함수
- 고차 함수(higher-order function)
- 파라미터를 받는 데코레이터 with 함수
- 첫번째 함수
- 파라미터를 받아서 내부 함수에 전달
- 두번째 함수
- 데코레이터가 될 함수
- 세번째 함수
- 데코레이팅의 결과를 반환하는 함수
- 첫번째 함수
- 파라미터를 받는 데코리이터 with 클래스
__call__매직 메서드는 원본 함수를 래핑하여 새로운 함수를 반환
- 우수 사례
- 파라미터 변환
- 코드 추적
- 파라미터 유효성 검사
- 재시도 로직 구현
- 일부 반복 작업을 데코레이터로 이동하여 클래스 단순화
- 파라미터의 유효성 검사
- 사전/사후 조건 강제
- 실제 함수의 실행 경로 추적
- 함수 지표 모니터링
- 함수의 실행 시간 측정
- 언제 함수가 실행되고 전달된 파라미터 로깅
#####데코레이터 부작용의 잘못된 처리
- 래핑된 함수 바깥에 추가 로직 구현
- 데코레이터를 다른 유형에 적용하려고 하면 오류 발생
- ex) 함수에 사용할 데코레이터를 메서드에 사용한 경우
- 혼용 안되는 예
- 클래스 메서드의 self 인자 부분에 문자열이 들어감
- 두번째 인자에는 아무것도 전달하지 않음
- 해결책
- 데코레이터를 클래스 객체로 구현하고 __get__메서드를 구현한 디스크립터 객체를 만듬
- 신중하게 설계되지 않은 데코레이터는 코드의 복잡성을 증가 시킴
- 재사용할 필요가 없을 경우 별개의 함수나 작은 클래스로도 충분함
- 고려사항
- 처음부터 데코레이터를 만들지 않음
- 데코레이터가 적어도 3회 이상 필요한 경우에만 구현
- 데코레이터 코드를 최소한으로 유지
- 리펙토링이 필요한 코드
- 하나 이상의 작업을 수행
- 리펙토링후 코드
- 캡슐화와 관심사의 분리
- 독립성
- 재사용성
- flask
