백엔드 스터디를 진행하면서 Decorator와 Annotation의 차이점에 대한 이야기가 나왔다.
기존 Python을 공부하면서 Decorator 패턴에 대한 내용을 본적이 있어 사용법이 Annotation과 비슷해 거의 같은 내용인줄 알았다. 이에 조금 더 자세한 내용을 찾아보았다.
Annotaion이란?
Annotation은 직역하면 주석이다 ! 하지만 우리가 기존에 알고 있는 주석과는 다른 점이 있다.
- // 이렇게 시작하는 주석은 사람에게 추가 정보를 제공한다.
- Annotaion, 즉 @으로 시작하는 주석은 특정 코드를 사용하는 프로그램에 추가 정보를 제공한다 !
즉 프로그램에 추가적인 정보를 제공하는 메타데이터라고 할 수 있다 !
- 메타데이터 : 데이터를 위한 데이터
Annotation의 역할
Annotation은 크게 3가지의 역할이 있다.
1. 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보를 제공
2. 런타임에 Reflection을 사용하여 객체 정보에 액세스
- Reflection : 자바에서 실행 중인 객체의 클래스 정보를 분석하고 이를 사용하여 객체 조작 가능.
- 클래스 정보 가져오기, 객체 생성하기, 필드 값 조작하기, 메서드 호출 가능
3. 실행시(런타임시)특정 기능을 실행하도록 정보를 제공
또한 사용자가 직접 Annotation을 만들고 적용할 수 있다. 이를 Custom Annotation이라 하는데 현재 급하게 알 필요는 없으니 나중에 필요할때 찾아보도록 하자.
Decorator Pattern이란?
- 객체지향 디자인 패턴 중 하나이다.
- 기존 객체를 변경하지 않고 동적으로 새로운 기능을 추가하는 방법을 말한다!
- 기존에 구현된 클래스에 그때그때 필요한 기능을 추가해 나가는 패턴이다.
- 객체 간 결합도를 낮추며, 확장성이 높은 구조를 만들 수 있다.
예시를 한번 들어보자.
1. 토스트를 판매할 때 칼로리를 계산해 알려주는 토스트 가게가 있다고 하자.
2. 현재 베이스 식빵으로는 일반, 호밀, 우유, 버터 식빵 4가지가 있다.
3. 재료는 햄, 야채, 치즈, 달걀 4가지가 있다.
- 앞으로 재료가 늘어날 예정이며 재료를 혼합한 토스트 종류도 늘어날 예정이다.
만약 패턴을 몰랐다면 ?
- 기본 재료를 조합해 만드는 토스트의 종류를 하위 클래스로 계속 상속에 추가 했을 것이다.
- ex. 햄야채 식빵 토스트, 달걀 호밀식빵 토스트, 야채 치즈 우유 식빵 토스트 클래스 ...
- 또는 상속 받지 않고, 하나의 클래스 안에서 처리
이렇게 할 시, 단일 책임 원칙에 위배되고 가독성을 낮춘다!
한번 이렇게 해보자.
- Toast라는 상위 클래스(abstract)를 만들고, 하위 클래스에 식빵에 종류를 둬 빵의 종류가 늘어날때 기존 코드 수정 없이 클래스만 추가하면 됨.
- 기본 재료와 복합 재료 나누기 - 기본재료(햄, 야채, 치즈, 달걀)만을 이용해 복합재료(햄야채치즈, 햄치즈달걀 등..)을 동적으로 추가
- 따라서 기본 재료는 하위 클래스에 놓고, 상위 클래스에 ToppingDecorator라는 이름의 클래스를 만듦
- 복합 재료는 기본 재료를 계속 늘려 나가는 방식으로 프로그래밍
Toast toast1 = new NormalBread(); //일반 빵 객체 생성 toast1.addTopping(new Cheese()); //상속 구조를 사용하여 객체 생성을 하는 것이 아닌, 기존 코드 수정 없이 동적 추가 toast1.addTopping(new Ham()); toast1.serve();
이렇게 결합력을 낮추고 객체를 실행하는 도중에 동적으로 확장할 수 있다.
Python에서의 Decorator는 Python에서 제공하는 추가 기능이다. 이는 함수를 장식하는 기능이다.
이는 함수를 수정하지 않은 상태에서 추가 기능을 구현할 때 사용한다 !
한번 예시를 보면서 이해해보자
def trace(func): def wrapper(): print(func.__name__, '함수 start') #기능 추가 func() #기존 함수 호출, func() == helloworld() print(func.__name__, '함수 end') #기능 추가 return wrapper @trace #Decorator 적용 def helloworld(): print('helloworld') helloworld() #함수 그대로 호출
이렇게 Java의 Annotation과 비슷하게 함수 위 @데코레이터 이렇게 작성 뒤 사용한다. 작동 순서는 다음과 같다.
1. helloworld() 호출
2. helloworld 함수 자체가 trace의 인자로 들어가 wrapper() 함수가 실행된다.
3. func == helloworld 이므로 wrapper 함수 안 func.name == helloworld, func() == helloworld()가 실행된다.위와 같이 기존 함수 수정 없이 함수에 기능을 쉽게 추가해준다.
Annotation이 Python의 Decorator와 사용법이 같고 기능이 비슷해서 헷갈렸던 것 같다. 지금까지의 정리 내용으로는 Python의 Decorator는 함수의 기능을 추가해주고, Annotation은 데이터를 위한 데이터(메타데이터)를 제공해주는 것 같다.
출처 : chatGPT, 광운대 오픈소스소프트웨어 강의 자료
안녕하세요~ 적어주신 내용 잘 읽었습니다.
좋은 자료라서 제가 발표 내용에 참고하려고 하는데 괜찮을까요? 감사합니다.