Decorator VS Annotation

이건희·2023년 3월 28일
1

백엔드 스터디를 진행하면서 Decorator와 Annotation의 차이점에 대한 이야기가 나왔다.
기존 Python을 공부하면서 Decorator 패턴에 대한 내용을 본적이 있어 사용법이 Annotation과 비슷해 거의 같은 내용인줄 알았다. 이에 조금 더 자세한 내용을 찾아보았다.

Annotation

Annotaion이란?

Annotation은 직역하면 주석이다 ! 하지만 우리가 기존에 알고 있는 주석과는 다른 점이 있다.

  • // 이렇게 시작하는 주석은 사람에게 추가 정보를 제공한다.
  • Annotaion, 즉 @으로 시작하는 주석은 특정 코드를 사용하는 프로그램에 추가 정보를 제공한다 !

즉 프로그램에 추가적인 정보를 제공하는 메타데이터라고 할 수 있다 !

  • 메타데이터 : 데이터를 위한 데이터

Annotation의 역할

Annotation은 크게 3가지의 역할이 있다.

1. 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보를 제공

2. 런타임에 Reflection을 사용하여 객체 정보에 액세스

  • Reflection : 자바에서 실행 중인 객체의 클래스 정보를 분석하고 이를 사용하여 객체 조작 가능.
    • 클래스 정보 가져오기, 객체 생성하기, 필드 값 조작하기, 메서드 호출 가능

3. 실행시(런타임시)특정 기능을 실행하도록 정보를 제공

또한 사용자가 직접 Annotation을 만들고 적용할 수 있다. 이를 Custom Annotation이라 하는데 현재 급하게 알 필요는 없으니 나중에 필요할때 찾아보도록 하자.


Decorator Pattern

Decorator Pattern이란?

  • 객체지향 디자인 패턴 중 하나이다.
  • 기존 객체를 변경하지 않고 동적으로 새로운 기능을 추가하는 방법을 말한다!
  • 기존에 구현된 클래스에 그때그때 필요한 기능을 추가해 나가는 패턴이다.
  • 객체 간 결합도를 낮추며, 확장성이 높은 구조를 만들 수 있다.

예시를 한번 들어보자.
1. 토스트를 판매할 때 칼로리를 계산해 알려주는 토스트 가게가 있다고 하자.
2. 현재 베이스 식빵으로는 일반, 호밀, 우유, 버터 식빵 4가지가 있다.
3. 재료는 햄, 야채, 치즈, 달걀 4가지가 있다.

  • 앞으로 재료가 늘어날 예정이며 재료를 혼합한 토스트 종류도 늘어날 예정이다.

만약 패턴을 몰랐다면 ?

  • 기본 재료를 조합해 만드는 토스트의 종류를 하위 클래스로 계속 상속에 추가 했을 것이다.
    • ex. 햄야채 식빵 토스트, 달걀 호밀식빵 토스트, 야채 치즈 우유 식빵 토스트 클래스 ...
  • 또는 상속 받지 않고, 하나의 클래스 안에서 처리

이렇게 할 시, 단일 책임 원칙에 위배되고 가독성을 낮춘다!


한번 이렇게 해보자.

  1. Toast라는 상위 클래스(abstract)를 만들고, 하위 클래스에 식빵에 종류를 둬 빵의 종류가 늘어날때 기존 코드 수정 없이 클래스만 추가하면 됨.
  2. 기본 재료와 복합 재료 나누기 - 기본재료(햄, 야채, 치즈, 달걀)만을 이용해 복합재료(햄야채치즈, 햄치즈달걀 등..)을 동적으로 추가
  3. 따라서 기본 재료는 하위 클래스에 놓고, 상위 클래스에 ToppingDecorator라는 이름의 클래스를 만듦
  4. 복합 재료는 기본 재료를 계속 늘려 나가는 방식으로 프로그래밍
      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, 광운대 오픈소스소프트웨어 강의 자료

profile
광운대학교 정보융합학부 학생입니다.

1개의 댓글

안녕하세요~ 적어주신 내용 잘 읽었습니다.
좋은 자료라서 제가 발표 내용에 참고하려고 하는데 괜찮을까요? 감사합니다.

답글 달기